Skip to content

Commit 3c572df

Browse files
majbthrdfpistm
andcommitted
feat: add the STM32WL SUBGHZSPI to the SPI library
Signed-off-by: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Co-authored-by: Frederic Pillon <frederic.pillon@st.com>
1 parent 390dd8f commit 3c572df

File tree

3 files changed

+187
-43
lines changed

3 files changed

+187
-43
lines changed

libraries/SPI/src/SPI.cpp

Lines changed: 78 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -421,3 +421,81 @@ void SPIClass::detachInterrupt(void)
421421
{
422422
// Should be disableInterrupt()
423423
}
424+
425+
#if defined(SUBGHZSPI_BASE)
426+
SUBGHZSPIClass SubGHZ_SPI;
427+
428+
void SUBGHZSPIClass::begin(uint8_t _pin)
429+
{
430+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
431+
LL_PWR_UnselectSUBGHZSPI_NSS();
432+
}
433+
SPIClass::begin(CS_PIN_CONTROLLED_BY_USER);
434+
}
435+
436+
void SUBGHZSPIClass::beginTransaction(uint8_t _pin, SPISettings settings)
437+
{
438+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
439+
LL_PWR_UnselectSUBGHZSPI_NSS();
440+
}
441+
SPIClass::beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
442+
}
443+
444+
byte SUBGHZSPIClass::transfer(uint8_t _pin, uint8_t _data, SPITransferMode _mode)
445+
{
446+
byte res;
447+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
448+
LL_PWR_SelectSUBGHZSPI_NSS();
449+
}
450+
res = SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
451+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
452+
LL_PWR_UnselectSUBGHZSPI_NSS();
453+
}
454+
return res;
455+
}
456+
457+
uint16_t SUBGHZSPIClass::transfer16(uint8_t _pin, uint16_t _data, SPITransferMode _mode)
458+
{
459+
uint16_t rx_buffer = 0;
460+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
461+
LL_PWR_SelectSUBGHZSPI_NSS();
462+
}
463+
SPIClass::transfer16(CS_PIN_CONTROLLED_BY_USER, _data, _mode);
464+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
465+
LL_PWR_UnselectSUBGHZSPI_NSS();
466+
}
467+
return rx_buffer;
468+
}
469+
470+
void SUBGHZSPIClass::transfer(uint8_t _pin, void *_buf, size_t _count, SPITransferMode _mode)
471+
{
472+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
473+
LL_PWR_SelectSUBGHZSPI_NSS();
474+
}
475+
SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _buf, _count, _mode);
476+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
477+
LL_PWR_UnselectSUBGHZSPI_NSS();
478+
}
479+
}
480+
481+
void SUBGHZSPIClass::transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode)
482+
{
483+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
484+
LL_PWR_SelectSUBGHZSPI_NSS();
485+
}
486+
SPIClass::transfer(CS_PIN_CONTROLLED_BY_USER, _bufout, _bufin, _count, _mode);
487+
if (_pin != CS_PIN_CONTROLLED_BY_USER) {
488+
LL_PWR_UnselectSUBGHZSPI_NSS();
489+
}
490+
}
491+
492+
void SUBGHZSPIClass::enableDebugPins(void)
493+
{
494+
spi_t *obj = getSpiObj();
495+
/* Configure SPI GPIO pins */
496+
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
497+
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
498+
pinmap_pinout(obj->pin_sclk, PinMap_SPI_SCLK);
499+
pinmap_pinout(obj->pin_ssel, PinMap_SPI_SSEL);
500+
}
501+
#endif

libraries/SPI/src/SPI.h

Lines changed: 40 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -151,15 +151,15 @@ class SPIClass {
151151
_spi.pin_ssel = (ssel);
152152
};
153153

154-
void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
154+
virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
155155
void end(void);
156156

