Skip to content

Commit

Permalink
feat: add the STM32WL SUBGHZSPI to the SPI library
Browse files Browse the repository at this point in the history
Signed-off-by: Peter Lawrence <12226419+majbthrd@users.noreply.github.com>
Co-authored-by: Frederic Pillon <frederic.pillon@st.com>
  • Loading branch information
2 people authored and matthijskooijman committed Dec 20, 2022
1 parent 37757fa commit aab7d10
Show file tree
Hide file tree
Showing 3 changed files with 184 additions and 40 deletions.
75 changes: 75 additions & 0 deletions libraries/SPI/src/SPI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -421,3 +421,78 @@ void SPIClass::detachInterrupt(void)
{
// Should be disableInterrupt()
}

#if defined(SUBGHZSPI_BASE)
void SUBGHZSPIClass::begin(uint8_t _pin)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
SPIClass::begin(CS_PIN_CONTROLLED_BY_USER);
}

void SUBGHZSPIClass::beginTransaction(uint8_t _pin, SPISettings settings)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
SPIClass::beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
}

byte SUBGHZSPIClass::transfer(uint8_t _pin, uint8_t _data, SPITransferMode _mode)
{
byte res;
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
res = SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
return res;
}

uint16_t SUBGHZSPIClass::transfer16(uint8_t _pin, uint16_t _data, SPITransferMode _mode)
{
uint16_t rx_buffer = 0;
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
SPIClass::transfer16(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
return rx_buffer;
}

void SUBGHZSPIClass::transfer(uint8_t _pin, void *_buf, size_t _count, SPITransferMode _mode)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _buf, _count, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
}

void SUBGHZSPIClass::transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode)
{
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_SelectSUBGHZSPI_NSS();
}
SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _bufout, _bufin, _count, _mode);
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
LL_PWR_UnselectSUBGHZSPI_NSS();
}
}

void SUBGHZSPIClass::enableDebugPins(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel)
{
/* Configure SPI GPIO pins */
pinmap_pinout(digitalPinToPinName(mosi), PinMap_SPI_MOSI);
pinmap_pinout(digitalPinToPinName(miso), PinMap_SPI_MISO);
pinmap_pinout(digitalPinToPinName(sclk), PinMap_SPI_SCLK);
pinmap_pinout(digitalPinToPinName(ssel), PinMap_SPI_SSEL);
}
#endif
43 changes: 33 additions & 10 deletions libraries/SPI/src/SPI.h
Original file line number Diff line number Diff line change
Expand Up @@ -151,15 +151,15 @@ class SPIClass {
_spi.pin_ssel = (ssel);
};

void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
void end(void);

/* This function should be used to configure the SPI instance in case you
* don't use default parameters.
* You can attach another CS pin to the SPI instance and each CS pin can be
* attach with specific SPI settings.
*/
void beginTransaction(uint8_t pin, SPISettings settings);
virtual void beginTransaction(uint8_t pin, SPISettings settings);
void beginTransaction(SPISettings settings)
{
beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
Expand All @@ -175,10 +175,10 @@ class SPIClass {
* instance with begin() or beginTransaction().
* You can specify the CS pin to use.
*/
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
virtual byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
virtual uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
virtual void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
virtual void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);

// Transfer functions when user controls himself the CS pin.
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST)
Expand Down Expand Up @@ -233,6 +233,10 @@ class SPIClass {
return &(_spi.handle);
}

protected:
// spi instance
spi_t _spi;

