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
majbthrd and fpistm committed Nov 29, 2022
1 parent dfe6e40 commit 6a220b3
Show file tree
Hide file tree
Showing 3 changed files with 187 additions and 43 deletions.
78 changes: 78 additions & 0 deletions libraries/SPI/src/SPI.cpp
Expand Up @@ -421,3 +421,81 @@ void SPIClass::detachInterrupt(void)
{
// Should be disableInterrupt()
}

#if defined(SUBGHZSPI_BASE)
SUBGHZSPIClass SubGHZ_SPI;

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(void)
{
spi_t *obj = getSpiObj();
/* 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);
pinmap_pinout(obj->pin_ssel, PinMap_SPI_SSEL);
}
#endif
50 changes: 40 additions & 10 deletions libraries/SPI/src/SPI.h
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 @@ -227,12 +227,22 @@ class SPIClass {
void attachInterrupt(void);
void detachInterrupt(void);

spi_t *getSpiObj(void)
{
return &_spi;
}


// Could be used to mix Arduino API and STM32Cube HAL API (ex: DMA). Use at your own risk.
SPI_HandleTypeDef *getHandle(void)
{
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 +251,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 +310,28 @@ class SPIClass {

extern SPIClass SPI;

#if defined(SUBGHZSPI_BASE)
class SUBGHZSPIClass : public SPIClass {
public:
SUBGHZSPIClass(): SPIClass{DEBUG_SUBGHZSPI_MOSI, DEBUG_SUBGHZSPI_MISO, DEBUG_SUBGHZSPI_SCLK, DEBUG_SUBGHZSPI_SS}
{
_spi.spi = SUBGHZSPI;
}
SUBGHZSPIClass(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel): SPIClass{mosi, miso, sclk, ssel}
{
_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(void);
};

extern SUBGHZSPIClass SubGHZ_SPI;
#endif

#endif /* _SPI_H_INCLUDED */
102 changes: 69 additions & 33 deletions libraries/SPI/src/utility/spi_com.c
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 Down Expand Up @@ -224,41 +230,50 @@ 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 (handle->Instance != 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;
}

// Configure the SPI pins
if (obj->pin_ssel != NC) {
handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
// Configure the SPI pins
if (obj->pin_ssel != NC) {
handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
} else {
handle->Init.NSS = SPI_NSS_SOFT;
}
#if defined(SUBGHZSPI_BASE)
} else {
handle->Init.NSS = SPI_NSS_SOFT;
}
#endif

/* Fill default value */
handle->Instance = obj->spi;
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 +333,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 +399,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 +476,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 6a220b3

Please sign in to comment.