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 * <p>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 not well defined and may differ across targets
184 * or across API calls (e.g. single-byte vs transaction vs async). More work is needed to make these consistent.</p>
185 *
186 * <h1>Asynchronous API</h1>
187 * <p>On many processors, Mbed OS also supports asynchronous %SPI. This feature allows you to run %SPI
188 * transfers completely in the background, while other threads execute in the foreground. This can
189 * be extremely useful if you need to send large amounts of data over the %SPI bus but don't want to
190 * block your main thread for ages. To see if your processor supports async %SPI, look for the
191 * DEVICE_SPI_ASYNCH macro.</p>
192 *
193 * <p>The asynchronous API has two different modes: nonblocking (where your thread can keep running, and
194 * the transfer calls a callback when finished) and blocking (where your thread blocks for the duration of
195 * the transfer but others can execute). Here's a sample of how to send the same data as above
196 * using the blocking async API:</p>
197 *
198 * <p>Note that when using the asynchronous API, you must use the CacheAlignedBuffer class when declaring the
199 * receive buffer. This is because some processors' async SPI implementations require the received buffer to
200 * be at an address which is aligned to the processor cache line size. CacheAlignedBuffer takes care of this
201 * for you and provides functions (data(), begin(), end()) to access the underlying data in the buffer.</p>
202 *
203 * @code
204 * #include "mbed.h"
205 *
206 * SPI device(SPI_MOSI, SPI_MISO, SPI_SCLK, SPI_CS, use_gpio_ssel)
207 *
208 * int main() {
209 * device.format(8, 0);
210 *
211 * uint8_t command[2] = {0x0A, 0x0B};
212 * CacheAlignedBuffer<uint8_t, 2> response;
213 * int result = device.transfer_and_wait(command, sizeof(command), response, sizeof(command));
214 * }
215 * @endcode
216 *
217 * <p>This code will cause the data in \c command to be sent to the device and the response to be received into
218 * \c response . During the transfer, the current thread is paused, but other threads can execute.
219 * The non-blocking API does not pause the current thread, but is a bit more complicated to use.
220 * See the SPI::transfer_and_wait() implementation in SPI.cpp for an example.</p>
221 *
222 * <h3>Async: DMA vs Interrupts</h3>
223 * <p>Some processors only provide asynchronous %SPI via interrupts, some only support DMA, and some offer both.
224 * Using interrupts is simpler and generally doesn't require additional resources from the chip, however,
225 * some CPU time will be spent servicing the interrupt while the transfer is running. This can become very
226 * performance-intensive -- on some chips, running async %SPI at frequencies of just a few MHz can be enough
227 * to make the interrupt use 100% of CPU time. In contrast, DMA can require additional resources to be allocated,
228 * (e.g. chips with few DMA channels might only support DMA on one or two %SPI busses at a time), but
229 * can run the bus at full speed without any CPU overhead. Generally, DMA should be preferred if available,
230 * especially if medium to fast bus speeds are needed.</p>
231 *
232 * <p>Consult your chip documentation and the Mbed port docs for your target to find out what is needed to enable
233 * DMA support. For example, for STMicro targets, see
234 * <a href="https://github.com/mbed-ce/mbed-os/wiki/STM32-DMA-SPI-Support">here</a>.To select DMA or interrupts,
235 * use the SPI::set_dma_usage() function. By default, interrupt %SPI will be used unless you change the
236 * setting.</p>
237 *
238 * <h3>Async: Queueing</h3>
239 * <p>The async %SPI system supports an optional transaction queueing mechanism. When this is enabled,
240 * Mbed will allow multiple transactions to be queued up on a single bus, and will execute each one
241 * and deliver the appropriate callback in series. This is mainly useful for the non-blocking
242 * async api (SPI::transfer()), though you can also use it with the blocking API by having multiple
243 * threads call it at once.</p>
244 *
245 * <p>The transaction queue size defaults to 2 on most devices, but you can change that using the
246 * \c drivers.spi_transaction_queue_len option, e.g.</p>
247 * \code{.json}
248 * {
249 * "target_overrides": {
250 * "*": {
251 * "drivers.spi_transaction_queue_len": 3
252 * }
253 * }
254 * }
255 * \endcode
256 *
257 * <p>To save a little bit of memory, you can also set the queue length to 0 to disable the queueing mechanism.</p>
258 *
259 * \warning Currently, the value set by SPI::set_default_write_value() is
260 * <a href="https://github.com/ARMmbed/mbed-os/issues/13941">not respected</a> by the asynchronous %SPI
261 * code. This needs to be fixed.
262 */
263class SPI : private NonCopyable<SPI> {
264
265public:
266
267 /** Create a SPI master connected to the specified pins.
268 *
269 * @note This constructor passes the SSEL pin selection to the target HAL.
270 * Not all targets support SSEL, so this cannot be relied on in portable code.
271 * Portable code should use the alternative constructor that uses GPIO
272 * for SSEL.
273 *
274 * @note You can specify mosi or miso as NC if not used.
275 *
276 * @param mosi SPI Master Out, Slave In pin.
277 * @param miso SPI Master In, Slave Out pin.
278 * @param sclk SPI Clock pin.
279 * @param ssel SPI Chip Select pin.
280 */
281 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC);
282
283 /** Create a SPI master connected to the specified pins.
284 *
285 * @note This constructor manipulates the SSEL pin as a GPIO output
286 * using a DigitalOut object. This should work on any target, and permits
287 * the use of select() and deselect() methods to keep the pin asserted
288 * between transfers.
289 *
290 * @note You can specify mosi or miso as NC if not used.
291 *
292 * @param mosi SPI Master Out, Slave In pin.
293 * @param miso SPI Master In, Slave Out pin.
294 * @param sclk SPI Clock pin.
295 * @param ssel SPI Chip Select pin.
296 */
297 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel, use_gpio_ssel_t);
298
299 /** Create a SPI master connected to the specified pins.
300 *
301 * @note This constructor passes the SSEL pin selection to the target HAL.
302 * Not all targets support SSEL, so this cannot be relied on in portable code.
303 * Portable code should use the alternative constructor that uses GPIO
304 * for SSEL.
305 *
306 * @note You can specify mosi or miso as NC if not used.
307 *
308 * @param static_pinmap reference to structure which holds static pinmap.
309 */
310 SPI(const spi_pinmap_t &static_pinmap);
311 SPI(const spi_pinmap_t &&) = delete; // prevent passing of temporary objects
312
313 /** Create a SPI master connected to the specified pins.
314 *
315 * @note This constructor manipulates the SSEL pin as a GPIO output
316 * using a DigitalOut object. This should work on any target, and permits
317 * the use of select() and deselect() methods to keep the pin asserted
318 * between transfers.
319 *
320 * @note You can specify mosi or miso as NC if not used.
321 *
322 * @param static_pinmap reference to structure which holds static pinmap.
323 * @param ssel SPI Chip Select pin.
324 */
325 SPI(const spi_pinmap_t &static_pinmap, PinName ssel);
326 SPI(const spi_pinmap_t &&, PinName) = delete; // prevent passing of temporary objects
327
328 virtual ~SPI();
329
330 /**
331 * @brief Configure the data transmission format.
332 *
333 * @param bits Number of bits per %SPI frame (4 - 32, target dependent).
334 * @param mode Clock polarity and phase mode (0 - 3).
335 *
336 * @code
337 * mode | POL PHA
338 * -----+--------
339 * 0 | 0 0
340 * 1 | 0 1
341 * 2 | 1 0
342 * 3 | 1 1
343 * @endcode
344 */
345 void format(int bits, int mode = 0);
346
347 /**
348 * @brief Set the %SPI bus clock frequency.
349 *
350 * @param hz Clock frequency in Hz (default = 1MHz).
351 */
352 void frequency(int hz = 1000000);
353
354 /**
355 * @brief Write to the %SPI Slave and return the response.
356 *
357 * @param value Data to be sent to the SPI slave. The number of significant bits in this
358 * value depend on the \c bits parameter to format().
359 *
360 * @return Response from the %SPI slave. The number of significant bits in this
361 * value depend on the \c bits parameter to format().
362 */
363 virtual int write(int value);
364
365 /**
366 * @brief Write to the SPI Slave and obtain the response.
367 *
368 * The total number of bytes sent and received will be the maximum of
369 * tx_length and rx_length. The bytes written will be padded with the
370 * value 0xff.
371 *
372 * Note: Even if the word size / bits per frame is not 8, \c rx_length and \c tx_length
373 * still count bytes of input data, not numbers of words.
374 *
375 * @param tx_buffer Pointer to the byte-array of data to write to the device.
376 * @param tx_length Number of bytes to write, may be zero.
377 * @param rx_buffer Pointer to the byte-array of data to read from the device.
378 * @param rx_length Number of bytes to read, may be zero.
379 * @return
380 * The number of bytes written and read from the device (as an int). This is
381 * maximum of tx_length and rx_length.
382 */
383 template<typename WordT>
384 typename std::enable_if<std::is_integral<WordT>::value, int>::type
385 write(const WordT *tx_buffer, int tx_length, WordT *rx_buffer, int rx_length)
386 {
387 return write_internal(reinterpret_cast<char const *>(tx_buffer), tx_length, reinterpret_cast<char *>(rx_buffer), rx_length);
388 }
389
390 // Overloads of the above to support passing nullptr
391 template<typename WordT>
392 typename std::enable_if<std::is_integral<WordT>::value, int>::type
393 write(const std::nullptr_t tx_buffer, int tx_length, WordT *rx_buffer, int rx_length)
394 {
395 return write_internal(tx_buffer, tx_length, reinterpret_cast<char *>(rx_buffer), rx_length);
396 }
397
398 template<typename WordT>
399 typename std::enable_if<std::is_integral<WordT>::value, int>::type
400 write(const WordT *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length)
401 {
402 return write_internal(reinterpret_cast<char const *>(tx_buffer), tx_length, rx_buffer, rx_length);
403 }
404
405 /**
406 * @brief Acquire exclusive access to this SPI bus.
407 *
408 * This function blocks until the chosen SPI peripheral is not being used by any other SPI objects.
409 * Careful -- if other code leaves the bus locked, this could block forever!
410 */
411 virtual void lock(void);
412
413 /**
414 * @brief Release exclusive access to this SPI bus.
415 *
416 * This allows other code to do operations using the SPI peripheral.
417 */
418 virtual void unlock(void);
419
420 /**
421 * @brief Assert the Slave Select line and acquire exclusive access to this SPI bus.
422 *
423 * The slave select line will remain selected (low) for all following operations until
424 * you call #deselect() on this instance. This allows you to string together multiple SPI transactions
425 * as if they were a single operation (from the perspective of peripheral chips).
426 *
427 * If use_gpio_ssel was not passed to the constructor, manual control of the SSEL line is not possible,
428 * and this function behaves identically to #lock().
429 *
430 * Like #lock(), this function will block until exclusive access can be acquired.
431 *
432 * \warning Do not call this function while an asynchronous transfer is in progress,
433 * as undefined behavior can occur.
434 */
435 void select(void);
436
437 /**
438 * @brief Deassert the Slave Select line, releasing exclusive access to this SPI bus.
439 *
440 * If use_gpio_ssel was not passed to the constructor, manual control of the SSEL line is not possible,
441 * and this function behaves identically to #unlock().
442 *
443 * \warning Do not call this function while an asynchronous transfer is in progress,
444 * as undefined behavior can occur.
445 */
446 void deselect(void);
447
448 /** Set default write data.
449 * SPI requires the master to send some data during a read operation.
450 * Different devices may require different default byte values.
451 * For example: A SD Card requires default bytes to be 0xFF.
452 *
453 * @param data Default character to be transmitted during a read operation.
454 */
455 void set_default_write_value(char data);
456
457#if DEVICE_SPI_ASYNCH
458
459 /**
460 * @brief Start non-blocking %SPI transfer.
461 *
462 * This function locks the deep sleep until any event has occurred.
463 *
464 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
465 * the default %SPI value is sent.
466 * @param tx_length The length of TX buffer in bytes.
467 * @param rx_buffer The RX buffer which is used for received data. Rather than a C array, a CacheAlignedBuffer
468 * structure must be passed so that cache alignment can be handled for data received from DMA.
469 * May be nullptr if rx_length is 0.
470 * @param rx_length The length of RX buffer in bytes.
471 * @param callback The event callback function.
472 * @param event The logical OR of events to subscribe to. May be #SPI_EVENT_ALL, or some combination
473 * of the flags #SPI_EVENT_ERROR, #SPI_EVENT_COMPLETE, or #SPI_EVENT_RX_OVERFLOW
474 *
475 * @return Operation result (integer)
476 * @retval 0 If the transfer has started.
477 * @retval -1 if the transfer could not be enqueued (increase drivers.spi_transaction_queue_len option)
478 */
479 template<typename WordT>
480 typename std::enable_if<std::is_integral<WordT>::value, int>::type
481 transfer(const WordT *tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
482 {
483 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
484 return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
485 }
486
487 // Overloads of the above to support passing nullptr
488 template<typename WordT>
489 typename std::enable_if<std::is_integral<WordT>::value, int>::type
490 transfer(const std::nullptr_t tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
491 {
492 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
493 return transfer_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, callback, event);
494 }
495 template<typename WordT>
496 typename std::enable_if<std::is_integral<WordT>::value, int>::type
497 transfer(const WordT *tx_buffer, int tx_length, std::nullptr_t rx_buffer, int rx_length, const event_callback_t &callback, int event = SPI_EVENT_COMPLETE)
498 {
499 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length, callback, event);
500 }
501
502 /**
503 * @brief Start %SPI transfer and wait until it is complete.
504 *
505 * Like the transactional API this blocks the current thread,
506 * however all work is done in the background and other threads may execute.
507 *
508 * As long as there is space, this function will enqueue the transfer request onto the peripheral,
509 * and block until it is done.
510 *
511 * Internally, the chip vendor may implement this function using either DMA or interrupts.
512 *
513 * @param tx_buffer The TX buffer with data to be transferred. May be nullptr if tx_length is 0.
514 * @param tx_length The length of TX buffer in bytes. If 0, the default %SPI data value is sent when receiving data.
515 * @param rx_buffer The RX buffer which is used for received data. Rather than a C array, a CacheAlignedBuffer
516 * structure must be passed so that cache alignment can be handled for data received from DMA.
517 * May be nullptr if rx_length is 0.
518 * @param rx_length The length of RX buffer in bytes If 0, no reception is done.
519 * @param timeout timeout value. Use #rtos::Kernel::wait_for_u32_forever to wait forever (the default).
520 *
521 * @return Operation result (integer)
522 * @retval -1 if the transfer could not be enqueued (increase drivers.spi_transaction_queue_len option)
523 * @retval 1 on timeout
524 * @retval 2 on other error
525 * @retval 0 on success
526 */
527 template<typename WordT>
528 typename std::enable_if<std::is_integral<WordT>::value, int>::type
529 transfer_and_wait(const WordT *tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
530 {
531 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
532 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
533 }
534
535 // Overloads of the above to support passing nullptr
536 template<typename WordT>
537 typename std::enable_if<std::is_integral<WordT>::value, int>::type
538 transfer_and_wait(const std::nullptr_t tx_buffer, int tx_length, CacheAlignedBuffer<WordT> &rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout = rtos::Kernel::wait_for_u32_forever)
539 {
540 MBED_ASSERT(rx_length <= static_cast<int>(rx_buffer.capacity()));
541 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.data(), rx_length, timeout);
542 }
543 template<typename WordT>
544 typename std::enable_if<std::is_integral<WordT>::value, int>::type
545 transfer_and_wait(const WordT *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)
546 {
547 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
548 }
549
550 /**
551 * @brief Abort the on-going SPI transfer, if any, and continue with transfers in the queue, if any.
552 */
554
555 /**
556 * @brief Clear the queue of transfers.
557 *
558 * If a transfer is currently active, it will continue until complete.
559 */
561
562 /**
563 * @brief Clear the queue of transfers and abort any on-going transfer.
564 */
566
567 /** Configure DMA usage suggestion for non-blocking transfers.
568 *
569 * @param usage The usage DMA hint for peripheral.
570 *
571 * @return Result of the operation.
572 * @retval 0 The usage was set.
573 * @retval -1 Usage cannot be set as there is an ongoing transaction.
574 */
576
577#if !defined(DOXYGEN_ONLY)
578protected:
579
580 /** SPI interrupt handler.
581 */
582 void irq_handler_asynch(void);
583
584 /** Start the transfer or put it on the queue.
585 *
586 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
587 * the default SPI value is sent
588 * @param tx_length The length of TX buffer in bytes.
589 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
590 * received data are ignored. This buffer is guaranteed to be cache aligned
591 * if the MCU has a cache.
592 * @param rx_length The length of RX buffer in bytes.
593 * @param callback The event callback function.
594 * @param event The event mask of events to modify.
595 *
596 * @return Operation success.
597 * @retval 0 A transfer was started or added to the queue.
598 * @retval -1 Transfer can't be added because queue is full.
599 */
600 int transfer_internal(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, const event_callback_t &callback, int event);
601
602 /**
603 * @brief Start %SPI transfer and wait until it is complete.
604 *
605 * Like the transactional API this blocks the current thread,
606 * however all work is done in the background and other threads may execute.
607 *
608 * As long as there is space, this function will enqueue the transfer request onto the peripheral,
609 * and block until it is done.
610 *
611 * Internally, the chip vendor may implement this function using either DMA or interrupts.
612 *
613 * @param tx_buffer The TX buffer with data to be transferred. May be nullptr if tx_length is 0.
614 * @param tx_length The length of TX buffer in bytes. If 0, no transmission is done.
615 * @param rx_buffer The RX buffer, which is used for received data. May be nullptr if tx_length is 0.
616 * This buffer is guaranteed to be cache aligned if the MCU has a cache.
617 * @param rx_length The length of RX buffer in bytes If 0, no reception is done.
618 * @param timeout timeout value. Use #rtos::Kernel::wait_for_u32_forever to wait forever (the default).
619 *
620 * @return Operation result (integer)
621 * @retval -1 if the transfer could not be enqueued (increase drivers.spi_transaction_queue_len option)
622 * @retval 1 on timeout
623 * @retval 2 on other error
624 * @retval 0 on success
625 */
626 int transfer_and_wait_internal(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length, rtos::Kernel::Clock::duration_u32 timeout);
627
628 /** Put a transfer on the transfer queue.
629 *
630 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
631 * the default SPI value is sent.
632 * @param tx_length The length of TX buffer in bytes.
633 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
634 * received data are ignored.
635 * @param rx_length The length of RX buffer in bytes.
636 * @param bit_width The buffers element width in bits.
637 * @param callback The event callback function.
638 * @param event The event mask of events to modify.
639 *
640 * @return Operation success.
641 * @retval 0 A transfer was added to the queue.
642 * @retval -1 Transfer can't be added because queue is full.
643 */
644 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);
645
646 /** Configure a callback, SPI peripheral, and initiate a new transfer.
647 *
648 * @param tx_buffer The TX buffer with data to be transferred. If NULL is passed,
649 * the default SPI value is sent.
650 * @param tx_length The length of TX buffer in bytes.
651 * @param rx_buffer The RX buffer which is used for received data. If NULL is passed,
652 * received data are ignored.
653 * @param rx_length The length of RX buffer in bytes.
654 * @param bit_width The buffers element width.
655 * @param callback The event callback function.
656 * @param event The event mask of events to modify.
657 */
658 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);
659
660private:
661 /** Lock deep sleep only if it is not yet locked */
662 void lock_deep_sleep();
663
664 /** Unlock deep sleep in case it is locked */
665 void unlock_deep_sleep();
666
667
668#if MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
669 /** Start a new transaction.
670 *
671 * @param data Transaction data.
672 */
673 void start_transaction(transaction_t *data);
674
675 /** Dequeue a transaction and start the transfer if there was one pending.
676 */
677 void dequeue_transaction();
678
679#endif // MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
680#endif // !defined(DOXYGEN_ONLY)
681#endif // DEVICE_SPI_ASYNCH
682
683#if !defined(DOXYGEN_ONLY)
684protected:
685#ifdef DEVICE_SPI_COUNT
686 // HAL must have defined this as a global enum
687 typedef ::SPIName SPIName;
688#else
689 // HAL may or may not have defined it - use a local definition
690 enum SPIName { GlobalSPI };
691#endif
692
693 // All members of spi_peripheral_s must be initialized to make the structure
694 // constant-initialized, and hence able to be omitted by the linker,
695 // as SingletonPtr now relies on C++ constant-initialization. (Previously it
696 // worked through C++ zero-initialization). And all the constants should be zero
697 // to ensure it stays in the actual zero-init part of the image if used, avoiding
698 // an initialized-data cost.
699 struct spi_peripheral_s {
700 /* Internal SPI name identifying the resources. */
701 SPIName name = SPIName(0);
702 /* Internal SPI object handling the resources' state. */
703 spi_t spi{};
704 /* Used by lock and unlock for thread safety */
706 /* Current user of the SPI, if any. */
707 SPI *owner = nullptr;
708 /* Number of SPI objects that have been created which reference this peripheral. */
709 uint8_t numUsers = 0;
710 /* True iff anyone has ever called spi_init() / spi_init_direct() for this peripheral */
711 bool initialized = false;
712#if DEVICE_SPI_ASYNCH && MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
713 /* Queue of pending transfers */
714 SingletonPtr<CircularBuffer<Transaction<SPI>, MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN> > transaction_buffer;
715#endif
716 };
717
718 // holds spi_peripheral_s per peripheral on the device.
719 // Drawback: it costs ram size even if the device is not used, however
720 // application can limit the allocation via JSON.
721 static spi_peripheral_s _peripherals[SPI_PERIPHERALS_USED];
722 static int _peripherals_used;
723
724 // Holds the reference to the associated peripheral.
725 spi_peripheral_s *_peripheral;
726
727#if DEVICE_SPI_ASYNCH
728 /* Interrupt */
729 CThunk<SPI> _irq;
730 /* Interrupt handler callback */
731 event_callback_t _callback;
732 /* Current preferred DMA mode @see dma_api.h */
733 DMAUsage _usage;
734 /* Current sate of the sleep manager */
735 bool _deep_sleep_locked;
736 /* Whether an async transfer is currently in progress. Specifically, this is true
737 * iff start_transfer() has been called and the chip has been selected but irq_handler_asynch()
738 * has NOT been called yet. */
739 volatile bool _transfer_in_progress = false;
740
741 // If there is a transfer in progress, this indicates whether it used DMA and therefore requires a cache
742 // flush at the end
743 bool _transfer_in_progress_uses_dma;
744
745#if __DCACHE_PRESENT
746 // These variables store the location and length in bytes of the Rx buffer if an async transfer
747 // is in progress. They are used for invalidating the cache after the transfer completes.
748 void *_transfer_in_progress_rx_buffer;
749 size_t _transfer_in_progress_rx_len;
750#endif
751
752 /* Event flags used for transfer_and_wait() */
753 rtos::EventFlags _transfer_and_wait_flags;
754#endif // DEVICE_SPI_ASYNCH
755
756 // Configuration.
757 PinName _mosi;
758 PinName _miso;
759 PinName _sclk;
760 PinName _hw_ssel;
761
762 // The Slave Select GPIO if we're doing it ourselves.
763 DigitalOut _sw_ssel;
764
765 /* Size of the SPI frame */
766 int _bits;
767 /* Clock polarity and phase */
768 int _mode;
769 /* Clock frequency */
770 int _hz;
771 /* Default character used for NULL transfers */
772 char _write_fill;
773 /* Select count to handle re-entrant selection */
774 volatile uint8_t _select_count = 0;
775 /* Static pinmap data */
776 const spi_pinmap_t *_static_pinmap;
777 /* SPI peripheral name */
778 SPIName _peripheral_name;
779 /* Pointer to spi init function */
780 void (*_init_func)(SPI *);
781
782private:
783
784 /**
785 * Get a reference to the mutex used to protect the peripherals array.
786 */
787 rtos::Mutex &_get_peripherals_mutex();
788
789 void _do_construct();
790
791 /** Private acquire function without locking/unlocking.
792 * Implemented in order to avoid duplicate locking and boost performance.
793 */
794 void _acquire(void);
795 void _set_ssel(int);
796
797 /** Private lookup in the static _peripherals table.
798 * Should be called with _peripherals_mutex locked.
799 */
800 static spi_peripheral_s *_lookup(SPIName name);
801
802 /** Allocate an entry in the static _peripherals table.
803 * Should be called with _peripherals_mutex locked.
804 */
805 static spi_peripheral_s *_alloc();
806
807 /// Deallocate the given peripheral.
808 /// Should be called with _peripherals_mutex locked.
809 static void _dealloc(spi_peripheral_s *peripheral);
810
811 static void _do_init(SPI *obj);
812 static void _do_init_direct(SPI *obj);
813
814 /**
815 * @brief Write to the SPI Slave and obtain the response.
816 *
817 * The total number of bytes sent and received will be the maximum of
818 * tx_length and rx_length. The bytes written will be padded with the
819 * value 0xff.
820 *
821 * Note: Even if the word size / bits per frame is not 8, \c rx_length and \c tx_length
822 * still count bytes of input data, not numbers of words.
823 *
824 * @param tx_buffer Pointer to the byte-array of data to write to the device.
825 * @param tx_length Number of bytes to write, may be zero.
826 * @param rx_buffer Pointer to the byte-array of data to read from the device.
827 * @param rx_length Number of bytes to read, may be zero.
828 * @return
829 * The number of bytes written and read from the device. This is
830 * maximum of tx_length and rx_length.
831 */
832 virtual int write_internal(const void *tx_buffer, int tx_length, void *rx_buffer, int rx_length);
833
834
835#endif //!defined(DOXYGEN_ONLY)
836};
837
838/** @}*/
839
840} // namespace mbed
841
842#endif // DEVICE_SPI || DOXYGEN_ONLY
843
844#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.
Definition: NonCopyable.h:162
An SPI Master, used for communicating with SPI slave devices.
Definition: SPI.h:263
std::enable_if< std::is_integral< WordT >::value, int >::type transfer(const WordT *tx_buffer, int tx_length, CacheAlignedBuffer< WordT > &rx_buffer, int rx_length, const event_callback_t &callback, int event=SPI_EVENT_COMPLETE)
Start non-blocking SPI transfer.
Definition: SPI.h:481
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.
std::enable_if< std::is_integral< WordT >::value, int >::type write(const WordT *tx_buffer, int tx_length, WordT *rx_buffer, int rx_length)
Write to the SPI Slave and obtain the response.
Definition: SPI.h:385
SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel=NC)
Create a SPI master connected to the specified pins.
std::enable_if< std::is_integral< WordT >::value, int >::type transfer_and_wait(const WordT *tx_buffer, int tx_length, CacheAlignedBuffer< WordT > &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:529
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.
virtual void lock(void)
Acquire exclusive access to this SPI bus.
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:70
#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.
constexpr size_t capacity()
#define MBED_ASSERT(expr)
MBED_ASSERT Declare runtime assertions: results in runtime error if condition is false.
Definition: mbed_assert.h:66
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.
Definition: SingletonPtr.h:88
Transaction structure.
Definition: Transaction.h:33
Asynch SPI HAL structure.
Definition: spi_api.h:69