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"
281 SPI(PinName mosi, PinName miso, PinName sclk, PinName ssel = NC);
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)
387 return write_internal(
reinterpret_cast<char const *
>(tx_buffer), tx_length,
reinterpret_cast<char *
>(rx_buffer), rx_length);
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)
395 return write_internal(tx_buffer, tx_length,
reinterpret_cast<char *
>(rx_buffer), rx_length);
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)
402 return write_internal(
reinterpret_cast<char const *
>(tx_buffer), tx_length, rx_buffer, rx_length);
479 template<
typename WordT>
480 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
484 return transfer_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length,
callback, event);
488 template<
typename WordT>
489 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
493 return transfer_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length,
callback, event);
495 template<
typename WordT>
496 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
499 return transfer_internal(tx_buffer, tx_length, rx_buffer, rx_length,
callback, event);
527 template<
typename WordT>
528 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
532 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length, timeout);
536 template<
typename WordT>
537 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
541 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer.
data(), rx_length, timeout);
543 template<
typename WordT>
544 typename std::enable_if<std::is_integral<WordT>::value,
int>::type
547 return transfer_and_wait_internal(tx_buffer, tx_length, rx_buffer, rx_length, timeout);
579#if !defined(DOXYGEN_ONLY)
584 void irq_handler_asynch(
void);
602 int transfer_internal(
const void *tx_buffer,
int tx_length,
void *rx_buffer,
int rx_length,
const event_callback_t &
callback,
int event);
628 int transfer_and_wait_internal(
const void *tx_buffer,
int tx_length,
void *rx_buffer,
int rx_length, rtos::Kernel::Clock::duration_u32 timeout);
646 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);
660 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);
664 void lock_deep_sleep();
667 void unlock_deep_sleep();
670#if MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
679 void dequeue_transaction();
685#if !defined(DOXYGEN_ONLY)
687#ifdef DEVICE_SPI_COUNT
689 typedef ::SPIName SPIName;
692 enum SPIName { GlobalSPI };
701 struct spi_peripheral_s {
703 SPIName name = SPIName(0);
709 SPI *owner =
nullptr;
711 uint8_t numUsers = 0;
713 bool initialized =
false;
714#if DEVICE_SPI_ASYNCH && MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
723 static spi_peripheral_s _peripherals[SPI_PERIPHERALS_USED];
724 static int _peripherals_used;
727 spi_peripheral_s *_peripheral;
733 event_callback_t _callback;
737 bool _deep_sleep_locked;
741 volatile bool _transfer_in_progress =
false;
745 bool _transfer_in_progress_uses_dma;
750 void *_transfer_in_progress_rx_buffer;
751 size_t _transfer_in_progress_rx_len;
776 volatile uint8_t _select_count = 0;
780 SPIName _peripheral_name;
782 void (*_init_func)(
SPI *);
791 void _do_construct();
802 static spi_peripheral_s *_lookup(SPIName name);
807 static spi_peripheral_s *_alloc();
811 static void _dealloc(spi_peripheral_s *peripheral);
813 static void _do_init(SPI *obj);
814 static void _do_init_direct(SPI *obj);
834 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.