From 78e080800e49e7b6cc79b5c94d79355055c36102 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Tue, 28 Nov 2023 11:04:07 +0100 Subject: [PATCH] feat(spi): add slave mode support Signed-off-by: patricklaf Co-authored-by: Frederic Pillon --- libraries/SPI/keywords.txt | 7 ++++-- libraries/SPI/src/SPI.cpp | 31 +++++++++++-------------- libraries/SPI/src/SPI.h | 36 +++++++++++++++++++++-------- libraries/SPI/src/utility/spi_com.c | 7 +++--- libraries/SPI/src/utility/spi_com.h | 8 ++++++- 5 files changed, 56 insertions(+), 33 deletions(-) diff --git a/libraries/SPI/keywords.txt b/libraries/SPI/keywords.txt index 18701284e0..4bf7e9bc16 100644 --- a/libraries/SPI/keywords.txt +++ b/libraries/SPI/keywords.txt @@ -30,5 +30,8 @@ SPI_MODE1 LITERAL1 SPI_MODE2 LITERAL1 SPI_MODE3 LITERAL1 -SPI_CONTINUE LITERAL1 -SPI_LAST LITERAL1 +SPI_TRANSMITRECEIVE LITERAL1 +SPI_TRANSMITONLY LITERAL1 +SPI_MASTER LITERAL1 +SPI_SLAVE LITERAL1 + diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 2c6e798b33..f6e3c72c58 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -53,28 +53,28 @@ SPIClass::SPIClass(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel) /** * @brief Initialize the SPI instance. + * @param device: device mode (optional), SPI_MASTER or SPI_SLAVE. Default is master. */ -void SPIClass::begin(void) +void SPIClass::begin(SPIDeviceMode device) { _spi.handle.State = HAL_SPI_STATE_RESET; _spiSettings = SPISettings(); - spi_init(&_spi, _spiSettings.clockFreq, - _spiSettings.dataMode, - _spiSettings.bitOrder); + _spiSettings.deviceMode = device; + spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode, + _spiSettings.bitOrder, _spiSettings.deviceMode); } /** * @brief This function should be used to configure the SPI instance in case you * don't use the default parameters set by the begin() function. - * @param settings: SPI settings(clock speed, bit order, data mode). + * @param settings: SPI settings(clock speed, bit order, data mode, device mode). */ void SPIClass::beginTransaction(SPISettings settings) { if (_spiSettings != settings) { _spiSettings = settings; - spi_init(&_spi, _spiSettings.clockFreq, - _spiSettings.dataMode, - _spiSettings.bitOrder); + spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode, + _spiSettings.bitOrder, _spiSettings.deviceMode); } } @@ -103,9 +103,8 @@ void SPIClass::setBitOrder(BitOrder bitOrder) { _spiSettings.bitOrder = bitOrder; - spi_init(&_spi, _spiSettings.clockFreq, - _spiSettings.dataMode, - _spiSettings.bitOrder); + spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode, + _spiSettings.bitOrder, _spiSettings.deviceMode); } /** @@ -127,9 +126,8 @@ void SPIClass::setDataMode(uint8_t mode) void SPIClass::setDataMode(SPIMode mode) { _spiSettings.dataMode = mode; - spi_init(&_spi, _spiSettings.clockFreq, - _spiSettings.dataMode, - _spiSettings.bitOrder); + spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode, + _spiSettings.bitOrder, _spiSettings.deviceMode); } /** @@ -147,9 +145,8 @@ void SPIClass::setClockDivider(uint8_t divider) _spiSettings.clockFreq = spi_getClkFreq(&_spi) / divider; } - spi_init(&_spi, _spiSettings.clockFreq, - _spiSettings.dataMode, - _spiSettings.bitOrder); + spi_init(&_spi, _spiSettings.clockFreq, _spiSettings.dataMode, + _spiSettings.bitOrder, _spiSettings.deviceMode); } /** diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 1105991dc7..92024c2610 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -43,27 +43,31 @@ extern "C" { class SPISettings { public: - constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode) + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, SPIDeviceMode deviceMode = SPI_MASTER) : clockFreq(clock), bitOrder(bitOrder), - dataMode((SPIMode)dataMode) + dataMode((SPIMode)dataMode), + deviceMode(deviceMode) { } - constexpr SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode) + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, SPIMode dataMode, SPIDeviceMode deviceMode = SPI_MASTER) : clockFreq(clock), bitOrder(bitOrder), - dataMode(dataMode) + dataMode(dataMode), + deviceMode(deviceMode) { } constexpr SPISettings() : clockFreq(SPI_SPEED_CLOCK_DEFAULT), bitOrder(MSBFIRST), - dataMode(SPI_MODE0) + dataMode(SPI_MODE0), + deviceMode(SPI_MASTER) { } bool operator==(const SPISettings &rhs) const { if ((this->clockFreq == rhs.clockFreq) && (this->bitOrder == rhs.bitOrder) && - (this->dataMode == rhs.dataMode)) { + (this->dataMode == rhs.dataMode) && + (this->deviceMode == rhs.deviceMode)) { return true; } return false; @@ -75,9 +79,10 @@ class SPISettings { } private: - uint32_t clockFreq; //specifies the spi bus maximum clock speed - BitOrder bitOrder; //bit order (MSBFirst or LSBFirst) - SPIMode dataMode; //one of the data mode + uint32_t clockFreq; // specifies the spi bus maximum clock speed + BitOrder bitOrder; // bit order (MSBFirst or LSBFirst) + SPIMode dataMode; // one of the data mode + SPIDeviceMode deviceMode; // device mode: master or slave friend class SPIClass; }; @@ -122,7 +127,7 @@ class SPIClass { _spi.pin_ssel = (ssel); }; - void begin(void); + void begin(SPIDeviceMode device = SPI_MASTER); void end(void); /* This function should be used to configure the SPI instance in case you @@ -163,6 +168,17 @@ class SPIClass { return &(_spi.handle); } + // Dedicated to SPI Slave + void attachSlaveInterrupt(uint8_t pin, callback_function_t callback) + { + ::attachInterrupt(pin, callback, FALLING); + } + + void detachSlaveInterrupt(uint8_t pin) + { + ::detachInterrupt(pin); + } + protected: // spi instance spi_t _spi; diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index 4adeb9d488..ec7c5dad8f 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -198,9 +198,10 @@ static uint32_t compute_disable_delay(spi_t *obj) * @param speed : spi output speed * @param mode : one of the spi modes * @param msb : set to 1 in msb first + * @param device : spi device mode: master or slave * @retval None */ -void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb) +void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMode device) { if (obj == NULL) { return; @@ -252,8 +253,8 @@ void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb) } /* Fill default value */ - handle->Instance = obj->spi; - handle->Init.Mode = SPI_MODE_MASTER; + handle->Instance = obj->spi; + handle->Init.Mode = (device == SPI_MASTER) ? SPI_MODE_MASTER : SPI_MODE_SLAVE; spi_freq = spi_getClkFreqInst(obj->spi); /* For SUBGHZSPI, 'SPI_BAUDRATEPRESCALER_*' == 'SUBGHZSPI_BAUDRATEPRESCALER_*' */ diff --git a/libraries/SPI/src/utility/spi_com.h b/libraries/SPI/src/utility/spi_com.h index 4d145ff7fd..cdde9ed0d2 100644 --- a/libraries/SPI/src/utility/spi_com.h +++ b/libraries/SPI/src/utility/spi_com.h @@ -74,6 +74,12 @@ typedef enum { SPI_MODE3 = 3, } SPIMode; +// Device mode +typedef enum { + SPI_MASTER, /* Device is master */ + SPI_SLAVE /* Device is slave */ +} SPIDeviceMode; + ///@brief SPI errors typedef enum { SPI_OK = 0, @@ -82,7 +88,7 @@ typedef enum { } spi_status_e; /* Exported functions ------------------------------------------------------- */ -void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb); +void spi_init(spi_t *obj, uint32_t speed, SPIMode mode, uint8_t msb, SPIDeviceMode device); void spi_deinit(spi_t *obj); spi_status_e spi_transfer(spi_t *obj, const uint8_t *tx_buffer, uint8_t *rx_buffer, uint16_t len); uint32_t spi_getClkFreq(spi_t *obj);