private:
/* Contains various spiSettings for the same spi instance. Each spi spiSettings
is associated to a CS pin. */
Expand All @@ -241,10 +245,6 @@ class SPIClass {
// Use to know which configuration is selected.
int16_t _CSPinConfig;

// spi instance
spi_t _spi;


typedef enum {
GET_IDX = 0,
ADD_NEW_PIN = 1
Expand Down Expand Up @@ -304,4 +304,27 @@ class SPIClass {

extern SPIClass SPI;

#if defined(SUBGHZSPI_BASE)
class SUBGHZSPIClass : public SPIClass {
public:
SUBGHZSPIClass(): SPIClass{NC, NC, NC, NC}
{
_spi.spi = SUBGHZSPI;
}

void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
void beginTransaction(uint8_t pin, SPISettings settings);
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
void enableDebugPins(uint32_t mosi = DEBUG_SUBGHZSPI_MOSI, uint32_t miso = DEBUG_SUBGHZSPI_MISO, uint32_t sclk = DEBUG_SUBGHZSPI_SCLK, uint32_t ssel = DEBUG_SUBGHZSPI_SS);

using SPIClass::beginTransaction;
using SPIClass::transfer;
using SPIClass::transfer16;
};

#endif

#endif /* _SPI_H_INCLUDED */
106 changes: 76 additions & 30 deletions libraries/SPI/src/utility/spi_com.c
Original file line number Diff line number Diff line change
Expand Up @@ -159,6 +159,12 @@ uint32_t spi_getClkFreqInst(SPI_TypeDef *spi_inst)
}
}
#endif // SPI6_BASE
#if defined(SUBGHZSPI_BASE)
if (spi_inst == SUBGHZSPI) {
/* Source CLK is APB3 (PCLK3) is derived from AHB3 clock */
spi_freq = HAL_RCC_GetHCLK3Freq();
}
#endif // SUBGHZSPI_BASE
#endif
}
return spi_freq;
Expand All @@ -175,7 +181,14 @@ uint32_t spi_getClkFreq(spi_t *obj)
uint32_t spi_freq = SystemCoreClock;

