Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add SPI slave mode support #2050

Draft
wants to merge 1 commit into
base: main
Choose a base branch
from
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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