Skip to content

Commit

Permalink
feat(spi): add slave mode support
Browse files Browse the repository at this point in the history
Signed-off-by: patricklaf <[email protected]>
Co-authored-by: Frederic Pillon <[email protected]>
  • Loading branch information
fpistm committed Dec 6, 2023
1 parent b149a92 commit 78e0808
Show file tree
Hide file tree
Showing 5 changed files with 56 additions and 33 deletions.
7 changes: 5 additions & 2 deletions libraries/SPI/keywords.txt
Original file line number Diff line number Diff line change
Expand Up @@ -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

31 changes: 14 additions & 17 deletions libraries/SPI/src/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
}

Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand Down
36 changes: 26 additions & 10 deletions libraries/SPI/src/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand All @@ -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;
};
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand Down
7 changes: 4 additions & 3 deletions libraries/SPI/src/utility/spi_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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_*' */
Expand Down
8 changes: 7 additions & 1 deletion libraries/SPI/src/utility/spi_com.h
Original file line number Diff line number Diff line change
Expand Up @@ -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,
Expand All @@ -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);
Expand Down

0 comments on commit 78e0808

Please sign in to comment.