if (obj != NULL) {
spi_inst = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
#if defined(SUBGHZSPI_BASE)
if (obj->handle.Instance == SUBGHZSPI) {
spi_inst = SUBGHZSPI;
} else
#endif
{
spi_inst = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
}

if (spi_inst != NP) {
spi_freq = spi_getClkFreqInst(spi_inst);
Expand Down Expand Up @@ -224,28 +237,39 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
uint32_t spi_freq = 0;
uint32_t pull = 0;

// Determine the SPI to use
SPI_TypeDef *spi_mosi = pinmap_peripheral(obj->pin_mosi, PinMap_SPI_MOSI);
SPI_TypeDef *spi_miso = pinmap_peripheral(obj->pin_miso, PinMap_SPI_MISO);
SPI_TypeDef *spi_sclk = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
SPI_TypeDef *spi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_SPI_SSEL);
#if defined(SUBGHZSPI_BASE)
if (obj->spi != SUBGHZSPI) {
#endif
// Determine the SPI to use
SPI_TypeDef *spi_mosi = pinmap_peripheral(obj->pin_mosi, PinMap_SPI_MOSI);
SPI_TypeDef *spi_miso = pinmap_peripheral(obj->pin_miso, PinMap_SPI_MISO);
SPI_TypeDef *spi_sclk = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
SPI_TypeDef *spi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_SPI_SSEL);

/* Pins MOSI/MISO/SCLK must not be NP. ssel can be NP. */
if (spi_mosi == NP || spi_miso == NP || spi_sclk == NP) {
core_debug("ERROR: at least one SPI pin has no peripheral\n");
return;
}
/* Pins MOSI/MISO/SCLK must not be NP. ssel can be NP. */
if (spi_mosi == NP || spi_miso == NP || spi_sclk == NP) {
core_debug("ERROR: at least one SPI pin has no peripheral\n");
return;
}

SPI_TypeDef *spi_data = pinmap_merge_peripheral(spi_mosi, spi_miso);
SPI_TypeDef *spi_cntl = pinmap_merge_peripheral(spi_sclk, spi_ssel);
SPI_TypeDef *spi_data = pinmap_merge_peripheral(spi_mosi, spi_miso);
SPI_TypeDef *spi_cntl = pinmap_merge_peripheral(spi_sclk, spi_ssel);

obj->spi = pinmap_merge_peripheral(spi_data, spi_cntl);
obj->spi = pinmap_merge_peripheral(spi_data, spi_cntl);

// Are all pins connected to the same SPI instance?
if (spi_data == NP || spi_cntl == NP || obj->spi == NP) {
core_debug("ERROR: SPI pins mismatch\n");
return;
// Are all pins connected to the same SPI instance?
if (spi_data == NP || spi_cntl == NP || obj->spi == NP) {
core_debug("ERROR: SPI pins mismatch\n");
return;
}
#if defined(SUBGHZSPI_BASE)
} else {
if (obj->pin_mosi != NC || obj->pin_miso != NC || obj->pin_sclk != NC || obj->pin_ssel != NC) {
core_debug("ERROR: SUBGHZ_SPI cannot define custom pins\n");
return;
}
}
#endif

// Configure the SPI pins
if (obj->pin_ssel != NC) {
Expand All @@ -259,6 +283,7 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
handle->Init.Mode = SPI_MODE_MASTER;

spi_freq = spi_getClkFreqInst(obj->spi);
/* For SUBGHZSPI, 'SPI_BAUDRATEPRESCALER_*' == 'SUBGHZSPI_BAUDRATEPRESCALER_*' */
if (speed >= (spi_freq / SPI_SPEED_CLOCK_DIV2_MHZ)) {
handle->Init.BaudRatePrescaler = SPI_BAUDRATEPRESCALER_2;
} else if (speed >= (spi_freq / SPI_SPEED_CLOCK_DIV4_MHZ)) {
Expand Down Expand Up @@ -318,18 +343,23 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
handle->Init.MasterKeepIOState = SPI_MASTER_KEEP_IO_STATE_ENABLE; /* Recommended setting to avoid glitches */
#endif

/* Configure SPI GPIO pins */
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
pinmap_pinout(obj->pin_sclk, PinMap_SPI_SCLK);
/*
* According the STM32 Datasheet for SPI peripheral we need to PULLDOWN
* or PULLUP the SCK pin according the polarity used.
*/
pull = (handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? GPIO_PULLDOWN : GPIO_PULLUP;
pin_PullConfig(get_GPIO_Port(STM_PORT(obj->pin_sclk)), STM_LL_GPIO_PIN(obj->pin_sclk), pull);
pinmap_pinout(obj->pin_ssel, PinMap_SPI_SSEL);

#if defined(SUBGHZSPI_BASE)
if (handle->Instance != SUBGHZSPI) {
#endif
/* Configure SPI GPIO pins */
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
pinmap_pinout(obj->pin_sclk, PinMap_SPI_SCLK);
/*
* According the STM32 Datasheet for SPI peripheral we need to PULLDOWN
* or PULLUP the SCK pin according the polarity used.
*/
pull = (handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? GPIO_PULLDOWN : GPIO_PULLUP;
pin_PullConfig(get_GPIO_Port(STM_PORT(obj->pin_sclk)), STM_LL_GPIO_PIN(obj->pin_sclk), pull);
pinmap_pinout(obj->pin_ssel, PinMap_SPI_SSEL);
#if defined(SUBGHZSPI_BASE)
}
#endif
#if defined SPI1_BASE
// Enable SPI clock
if (handle->Instance == SPI1) {
Expand Down Expand Up @@ -379,6 +409,14 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
}
#endif

#if defined SUBGHZSPI_BASE
if (handle->Instance == SUBGHZSPI) {
__HAL_RCC_SUBGHZSPI_CLK_ENABLE();
__HAL_RCC_SUBGHZSPI_FORCE_RESET();
__HAL_RCC_SUBGHZSPI_RELEASE_RESET();
}
#endif

HAL_SPI_Init(handle);

/* In order to set correctly the SPI polarity we need to enable the peripheral */
Expand Down Expand Up @@ -448,6 +486,14 @@ void spi_deinit(spi_t *obj)
__HAL_RCC_SPI6_CLK_DISABLE();
}
#endif

#if defined SUBGHZSPI_BASE
if (handle->Instance == SUBGHZSPI) {
__HAL_RCC_SUBGHZSPI_FORCE_RESET();
__HAL_RCC_SUBGHZSPI_RELEASE_RESET();
__HAL_RCC_SUBGHZSPI_CLK_DISABLE();
}
#endif
}

/**
Expand Down

0 comments on commit aab7d10

Please sign in to comment.