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);
577#if !defined(DOXYGEN_ONLY)
582 void irq_handler_asynch(
void);
600 int transfer_internal(
const void *tx_buffer,
int tx_length,
void *rx_buffer,
int rx_length,
const event_callback_t &
callback,
int event);
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);
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);
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);
662 void lock_deep_sleep();
665 void unlock_deep_sleep();
668#if MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
677 void dequeue_transaction();
683#if !defined(DOXYGEN_ONLY)
685#ifdef DEVICE_SPI_COUNT
687 typedef ::SPIName SPIName;
690 enum SPIName { GlobalSPI };
699 struct spi_peripheral_s {
701 SPIName name = SPIName(0);
707 SPI *owner =
nullptr;
709 uint8_t numUsers = 0;
711 bool initialized =
false;
712#if DEVICE_SPI_ASYNCH && MBED_CONF_DRIVERS_SPI_TRANSACTION_QUEUE_LEN
721 static spi_peripheral_s _peripherals[SPI_PERIPHERALS_USED];
722 static int _peripherals_used;
725 spi_peripheral_s *_peripheral;
731 event_callback_t _callback;
735 bool _deep_sleep_locked;
739 volatile bool _transfer_in_progress =
false;
743 bool _transfer_in_progress_uses_dma;
748 void *_transfer_in_progress_rx_buffer;
749 size_t _transfer_in_progress_rx_len;
774 volatile uint8_t _select_count = 0;
778 SPIName _peripheral_name;
780 void (*_init_func)(
SPI *);
789 void _do_construct();
800 static spi_peripheral_s *_lookup(SPIName name);
805 static spi_peripheral_s *_alloc();
809 static void _dealloc(spi_peripheral_s *peripheral);
811 static void _do_init(SPI *obj);
812 static void _do_init_direct(SPI *obj);
832 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.