Mbed OS Reference
Loading...
Searching...
No Matches
SPI.h
1/* mbed Microcontroller Library
2 * Copyright (c) 2006-2019 ARM Limited
3 * SPDX-License-Identifier: Apache-2.0
4 *
5 * Licensed under the Apache License, Version 2.0 (the "License");
6 * you may not use this file except in compliance with the License.
7 * You may obtain a copy of the License at
8 *
9 * http://www.apache.org/licenses/LICENSE-2.0
10 *
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
16 */
17#ifndef MBED_SPI_H
18#define MBED_SPI_H
19
20#include "platform/platform.h"
21
22#if DEVICE_SPI || defined(DOXYGEN_ONLY)
23
24#include "rtos/Mutex.h"
25#include "hal/spi_api.h"
26#include "drivers/DigitalOut.h"
27#include "platform/SingletonPtr.h"
28#include "platform/NonCopyable.h"
29#include "platform/CacheAlignedBuffer.h"
30
31#if defined MBED_CONF_DRIVERS_SPI_COUNT_MAX && DEVICE_SPI_COUNT > MBED_CONF_DRIVERS_SPI_COUNT_MAX
32#define SPI_PERIPHERALS_USED MBED_CONF_DRIVERS_SPI_COUNT_MAX
33#elif defined DEVICE_SPI_COUNT
34#define SPI_PERIPHERALS_USED DEVICE_SPI_COUNT
35#else
36/* Backwards compatibility with HALs not providing DEVICE_SPI_COUNT */
37#define SPI_PERIPHERALS_USED 1
38#endif
39
40#if DEVICE_SPI_ASYNCH
41#include "platform/CThunk.h"
42#include "hal/dma_api.h"
43#include "platform/CircularBuffer.h"
44#include "platform/Callback.h"
45#include "platform/Transaction.h"
46#include "rtos/EventFlags.h"
47#endif
48
49namespace mbed {
50/**
51 * \defgroup drivers_SPI SPI class
52 * \ingroup drivers-public-api-spi
53 * @{
54 */
55
56struct use_gpio_ssel_t { };
57const use_gpio_ssel_t use_gpio_ssel;
58
59/**
60 * @brief An %SPI Master, used for communicating with %SPI slave devices.
61 *
62 * The default format is set to 8-bits, mode 0, and a clock frequency of 1MHz.
63 *
64 * @note Synchronization level: Thread safe
65 *
66 * %SPI allows you to transfer data to and from peripheral devices using single-word transfers, transactions,
67 * or an asynchronous API.
68 *
69 * Here's how to talk to a chip using the single-word API:
70 * @code{.cpp}
71 * #include "mbed.h"
72 *
73 * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, use_gpio_ssel)
74 *
75 * int main() {
76 * device.format(8, 0);
77 *
78 * device.lock();
79 * device.select();
80 * int response = device.write(0x0A);
81 * int response2 = device.write(0x0B);
82 * device.deselect();
83 * device.unlock();
84 * }
85 * @endcode
86 *
87 * And here's how to do the same thing using a transaction:
88 * @code
89 * #include "mbed.h"
90 *
91 * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, use_gpio_ssel)
92 *
93 * int main() {
94 * device.format(8, 0);
95 *
96 * uint8_t command[2] = {0x0A, 0x0B};
97 * uint8_t response[2];
98 * int result = device.write(command, sizeof(command), response, sizeof(response));
99 * }
100 * @endcode
101 *
102 * <h1>Hardware vs Software Chip Selects</h1>
103 * <p>Most ARM chips have specific pins marked as "hardware chip selects". This means that they are connected
104 * to the %SPI peripheral and are automatically brought low by hardware when data is sent. However, chips
105 * often only have only one pin for each SPI bus that can be used as a hardware chip select. If you wish to
106 * use multiple peripheral devices with one SPI bus, or just don't have access to the HW CS pin, you must use the
107 * %SPI object in "GPIO chip select" mode.</p>
108 *
109 * <p>To use GPIO CS mode, simply pass the CS pin as the 4th constructor parameter, then pass the
110 * special constant \c use_gpio_ssel as the 5th parameter. This puts the object in GPIO mode, where
111 * it will operate the CS line as a regular GPIO pin before and after doing an SPI transfer. This mode
112 * is marginally slower than HW CS mode, but otherwise should offer the same functionality. In fact,
113 * since the pin mapping is more flexible, it may be advisable to use GPIO CS mode by default.</p>
114 *
115 * \warning It is not recommended to control the CS line using a separate DigitalOut instance!
116 * This was needed in very old Mbed versions but should now be considered a legacy practice.
117 * Not only does it make it difficult to use the asynchronous API, but it can also lead to corner
118 * cases which corrupt data. The CS line, whether done through GPIO or HW, should always be managed through
119 * the SPI class.
120 *
121 * <h1>Sharing a Bus</h1>
122 * <p>Multiple %SPI devices may share the same physical bus, so long as each has its own dedicated chip select
123 * (CS) pin. To implement this sharing, each chip's driver should create its own instance of the SPI class, passing
124 * the same MOSI, MISO, and SCLK pins but a different CS pin. Mbed OS will internally share the %SPI hardware
125 * between these objects. Note that this is <i>completely different</i> from how the I2C class handles
126 * sharing.</p>
127 *
128 * <h1>Frame/Word Size</h1>
129 * <p>Mbed OS supports configuration of the %SPI frame size, also known as the word size, which controls how
130 * many bits are sent in one transfer operation (one call to SPI::write()). This parameter should match
131 * the "register size" of the %SPI peripheral that you are talking to. For example, if you're working with a chip
132 * which uses 16-bit registers, you should set the frame size to 16 using SPI::format(). Some Mbed devices also
133 * support 32-bit frames -- use the \c DEVICE_SPI_32BIT_WORDS feature macro to test if yours does.</p>
134 *
135 * <p>The frame size controls the effective width of data written and read from the chip. For example, if you set
136 * frame size to 8, SPI::write(int) will take one byte and return one byte, but if you set it to 16, SPI::write(int)
137 * will take a 16 bit value and return a 16 bit value. You can also do transactions with frame sizes other
138 * than 8. Just be sure to pass the length in bytes, not words!</p>
139 *
140 * <p>It should be noted that changing the frame size can perform an apparent "endian swap" on data being
141 * transmitted. For example, suppose you have the 32-bit integer 0x01020408. On a little-endian processor,
142 * this will be encoded with the LSByte <i>first</i> in memory: <tt>08 04 02 01</tt>. If you send that
143 * integer using one-byte word size, it will appear as such. Consider the following example:</p>
144 * @code{.cpp}
145 * spi.format(8, 0);
146 * uint32_t myInteger = 0x01020408;
147 * spi.write(reinterpret_cast<const char *>(&myInteger), sizeof(myInteger), nullptr, 0);
148 * @endcode
149 *
150 * <p>If you ran this code, then used a logic analyzer to view the bytes on the MOSI line, it would show bytes
151 * matching the layout of the integer in memory:</p>
152 * <pre>
153 * MOSI -> 08 04 02 01
154 * </pre>
155 *
156 * <p>But what about if you used a 32-bit frame size?</p>
157 * @code{.cpp}
158 * spi.format(32, 0);
159 * uint32_t myInteger = 0x01020408;
160 * spi.write<uint32_t>(&myInteger, sizeof(myInteger), nullptr, 0);
161 * @endcode
162 *
163 * <p>In this case, the complete 32-bit integer is sent as a single unit, from its MSBit to its LSBit, without
164 * breaking it into bytes. This will send the data in an order different from the order in memory. Viewed as
165 * bytes, it would look like:</p>
166 *
167 * <pre>
168 * MOSI -> 01 02 04 08
169 * </pre>
170 *
171 * <p>But viewed by a peripheral chip which uses 32-bit SPI words, it would look like:</p>
172 *
173 * <pre>
174 * MOSI -> 0x01020408
175 * </pre>
176 *
177 * <p>When viewed as bytes, it's almost as if you did an endian swap on the data before sending it,
178 * but in fact it's standard %SPI behavior when using frame sizes greater than one byte. This same rule
179 * applies to receiving data, so be sure to check examples in the datasheet to determine what frame
180 * size to use and whether byte swapping is needed when working with an external chip.</p>
181 *
182 * \note Some Mbed targets support frame sizes that are not standard integer sizes, e.g. 4 bits, 7 bits, or
183 * 24 bits. However, the behavior of these frame sizes is currently not tested, and you may need to test what works or
184 * inspect your target's SPI driver code. More work is needed to make these consistent. When available, using these frame sizes
185 * requires writing each word to be transmitted into the next-largest C integer type. For example, to send 24-bit frames, you
186 * would create an array of uint32_ts and write each 24-bit integer into its own uint32_t.
187 * Then you would pass in the byte length of the array (number of frames * 4, NOT number of frames * 3) to the SPI driver.
188 *
189 * <h1>Asynchronous API</h1>
190 * <p>On many processors, Mbed OS also supports asynchronous %SPI. This feature allows you to run %SPI
191 * transfers completely in the background, while other threads execute in the foreground. This can
192 * be extremely useful if you need to send large amounts of data over the %SPI bus but don't want to
193 * block your main thread for ages. To see if your processor supports async %SPI, look for the
194 * DEVICE_SPI_ASYNCH macro.</p>
195 *
196 * <p>The asynchronous API has two different modes: nonblocking (where your thread can keep running, and
197 * the transfer calls a callback when finished) and blocking (where your thread blocks for the duration of
198 * the transfer but others can execute). Here's a sample of how to send the same data as above
199 * using the blocking async API:</p>
200 *
201 * <p>Note that when using the asynchronous API, you must use the CacheAlignedBuffer class when declaring the
202 * receive buffer. This is because some processors' async SPI implementations require the received buffer to
203 * be at an address which is aligned to the processor cache line size. CacheAlignedBuffer takes care of this
204 * for you and provides functions (data(), begin(), end()) to access the underlying data in the buffer.</p>
205 *
206 * @code
207 * #include "mbed.h"
208 *
209 * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, use_gpio_ssel)
210 *
211 * int main() {
212 * device.format(8, 0);
213 *
214 * uint8_t command[2] = {0x0A, 0x0B};
215 * CacheAlignedBuffer<uint8_t, 2> response;
216 * int result = device.transfer_and_wait(command, sizeof(command), response, sizeof(command));
217 * }
218 * @endcode
219 *
220 * <p>This code will cause the data in \c command to be sent to the device and the response to be received into
221 * \c response . During the transfer, the current thread is paused, but other threads can execute.
222 * The non-blocking API does not pause the current thread, but is a bit more complicated to use.
223 * See the SPI::transfer_and_wait() implementation in SPI.cpp for an example.</p>
224 *
225 * <h3>Async: DMA vs Interrupts</h3>
226 * <p>Some processors only provide asynchronous %SPI via interrupts, some only support DMA, and some offer both.
227 * Using interrupts is simpler and generally doesn't require additional resources from the chip, however,
228 * some CPU time will be spent servicing the interrupt while the transfer is running. This can become very
229 * performance-intensive -- on some chips, running async %SPI at frequencies of just a few MHz can be enough
230 * to make the interrupt use 100% of CPU time. In contrast, DMA can require additional resources to be allocated,
231 * (e.g. chips with few DMA channels might only support DMA on one or two %SPI busses at a time), but
232 * can run the bus at full speed without any CPU overhead. Generally, DMA should be preferred if available,
233 * especially if medium to fast bus speeds are needed.</p>
234 *
235 * <p>Consult your chip documentation and the Mbed port docs for your target to find out what is needed to enable
236 * DMA support. For example, for STMicro targets, see
237 * <a href="https://github.com/mbed-ce/mbed-os/wiki/STM32-DMA-SPI-Support">here</a>.To select DMA or interrupts,
238 * use the SPI::set_dma_usage() function. By default, interrupt %SPI will be used unless you change the
239 * setting.</p>
240 *
241 * <h3>Async: Queueing</h3>
242 * <p>The async %SPI system supports an optional transaction queueing mechanism. When this is enabled,
243 * Mbed will allow multiple transactions to be queued up on a single bus, and will execute each one
244 * and deliver the appropriate callback in series. This is mainly useful for the non-blocking
245 * async api (SPI::transfer()), though you can also use it with the blocking API by having multiple
246 * threads call it at once.</p>
247 *
248 * <p>The transaction queue size defaults to 2 on most devices, but you can change that using the
249 * \c drivers.spi_transaction_queue_len option, e.g.</p>
250 * \code{.json}
251 * {
252 * "target_overrides": {
253 * "*": {
254 * "drivers.spi_transaction_queue_len": 3
255 * }
256 * }
257 * }
258 * \endcode
259 *
260 * <p>To save a little bit of memory, you can also set the queue length to 0 to disable the queueing mechanism.</p>
261 *
262 * \warning Currently, the value set by SPI::set_default_write_value() is
263 * <a href="https://github.com/ARMmbed/mbed-os/issues/13941">not respected</a> by the asynchronous %SPI
264 * code. This needs to be fixed.
265 */
266class SPI : private NonCopyable<SPI> {
267
268public:
269
270 /** Create a SPI master connected to the specified pins.
271 *
272 * @note This constructor passes the SSEL pin selection to the target HAL.
273 * Not all targets support SSEL, so this cannot be relied on in portable code.
274 * Portable code should use the alternative constructor that uses GPIO
275 * for SSEL.
276 *
277 * @note You can specify mosi or miso as NC if not used.
278 *
279 * @param mosi SPI Master Out, Slave In pin.
280 * @param miso SPI Master In, Slave Out pin.
281 * @param sclk SPI Clock pin.
282 * @param ssel SPI Chip Select pin.
283 */
284 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC);
285
286 /** Create a SPI master connected to the specified pins.
287 *
288 * @note This constructor manipulates the SSEL pin as a GPIO output
289 * using a DigitalOut object. This should work on any target, and permits
290 * the use of select() and deselect() methods to keep the pin asserted
291 * between transfers.
292 *
293 * @note You can specify mosi or miso as NC if not used.
294 *
295 * @param mosi SPI Master Out, Slave In pin.
296 * @param miso SPI Master In, Slave Out pin.
297 * @param sclk SPI Clock pin.
298 * @param ssel SPI Chip Select pin.
299 */
300 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel, use_gpio_ssel_t);
301
302 /** Create a SPI master connected to the specified pins.
303 *
304 * @note This constructor passes the SSEL pin selection to the target HAL.
305 * Not all targets support SSEL, so this cannot be relied on in portable code.
306 * Portable code should use the alternative constructor that uses GPIO
307 * for SSEL.
308 *
309 * @note You can specify mosi or miso as NC if not used.
310 *
311 * @param static_pinmap reference to structure which holds static pinmap.
312 */
313 SPI(const spi_pinmap_t &static_pinmap);
314 SPI(const spi_pinmap_t &&) = delete; // prevent passing of temporary objects
315
316 /** Create a SPI master connected to the specified pins.
317 *
318 * @note This constructor manipulates the SSEL pin as a GPIO output
319 * using a DigitalOut object. This should work on any target, and permits
320 * the use of select() and deselect() methods to keep the pin asserted
321 * between transfers.
322 *
323 * @note You can specify mosi or miso as NC if not used.
324 *
325 * @param static_pinmap reference to structure which holds static pinmap.
326 * @param ssel SPI Chip Select pin.
327 */
328 SPI(const spi_pinmap_t &static_pinmap, PinName ssel);
329 SPI(const spi_pinmap_t &&, PinName) = delete; // prevent passing of temporary objects
330
331 virtual ~SPI();
332
333 /**
334 * @brief Configure the data transmission format.
335 *
336 * @param bits Number of bits per %SPI frame (4 - 32, target dependent).
337 * @param mode Clock polarity and phase mode (0 - 3).
338 *
339 * @code
340 * mode | POL PHA
341 * -----+--------
342 * 0 | 0 0
343 * 1 | 0 1
344 * 2 | 1 0
345 * 3 | 1 1
346 * @endcode
347 */
348 void format(int bits, int mode = 0);
349
350 /**
351 * @brief Set the %SPI bus clock frequency.
352 *
353 * @param hz Clock frequency in Hz (default = 1MHz).
354 */
355 void frequency(int hz = 1000000);
356
357 /**
358 * @brief Write to the %SPI Slave and return the response.
359 *
360 * @param value Data to be sent to the SPI slave. The number of significant bits in this
361 * value depend on the \c bits parameter to format().
362 *
363 * @return Response from the %SPI slave. The number of significant bits in this
364 * value depend on the \c bits parameter to format().
365 */
366 virtual int write(int value);
367
368 /**
369 * @brief Write to the SPI Slave and obtain the response.
370 *
371 * The total number of bytes sent and received will be the maximum of
372 * tx_length and rx_length. The bytes written will be padded with the
373 * value set via set_default_write_value().
374 *
375 * @note Even if the word size / bits per frame is not 8, \c rx_length and \c tx_length
376 * still count bytes of input data, not numbers of words. So, for example, if you want to send 1 word of
377 * 32-bit data, tx_length needs to be 4.
378 *
379 * @param tx_buffer Pointer to the byte-array of data to write to the device.
380 * @param tx_length Number of bytes to write, may be zero.
381 * @param rx_buffer Pointer to the byte-array of data to read from the device.
382 * @param rx_length Number of bytes to read, may be zero.
383 * @return
384 * The number of bytes written and read from the device (as an int). This is
385 * maximum of tx_length and rx_length.
386 */
387 int write(const uint8_t *tx_buffer, int tx_length, uint8_t *rx_buffer, int rx_length)
388 {
389 return write_internal(tx_buffer, tx_length, rx_buffer, rx_length);
390 }
391
392 // Overloads of the above to support passing other integer sizes
393 int write(const int8_t *tx_buffer, int tx_length, int8_t *rx_buffer, int rx_length)
394 {
395 return write_internal(tx_buffer, tx_length, rx_buffer, rx_length);
396 }
397 // crazily, 'char' is not implicitly unsigned OR signed, so it needs its own case here
398 int write(const char *tx_buffer, int tx_length, char *rx_buffer, int rx_length)
399 {
400 return write_internal(tx_buffer, tx_length, rx_buffer, rx_length);
401 }
402 int write(const uint16_t *tx_buffer, int tx_length, uint16_t *rx_buffer, int rx_length)
403 {
404 return write_internal(tx_buffer, tx_length, rx_buffer, rx_length);
405 }
406 int write(const uint32_t *tx_buffer, int tx_length, uint32_t *rx_buffer, int rx_length)
407 {
408 return write_internal(tx_buffer, tx_length, rx_buffer, rx_length);
409 }
410
411
412 /**
413 * @brief Acquire exclusive access to this SPI bus.
414 *
415 * This function blocks until the chosen SPI peripheral is not being used by any other SPI objects.
416 * Careful -- if other code leaves the bus locked, this could block forever!
417 */
418 virtual void lock(void);
419
420 /**
421 * @brief Release exclusive access to this SPI bus.
422 *
423 * This allows other code to do operations using the SPI peripheral.
424 */
425 virtual void unlock(void);
426
427 /**
428 * @brief Assert the Slave Select line and acquire exclusive access to this SPI bus.
429 *
430 * The slave select line will remain selected (low) for all following operations until
431 * you call #deselect() on this instance. This allows you to string together multiple SPI transactions
432 * as if they were a single operation (from the perspective of peripheral chips).
433 *
434 * If use_gpio_ssel was not passed to the constructor, manual control of the SSEL line is not possible,
435 * and this function behaves identically to #lock().
436 *
437 * Like #lock(), this function will block until exclusive access can be acquired.
438 *
439 * \warning Do not call this function while an asynchronous transfer is in progress,
440 * as undefined behavior can occur.
441 */
442 void select(void);
443
444 /**
445 * @brief Deassert the Slave Select line, releasing exclusive access to this SPI bus.
446 *
447 * If use_gpio_ssel was not passed to the constructor, manual control of the SSEL line is not possible,
448 * and this function behaves identically to #unlock().
449 *
450 * \warning Do not call this function while an asynchronous transfer is in progress,
451 * as undefined behavior can occur.
452 */
453 void deselect(void);
454
455 /** Set default write data.
456 * SPI requires the master to send some data during a read operation.
457 * Different devices may require different default byte values.
458 * For example: A SD Card requires default bytes to be 0xFF.
459 *
460 * @param data Default character to be transmitted during a read operation.
461 */
462 void set_default_write_value(char data);
463
464#if DEVICE_SPI_ASYNCH
465
466 /**
467 * @brief Start non-blocking %SPI transfer.
468 *
469 * This function locks the deep sleep until any event has occurred.
470 *
471 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
472 * the default %SPI value is sent.
473 * @param tx_length The length of TX buffer in bytes.
474 * @param rx_buffer The RX buffer which is used for received data. Rather than a C array, a CacheAlignedBuffer
475 * structure must be passed so that cache alignment can be handled for data received from DMA.
476 * May be nullptr if rx_length is 0.
477 * @param rx_length The length of RX buffer in bytes.
478 * @param callback The event callback function.
479 * @param event The logical OR of events to subscribe to. May be #SPI_EVENT_ALL, or some combination
480 * of the flags #SPI_EVENT_ERROR, #SPI_EVENT_COMPLETE, or #SPI_EVENT_RX_OVERFLOW
481 *
482 * @return Operation result (integer)
483 * @retval 0 If the transfer has started.
484 * @retval -1 if the transfer could not be enqueued (increase drivers.spi_transaction_queue_len option)
485 */
486 int transfer(const uint8_t *tx_buffer, int tx_length, CacheAlignedBuffer<uint8_t> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
487 {
488 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
489 return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
490 }
491
492 // Overloads of the above to support passing other integer sizes and null Rx buffers
493 int transfer(const uint8_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
494 {
495 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
496 }
497 int transfer(const int8_t *tx_buffer, int tx_length, CacheAlignedBuffer<int8_t> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
498 {
499 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
500 return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
501 }
502 int transfer(const int8_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
503 {
504 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
505 }
506 // crazily, 'char' is not implicitly unsigned OR signed, so it needs its own case here
507 int transfer(const char *tx_buffer, int tx_length, CacheAlignedBuffer<char> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
508 {
509 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
510 return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
511 }
512 int transfer(const char *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
513 {
514 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
515 }
516 int transfer(const uint16_t *tx_buffer, int tx_length, CacheAlignedBuffer<uint16_t> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
517 {
518 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(uint16_t)));
519 return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
520 }
521 int transfer(const uint16_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
522 {
523 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
524 }
525 int transfer(const uint32_t *tx_buffer, int tx_length, CacheAlignedBuffer<uint32_t> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
526 {
527 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(uint32_t)));
528 return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
529 }
530 int transfer(const uint32_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
531 {
532 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
533 }
534
535 /**
536 * @brief Start %SPI transfer and wait until it is complete.
537 *
538 * Like the transactional API this blocks the current thread,
539 * however all work is done in the background and other threads may execute.
540 *
541 * As long as there is space, this function will enqueue the transfer request onto the peripheral,
542 * and block until it is done.
543 *
544 * Internally, the chip vendor may implement this function using either DMA or interrupts.
545 *
546 * @param tx_buffer The TX buffer with data to be transferred. May be nullptr if tx_length is 0.
547 * @param tx_length The length of TX buffer in bytes. If 0, the default %SPI data value is sent when receiving data.
548 * @param rx_buffer The RX buffer which is used for received data. Rather than a C array, a CacheAlignedBuffer
549 * structure must be passed so that cache alignment can be handled for data received from DMA.
550 * May be nullptr if rx_length is 0.
551 * @param rx_length The length of RX buffer in bytes If 0, no reception is done.
552 * @param timeout timeout value. Use #rtos::Kernel::wait_for_u32_forever to wait forever (the default).
553 *
554 * @return Operation result (integer)
555 * @retval -1 if the transfer could not be enqueued (increase drivers.spi_transaction_queue_len option)
556 * @retval 1 on timeout
557 * @retval 2 on other error
558 * @retval 0 on success
559 */
560 int transfer_and_wait(const uint8_t *tx_buffer, int tx_length, CacheAlignedBuffer<uint8_t> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
561 {
562 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
563 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
564 }
565
566 // Overloads of the above to support passing other integer sizes and null Rx buffers
567 int transfer_and_wait(const uint8_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
568 {
569 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
570 }
571 int transfer_and_wait(const int8_t *tx_buffer, int tx_length, CacheAlignedBuffer<int8_t> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
572 {
573 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
574 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
575 }
576 int transfer_and_wait(const int8_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
577 {
578 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
579 }
580 // crazily, 'char' is not implicitly unsigned OR signed, so it needs its own case here
581 int transfer_and_wait(const char *tx_buffer, int tx_length, CacheAlignedBuffer<char> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
582 {
583 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
584 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
585 }
586 int transfer_and_wait(const char *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
587 {
588 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
589 }
590 int transfer_and_wait(const uint16_t *tx_buffer, int tx_length, CacheAlignedBuffer<uint16_t> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
591 {
592 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(uint16_t)));
593 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
594 }
595 int transfer_and_wait(const uint16_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
596 {
597 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
598 }
599 int transfer_and_wait(const uint32_t *tx_buffer, int tx_length, CacheAlignedBuffer<uint32_t> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
600 {
601 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity() * sizeof(uint32_t)));
602 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
603 }
604 int transfer_and_wait(const uint32_t *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
605 {
606 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
607 }
608
609 /**
610 * @brief Abort the on-going SPI transfer, if any, and continue with transfers in the queue, if any.
611 *
612 * @note If a transfer is aborted, its callback will not be called at all.
613 */
615
616 /**
617 * @brief Clear the queue of transfers.
618 *
619 * If a transfer is currently active, it will continue until complete.
620 */
622
623 /**
624 * @brief Clear the queue of transfers and abort any on-going transfer.
625 */
627
628 /** Configure DMA usage suggestion for non-blocking transfers.
629 *
630 * @param usage The usage DMA hint for peripheral.
631 *
632 * @return Result of the operation.
633 * @retval 0 The usage was set.
634 * @retval -1 Usage cannot be set as there is an ongoing transaction.
635 */
637
638#if !defined(DOXYGEN_ONLY)
639protected:
640
641 /** SPI interrupt handler.
642 */
643 void irq_handler_asynch(void);
644
645 /** Start the transfer or put it on the queue.
646 *
647 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
648 * the default SPI value is sent
649 * @param tx_length The length of TX buffer in bytes.
650 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
651 * received data are ignored. This buffer is guaranteed to be cache aligned
652 * if the MCU has a cache.
653 * @param rx_length The length of RX buffer in bytes.
654 * @param callback The event callback function.
655 * @param event The event mask of events to modify.
656 *
657 * @return Operation success.
658 * @retval 0 A transfer was started or added to the queue.
659 * @retval -1 Transfer can't be added because queue is full.
660 */
661 int transfer_internal(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, const event_callback_t &callback, int event);
662
663 /**
664 * @brief Start %SPI transfer and wait until it is complete.
665 *
666 * Like the transactional API this blocks the current thread,
667 * however all work is done in the background and other threads may execute.
668 *
669 * As long as there is space, this function will enqueue the transfer request onto the peripheral,
670 * and block until it is done.
671 *
672 * Internally, the chip vendor may implement this function using either DMA or interrupts.
673 *
674 * @param tx_buffer The TX buffer with data to be transferred. May be nullptr if tx_length is 0.
675 * @param tx_length The length of TX buffer in bytes. If 0, no transmission is done.
676 * @param rx_buffer The RX buffer, which is used for received data. May be nullptr if tx_length is 0.
677 * This buffer is guaranteed to be cache aligned if the MCU has a cache.
678 * @param rx_length The length of RX buffer in bytes If 0, no reception is done.
679 * @param timeout timeout value. Use #rtos::Kernel::wait_for_u32_forever to wait forever (the default).
680 *
681 * @return Operation result (integer)
682 * @retval -1 if the transfer could not be enqueued (increase drivers.spi_transaction_queue_len option)
683 * @retval 1 on timeout
684 * @retval 2 on other error
685 * @retval 0 on success
686 */
687 int transfer_and_wait_internal(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout);
688
689 /** Put a transfer on the transfer queue.
690 *
691 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
692 * the default SPI value is sent.
693 * @param tx_length The length of TX buffer in bytes.
694 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
695 * received data are ignored.
696 * @param rx_length The length of RX buffer in bytes.
697 * @param bit_width The buffers element width in bits.
698 * @param callback The event callback function.
699 * @param event The event mask of events to modify.
700 *
701 * @return Operation success.
702 * @retval 0 A transfer was added to the queue.
703 * @retval -1 Transfer can't be added because queue is full.
704 */
705 int queue_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event);
706
707 /** Configure a callback, SPI peripheral, and initiate a new transfer.
708 *
709 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
710 * the default SPI value is sent.
711 * @param tx_length The length of TX buffer in bytes.
712 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
713 * received data are ignored.
714 * @param rx_length The length of RX buffer in bytes.
715 * @param bit_width The buffers element width.
716 * @param callback The event callback function.
717 * @param event The event mask of events to modify.
718 */
719 void start_transfer(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, unsigned char bit_width, const event_callback_t &callback, int event);
720
721private:
722 /** Lock deep sleep only if it is not yet locked */
723 void lock_deep_sleep();
724
725 /** Unlock deep sleep in case it is locked */
726 void unlock_deep_sleep();
727
728
729#if MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
730 /** Start a new transaction.
731 *
732 * @param data Transaction data.
733 */
734 void start_transaction(transaction_t *data);
735
736 /** Dequeue a transaction and start the transfer if there was one pending.
737 */
738 void dequeue_transaction();
739
740#endif // MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
741#endif // !defined(DOXYGEN_ONLY)
742#endif // DEVICE_SPI_ASYNCH
743
744#if !defined(DOXYGEN_ONLY)
745protected:
746#ifdef DEVICE_SPI_COUNT
747 // HAL must have defined this as a global enum
748 typedef ::SPIName SPIName;
749#else
750 // HAL may or may not have defined it - use a local definition
751 enum SPIName { GlobalSPI };
752#endif
753
754 // All members of spi_peripheral_s must be initialized to make the structure
755 // constant-initialized, and hence able to be omitted by the linker,
756 // as SingletonPtr now relies on C++ constant-initialization. (Previously it
757 // worked through C++ zero-initialization). And all the constants should be zero
758 // to ensure it stays in the actual zero-init part of the image if used, avoiding
759 // an initialized-data cost.
760 struct spi_peripheral_s {
761 /* Internal SPI name identifying the resources. */
762 SPIName name = SPIName(0);
763 /* Internal SPI object handling the resources' state. */
764 spi_t spi{};
765 /* Used by lock and unlock for thread safety */
767 /* Current user of the SPI, if any. */
768 SPI *owner = nullptr;
769 /* Number of SPI objects that have been created which reference this peripheral. */
770 uint8_t numUsers = 0;
771 /* True iff anyone has ever called spi_init() / spi_init_direct() for this peripheral */
772 bool initialized = false;
773#if DEVICE_SPI_ASYNCH && MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
774 /* Queue of pending transfers */
775 SingletonPtr<CircularBuffer<Transaction<SPI>, MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN> > transaction_buffer;
776#endif
777 };
778
779 // holds spi_peripheral_s per peripheral on the device.
780 // Drawback: it costs ram size even if the device is not used, however
781 // application can limit the allocation via JSON.
782 static spi_peripheral_s _peripherals[SPI_PERIPHERALS_USED];
783 static int _peripherals_used;
784
785 // Holds the reference to the associated peripheral.
786 spi_peripheral_s *_peripheral;
787
788#if DEVICE_SPI_ASYNCH
789 /* Interrupt */
790 CThunk<SPI> _irq;
791 /* Interrupt handler callback */
792 event_callback_t _callback;
793 /* Current preferred DMA mode @see dma_api.h */
794 DMAUsage _usage;
795 /* Current sate of the sleep manager */
796 bool _deep_sleep_locked;
797 /* Whether an async transfer is currently in progress. Specifically, this is true
798 * iff start_transfer() has been called and the chip has been selected but irq_handler_asynch()
799 * has NOT been called yet. */
800 volatile bool _transfer_in_progress = false;
801
802 // If there is a transfer in progress, this indicates whether it used DMA and therefore requires a cache
803 // flush at the end
804 bool _transfer_in_progress_uses_dma;
805
806#if __DCACHE_PRESENT
807 // These variables store the location and length in bytes of the Rx buffer if an async transfer
808 // is in progress. They are used for invalidating the cache after the transfer completes.
809 void *_transfer_in_progress_rx_buffer;
810 size_t _transfer_in_progress_rx_len;
811#endif
812
813 /* Event flags used for transfer_and_wait() */
814 rtos::EventFlags _transfer_and_wait_flags;
815#endif // DEVICE_SPI_ASYNCH
816
817 // Configuration.
818 PinName _mosi;
819 PinName _miso;
820 PinName _sclk;
821 PinName _hw_ssel;
822
823 // The Slave Select GPIO if we're doing it ourselves.
824 DigitalOut _sw_ssel;
825
826 /* Size of the SPI frame */
827 int _bits;
828 /* Clock polarity and phase */
829 int _mode;
830 /* Clock frequency */
831 int _hz;
832 /* Default character used for NULL transfers */
833 char _write_fill;
834 /* Select count to handle re-entrant selection */
835 volatile uint8_t _select_count = 0;
836 /* Static pinmap data */
837 const spi_pinmap_t *_static_pinmap;
838 /* SPI peripheral name */
839 SPIName _peripheral_name;
840 /* Pointer to spi init function */
841 void (*_init_func)(SPI *);
842
843private:
844
845 /**
846 * Get a reference to the mutex used to protect the peripherals array.
847 */
848 rtos::Mutex &_get_peripherals_mutex();
849
850 void _do_construct();
851
852 /** Private acquire function without locking/unlocking.
853 * Implemented in order to avoid duplicate locking and boost performance.
854 */
855 void _acquire(void);
856 void _set_ssel(int);
857
858 /** Private lookup in the static _peripherals table.
859 * Should be called with _peripherals_mutex locked.
860 */
861 static spi_peripheral_s *_lookup(SPIName name);
862
863 /** Allocate an entry in the static _peripherals table.
864 * Should be called with _peripherals_mutex locked.
865 */
866 static spi_peripheral_s *_alloc();
867
868 /// Deallocate the given peripheral.
869 /// Should be called with _peripherals_mutex locked.
870 static void _dealloc(spi_peripheral_s *peripheral);
871
872 static void _do_init(SPI *obj);
873 static void _do_init_direct(SPI *obj);
874
875 /**
876 * @brief Write to the SPI Slave and obtain the response.
877 *
878 * The total number of bytes sent and received will be the maximum of
879 * tx_length and rx_length. The bytes written will be padded with the
880 * value 0xff.
881 *
882 * Note: Even if the word size / bits per frame is not 8, \c rx_length and \c tx_length
883 * still count bytes of input data, not numbers of words.
884 *
885 * @param tx_buffer Pointer to the byte-array of data to write to the device.
886 * @param tx_length Number of bytes to write, may be zero.
887 * @param rx_buffer Pointer to the byte-array of data to read from the device.
888 * @param rx_length Number of bytes to read, may be zero.
889 * @return
890 * The number of bytes written and read from the device. This is
891 * maximum of tx_length and rx_length.
892 */
893 virtual int write_internal(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length);
894
895
896#endif //!defined(DOXYGEN_ONLY)
897};
898
899/** @}*/
900
901} // namespace mbed
902
903#endif // DEVICE_SPI || DOXYGEN_ONLY
904
905#endif // MBED_SPI_H
Class for created a pointer with data bound to it.
Definition CThunk.h:45
CacheAlignedBuffer is used by Mbed in locations where we need a cache-aligned buffer.
Prevents generation of copy constructor and copy assignment operator in derived classes.
An SPI Master, used for communicating with SPI slave devices.
Definition SPI.h:266
SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel, use_gpio_ssel_t)
Create a SPI master connected to the specified pins.
void deselect(void)
Deassert the Slave Select line, releasing exclusive access to this SPI bus.
void set_default_write_value(char data)
Set default write data.
int write(const uint8_t *tx_buffer, int tx_length, uint8_t *rx_buffer, int rx_length)
Write to the SPI Slave and obtain the response.
Definition SPI.h:387
SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel=NC)
Create a SPI master connected to the specified pins.
SPI(const spi_pinmap_t &static_pinmap, PinName ssel)
Create a SPI master connected to the specified pins.
void frequency(int hz=1000000)
Set the SPI bus clock frequency.
int set_dma_usage(DMAUsage usage)
Configure DMA usage suggestion for non-blocking transfers.
virtual int write(int value)
Write to the SPI Slave and return the response.
virtual void unlock(void)
Release exclusive access to this SPI bus.
void format(int bits, int mode=0)
Configure the data transmission format.
void abort_all_transfers()
Clear the queue of transfers and abort any on-going transfer.
void abort_transfer()
Abort the on-going SPI transfer, if any, and continue with transfers in the queue,...
void clear_transfer_buffer()
Clear the queue of transfers.
SPI(const spi_pinmap_t &static_pinmap)
Create a SPI master connected to the specified pins.
void select(void)
Assert the Slave Select line and acquire exclusive access to this SPI bus.
int transfer_and_wait(const uint8_t *tx_buffer, int tx_length, CacheAlignedBuffer< uint8_t > &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout=rtos::Kernel::wait_for_u32_forever)
Start SPI transfer and wait until it is complete.
Definition SPI.h:560
virtual void lock(void)
Acquire exclusive access to this SPI bus.
int transfer(const uint8_t *tx_buffer, int tx_length, CacheAlignedBuffer< uint8_t > &rx_buffer, int rx_length, const event_callback_t &callback, int event=SPI_EVENT_COMPLETE)
Start non-blocking SPI transfer.
Definition SPI.h:486
The EventFlags class is used to control event flags or wait for event flags other threads control.
Definition EventFlags.h:53
The Mutex class is used to synchronize the execution of threads.
Definition Mutex.h:79
#define SPI_EVENT_COMPLETE
Indicates that the transfer completed successfully.
Definition spi_api.h:46
DMAUsage
Enumeration of possible DMA usage hints.
Definition dma_api.h:32
DataT * data()
Get a pointer to the aligned data array inside the buffer.
#define MBED_ASSERT(expr)
MBED_ASSERT Declare runtime assertions: results in runtime error if condition is false.
Definition mbed_assert.h:67
Callback< R(ArgTs...)> callback(R(*func)(ArgTs...)=nullptr) noexcept
Create a callback class with type inferred from the arguments.
Definition Callback.h:678
constexpr Clock::duration_u32 wait_for_u32_forever
Magic "wait forever" constant for Kernel::Clock::duration_u32-based APIs.
Definition Kernel.h:120
Utility class for creating and using a singleton.
Transaction structure.
Definition Transaction.h:33
Asynch SPI HAL structure.
Definition spi_api.h:69