157157
/* This function should be used to configure the SPI instance in case you
158158
* don't use default parameters.
159159
* You can attach another CS pin to the SPI instance and each CS pin can be
160160
* attach with specific SPI settings.
161161
*/
162-
void beginTransaction(uint8_t pin, SPISettings settings);
162+
virtual void beginTransaction(uint8_t pin, SPISettings settings);
163163
void beginTransaction(SPISettings settings)
164164
{
165165
beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
@@ -175,10 +175,10 @@ class SPIClass {
175175
* instance with begin() or beginTransaction().
176176
* You can specify the CS pin to use.
177177
*/
178-
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
179-
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
180-
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
181-
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
178+
virtual byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
179+
virtual uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
180+
virtual void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
181+
virtual void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
182182

183183
// Transfer functions when user controls himself the CS pin.
184184
byte transfer(uint8_t _data, SPITransferMode _mode = SPI_LAST)
@@ -227,12 +227,22 @@ class SPIClass {
227227
void attachInterrupt(void);
228228
void detachInterrupt(void);
229229

230+
spi_t *getSpiObj(void)
231+
{
232+
return &_spi;
233+
}
234+
235+
230236
// Could be used to mix Arduino API and STM32Cube HAL API (ex: DMA). Use at your own risk.
231237
SPI_HandleTypeDef *getHandle(void)
232238
{
233239
return &(_spi.handle);
234240
}
235241

242+
protected:
243+
// spi instance
244+
spi_t _spi;
245+
236246
private:
237247
/* Contains various spiSettings for the same spi instance. Each spi spiSettings
238248
is associated to a CS pin. */
@@ -241,10 +251,6 @@ class SPIClass {
241251
// Use to know which configuration is selected.
242252
int16_t _CSPinConfig;
243253

244-
// spi instance
245-
spi_t _spi;
246-
247-
248254
typedef enum {
249255
GET_IDX = 0,
250256
ADD_NEW_PIN = 1
@@ -304,4 +310,28 @@ class SPIClass {
304310

305311
extern SPIClass SPI;
306312

313+
#if defined(SUBGHZSPI_BASE)
314+
class SUBGHZSPIClass : public SPIClass {
315+
public:
316+
SUBGHZSPIClass(): SPIClass{DEBUG_SUBGHZSPI_MOSI, DEBUG_SUBGHZSPI_MISO, DEBUG_SUBGHZSPI_SCLK, DEBUG_SUBGHZSPI_SS}
317+
{
318+
_spi.spi = SUBGHZSPI;
319+
}
320+
SUBGHZSPIClass(uint32_t mosi, uint32_t miso, uint32_t sclk, uint32_t ssel): SPIClass{mosi, miso, sclk, ssel}
321+
{
322+
_spi.spi = SUBGHZSPI;
323+
}
324+
325+
void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
326+
void beginTransaction(uint8_t pin, SPISettings settings);
327+
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
328+
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
329+
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
330+
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
331+
void enableDebugPins(void);
332+
};
333+
334+
extern SUBGHZSPIClass SubGHZ_SPI;
307335
#endif
336+
337+
#endif /* _SPI_H_INCLUDED */

libraries/SPI/src/utility/spi_com.c

Lines changed: 69 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,12 @@ uint32_t spi_getClkFreqInst(SPI_TypeDef *spi_inst)
159159
}
160160
}
161161
#endif // SPI6_BASE
162+
#if defined(SUBGHZSPI_BASE)
163+
if (spi_inst == SUBGHZSPI) {
164+
/* Source CLK is APB3 (PCLK3) is derived from AHB3 clock */
165+
spi_freq = HAL_RCC_GetHCLK3Freq();
166+
}
167+
#endif // SUBGHZSPI_BASE
162168
#endif
163169
}
164170
return spi_freq;
@@ -224,41 +230,50 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
224230
uint32_t spi_freq = 0;
225231
uint32_t pull = 0;
226232

227-
// Determine the SPI to use
228-
SPI_TypeDef *spi_mosi = pinmap_peripheral(obj->pin_mosi, PinMap_SPI_MOSI);
229-
SPI_TypeDef *spi_miso = pinmap_peripheral(obj->pin_miso, PinMap_SPI_MISO);
230-
SPI_TypeDef *spi_sclk = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
231-
SPI_TypeDef *spi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_SPI_SSEL);
233+
#if defined(SUBGHZSPI_BASE)
234+
if (handle->Instance != SUBGHZSPI) {
235+
#endif
236+
// Determine the SPI to use
237+
SPI_TypeDef *spi_mosi = pinmap_peripheral(obj->pin_mosi, PinMap_SPI_MOSI);
238+
SPI_TypeDef *spi_miso = pinmap_peripheral(obj->pin_miso, PinMap_SPI_MISO);
239+
SPI_TypeDef *spi_sclk = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
240+
SPI_TypeDef *spi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_SPI_SSEL);
232241

233-
/* Pins MOSI/MISO/SCLK must not be NP. ssel can be NP. */
234-
if (spi_mosi == NP || spi_miso == NP || spi_sclk == NP) {
235-
core_debug("ERROR: at least one SPI pin has no peripheral\n");
236-
return;
237-
}
242+
/* Pins MOSI/MISO/SCLK must not be NP. ssel can be NP. */
243+
if (spi_mosi == NP || spi_miso == NP || spi_sclk == NP) {
244+
core_debug("ERROR: at least one SPI pin has no peripheral\n");
245+
return;
246+
}
238247

239-
SPI_TypeDef *spi_data = pinmap_merge_peripheral(spi_mosi, spi_miso);
240-
SPI_TypeDef *spi_cntl = pinmap_merge_peripheral(spi_sclk, spi_ssel);
248+
SPI_TypeDef *spi_data = pinmap_merge_peripheral(spi_mosi, spi_miso);
249+
SPI_TypeDef *spi_cntl = pinmap_merge_peripheral(spi_sclk, spi_ssel);
241250

242-
obj->spi = pinmap_merge_peripheral(spi_data, spi_cntl);
251+
obj->spi = pinmap_merge_peripheral(spi_data, spi_cntl);
243252

244-
// Are all pins connected to the same SPI instance?
245-
if (spi_data == NP || spi_cntl == NP || obj->spi == NP) {
246-
core_debug("ERROR: SPI pins mismatch\n");
247-
return;
248-
}
253+
// Are all pins connected to the same SPI instance?
254+
if (spi_data == NP || spi_cntl == NP || obj->spi == NP) {
255+
core_debug("ERROR: SPI pins mismatch\n");
256+
return;
257+
}
249258

250-
// Configure the SPI pins
251-
if (obj->pin_ssel != NC) {
252-
handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
259+
// Configure the SPI pins
260+
if (obj->pin_ssel != NC) {
261+
handle->Init.NSS = SPI_NSS_HARD_OUTPUT;
262+
} else {
263+
handle->Init.NSS = SPI_NSS_SOFT;
264+
}
265+
#if defined(SUBGHZSPI_BASE)
253266
} else {
254267
handle->Init.NSS = SPI_NSS_SOFT;
255268
}
269+
#endif
256270

257271
/* Fill default value */
258272
handle->Instance = obj->spi;
259273
handle->Init.Mode = SPI_MODE_MASTER;
260274

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

321-
/* Configure SPI GPIO pins */
322-
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
323-
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
324-
pinmap_pinout(obj->pin_sclk, PinMap_SPI_SCLK);
325-
/*
326-
* According the STM32 Datasheet for SPI peripheral we need to PULLDOWN
327-
* or PULLUP the SCK pin according the polarity used.
328-
*/
329-
pull = (handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? GPIO_PULLDOWN : GPIO_PULLUP;
330-
pin_PullConfig(get_GPIO_Port(STM_PORT(obj->pin_sclk)), STM_LL_GPIO_PIN(obj->pin_sclk), pull);
331-
pinmap_pinout(obj->pin_ssel, PinMap_SPI_SSEL);
332-
336+
#if defined(SUBGHZSPI_BASE)
337+
if (handle->Instance != SUBGHZSPI) {
338+
#endif
339+
/* Configure SPI GPIO pins */
340+
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
341+
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
342+
pinmap_pinout(obj->pin_sclk, PinMap_SPI_SCLK);
343+
/*
344+
* According the STM32 Datasheet for SPI peripheral we need to PULLDOWN
345+
* or PULLUP the SCK pin according the polarity used.
346+
*/
347+
pull = (handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? GPIO_PULLDOWN : GPIO_PULLUP;
348+
pin_PullConfig(get_GPIO_Port(STM_PORT(obj->pin_sclk)), STM_LL_GPIO_PIN(obj->pin_sclk), pull);
349+
pinmap_pinout(obj->pin_ssel, PinMap_SPI_SSEL);
350+
#if defined(SUBGHZSPI_BASE)
351+
}
352+
#endif
333353
#if defined SPI1_BASE
334354
// Enable SPI clock
335355
if (handle->Instance == SPI1) {
@@ -379,6 +399,14 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
379399
}
380400
#endif
381401

402+
#if defined SUBGHZSPI_BASE
403+
if (handle->Instance == SUBGHZSPI) {
404+
__HAL_RCC_SUBGHZSPI_CLK_ENABLE();
405+
__HAL_RCC_SUBGHZSPI_FORCE_RESET();
406+
__HAL_RCC_SUBGHZSPI_RELEASE_RESET();
407+
}
408+
#endif
409+
382410
HAL_SPI_Init(handle);
383411

384412
/* In order to set correctly the SPI polarity we need to enable the peripheral */
@@ -448,6 +476,14 @@ void spi_deinit(spi_t *obj)
448476
__HAL_RCC_SPI6_CLK_DISABLE();
449477
}
450478
#endif
479+
480+
#if defined SUBGHZSPI_BASE
481+
if (handle->Instance == SUBGHZSPI) {
482+
__HAL_RCC_SUBGHZSPI_FORCE_RESET();
483+
__HAL_RCC_SUBGHZSPI_RELEASE_RESET();
484+
__HAL_RCC_SUBGHZSPI_CLK_DISABLE();
485+
}
486+
#endif
451487
}
452488

453489
/**

0 commit comments

Comments
 (0)