20#include "platform/platform.h"
22#if DEVICE_SPI || defined(DOXYGEN_ONLY)
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"
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
37#define SPI_PERIPHERALS_USED 1
41#include "platform/CThunk.h"
43#include "platform/CircularBuffer.h"
44#include "platform/Callback.h"
45#include "platform/Transaction.h"
46#include "rtos/EventFlags.h"
284 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC);
386 template<
typename WordT>
387 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
388 write(
const WordT *tx_buffer,
int tx_length, WordT *rx_buffer,
int rx_length)
390 return write_internal(
reinterpret_cast<char const *
>(tx_buffer), tx_length,
reinterpret_cast<char *
>(rx_buffer), rx_length);
394 template<
typename WordT>
395 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
396 write(
const std::nullptr_t tx_buffer,
int tx_length, WordT *rx_buffer,
int rx_length)
398 return write_internal(tx_buffer, tx_length,
reinterpret_cast<char *
>(rx_buffer), rx_length);
401 template<
typename WordT>
402 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
403 write(
const WordT *tx_buffer,
int tx_length, std::nullptr_t rx_buffer,
int rx_length)
405 return write_internal(
reinterpret_cast<char const *
>(tx_buffer), tx_length, rx_buffer, rx_length);
482 template<
typename WordT>
483 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
487 return transfer_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length,
callback, event);
491 template<
typename WordT>
492 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
496 return transfer_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length,
callback, event);
498 template<
typename WordT>
499 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
502 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length,
callback, event);
530 template<
typename WordT>
531 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
535 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length, timeout);
539 template<
typename WordT>
540 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
544 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length, timeout);
546 template<
typename WordT>
547 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
550 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
582#if !defined(DOXYGEN_ONLY)
587 void irq_handler_asynch(
void);
605 int transfer_internal(
const void *tx_buffer,
int tx_length,
void *rx_buffer,
int rx_length,
const event_callback_t &
callback,
int event);
631 int transfer_and_wait_internal(
const void *tx_buffer,
int tx_length,
void *rx_buffer,
int rx_length, rtos::Kernel::Clock::duration_u32 timeout);
649 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);
663 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);
667 void lock_deep_sleep();
670 void unlock_deep_sleep();
673#if MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
682 void dequeue_transaction();
688#if !defined(DOXYGEN_ONLY)
690#ifdef DEVICE_SPI_COUNT
692 typedef ::SPIName SPIName;
695 enum SPIName { GlobalSPI };
704 struct spi_peripheral_s {
706 SPIName name = SPIName(0);
712 SPI *owner =
nullptr;
714 uint8_t numUsers = 0;
716 bool initialized =
false;
717#if DEVICE_SPI_ASYNCH && MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
726 static spi_peripheral_s _peripherals[SPI_PERIPHERALS_USED];
727 static int _peripherals_used;
730 spi_peripheral_s *_peripheral;
736 event_callback_t _callback;
740 bool _deep_sleep_locked;
744 volatile bool _transfer_in_progress =
false;
748 bool _transfer_in_progress_uses_dma;
753 void *_transfer_in_progress_rx_buffer;
754 size_t _transfer_in_progress_rx_len;
779 volatile uint8_t _select_count = 0;
783 SPIName _peripheral_name;
785 void (*_init_func)(
SPI *);
794 void _do_construct();
805 static spi_peripheral_s *_lookup(SPIName name);
810 static spi_peripheral_s *_alloc();
814 static void _dealloc(spi_peripheral_s *peripheral);
816 static void _do_init(SPI *obj);
817 static void _do_init_direct(SPI *obj);
837 virtual int write_internal(
const void *tx_buffer,
int tx_length,
void *rx_buffer,
int rx_length);
Class for created a pointer with data bound to it.
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.
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.
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.
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.
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.
The Mutex class is used to synchronize the execution of threads.
#define SPI_EVENT_COMPLETE
Indicates that the transfer completed successfully.
DMAUsage
Enumeration of possible DMA usage hints.
constexpr Clock::duration_u32 wait_for_u32_forever
Magic "wait forever" constant for Kernel::Clock::duration_u32-based APIs.
Utility class for creating and using a singleton.
Asynch SPI HAL structure.