Skip to content

Commit aab7d10

Browse files
majbthrdfpistm
authored andcommitted
feat: add the STM32WL SUBGHZSPI to the SPI library
Signed-off-by: Peter Lawrence <[email protected]> Co-authored-by: Frederic Pillon <[email protected]>
1 parent 37757fa commit aab7d10

File tree

3 files changed

+184
-40
lines changed

3 files changed

+184
-40
lines changed

libraries/SPI/src/SPI.cpp

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

libraries/SPI/src/SPI.h

+33-10
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)
@@ -233,6 +233,10 @@ class SPIClass {
233233
return &(_spi.handle);
234234
}
235235

236+
protected:
237+
// spi instance
238+
spi_t _spi;
239+
236240
private:
237241
/* Contains various spiSettings for the same spi instance. Each spi spiSettings
238242
is associated to a CS pin. */
@@ -241,10 +245,6 @@ class SPIClass {
241245
// Use to know which configuration is selected.
242246
int16_t _CSPinConfig;
243247

244-
// spi instance
245-
spi_t _spi;
246-
247-
248248
typedef enum {
249249
GET_IDX = 0,
250250
ADD_NEW_PIN = 1
@@ -304,4 +304,27 @@ class SPIClass {
304304

305305
extern SPIClass SPI;
306306

307+
#if defined(SUBGHZSPI_BASE)
308+
class SUBGHZSPIClass : public SPIClass {
309+
public:
310+
SUBGHZSPIClass(): SPIClass{NC, NC, NC, NC}
311+
{
312+
_spi.spi = SUBGHZSPI;
313+
}
314+
315+
void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
316+
void beginTransaction(uint8_t pin, SPISettings settings);
317+
byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
318+
uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
319+
void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
320+
void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
321+
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);
322+
323+
using SPIClass::beginTransaction;
324+
using SPIClass::transfer;
325+
using SPIClass::transfer16;
326+
};
327+
307328
#endif
329+
330+
#endif /* _SPI_H_INCLUDED */

libraries/SPI/src/utility/spi_com.c

+76-30
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;
@@ -175,7 +181,14 @@ uint32_t spi_getClkFreq(spi_t *obj)
175181
uint32_t spi_freq = SystemCoreClock;
176182

177183
if (obj != NULL) {
178-
spi_inst = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
184+
#if defined(SUBGHZSPI_BASE)
185+
if (obj->handle.Instance == SUBGHZSPI) {
186+
spi_inst = SUBGHZSPI;
187+
} else
188+
#endif
189+
{
190+
spi_inst = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
191+
}
179192

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

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);
240+
#if defined(SUBGHZSPI_BASE)
241+
if (obj->spi != SUBGHZSPI) {
242+
#endif
243+
// Determine the SPI to use
244+
SPI_TypeDef *spi_mosi = pinmap_peripheral(obj->pin_mosi, PinMap_SPI_MOSI);
245+
SPI_TypeDef *spi_miso = pinmap_peripheral(obj->pin_miso, PinMap_SPI_MISO);
246+
SPI_TypeDef *spi_sclk = pinmap_peripheral(obj->pin_sclk, PinMap_SPI_SCLK);
247+
SPI_TypeDef *spi_ssel = pinmap_peripheral(obj->pin_ssel, PinMap_SPI_SSEL);
232248

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-
}
249+
/* Pins MOSI/MISO/SCLK must not be NP. ssel can be NP. */
250+
if (spi_mosi == NP || spi_miso == NP || spi_sclk == NP) {
251+
core_debug("ERROR: at least one SPI pin has no peripheral\n");
252+
return;
253+
}
238254

239-
SPI_TypeDef *spi_data = pinmap_merge_peripheral(spi_mosi, spi_miso);
240-
SPI_TypeDef *spi_cntl = pinmap_merge_peripheral(spi_sclk, spi_ssel);
255+
SPI_TypeDef *spi_data = pinmap_merge_peripheral(spi_mosi, spi_miso);
256+
SPI_TypeDef *spi_cntl = pinmap_merge_peripheral(spi_sclk, spi_ssel);
241257

242-
obj->spi = pinmap_merge_peripheral(spi_data, spi_cntl);
258+
obj->spi = pinmap_merge_peripheral(spi_data, spi_cntl);
243259

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;
260+
// Are all pins connected to the same SPI instance?
261+
if (spi_data == NP || spi_cntl == NP || obj->spi == NP) {
262+
core_debug("ERROR: SPI pins mismatch\n");
263+
return;
264+
}
265+
#if defined(SUBGHZSPI_BASE)
266+
} else {
267+
if (obj->pin_mosi != NC || obj->pin_miso != NC || obj->pin_sclk != NC || obj->pin_ssel != NC) {
268+
core_debug("ERROR: SUBGHZ_SPI cannot define custom pins\n");
269+
return;
270+
}
248271
}
272+
#endif
249273

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

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

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-
346+
#if defined(SUBGHZSPI_BASE)
347+
if (handle->Instance != SUBGHZSPI) {
348+
#endif
349+
/* Configure SPI GPIO pins */
350+
pinmap_pinout(obj->pin_mosi, PinMap_SPI_MOSI);
351+
pinmap_pinout(obj->pin_miso, PinMap_SPI_MISO);
352+
pinmap_pinout(obj->pin_sclk, PinMap_SPI_SCLK);
353+
/*
354+
* According the STM32 Datasheet for SPI peripheral we need to PULLDOWN
355+
* or PULLUP the SCK pin according the polarity used.
356+
*/
357+
pull = (handle->Init.CLKPolarity == SPI_POLARITY_LOW) ? GPIO_PULLDOWN : GPIO_PULLUP;
358+
pin_PullConfig(get_GPIO_Port(STM_PORT(obj->pin_sclk)), STM_LL_GPIO_PIN(obj->pin_sclk), pull);
359+
pinmap_pinout(obj->pin_ssel, PinMap_SPI_SSEL);
360+
#if defined(SUBGHZSPI_BASE)
361+
}
362+
#endif
333363
#if defined SPI1_BASE
334364
// Enable SPI clock
335365
if (handle->Instance == SPI1) {
@@ -379,6 +409,14 @@ void spi_init(spi_t *obj, uint32_t speed, spi_mode_e mode, uint8_t msb)
379409
}
380410
#endif
381411

412+
#if defined SUBGHZSPI_BASE
413+
if (handle->Instance == SUBGHZSPI) {
414+
__HAL_RCC_SUBGHZSPI_CLK_ENABLE();
415+
__HAL_RCC_SUBGHZSPI_FORCE_RESET();
416+
__HAL_RCC_SUBGHZSPI_RELEASE_RESET();
417+
}
418+
#endif
419+
382420
HAL_SPI_Init(handle);
383421

384422
/* In order to set correctly the SPI polarity we need to enable the peripheral */
@@ -448,6 +486,14 @@ void spi_deinit(spi_t *obj)
448486
__HAL_RCC_SPI6_CLK_DISABLE();
449487
}
450488
#endif
489+
490+
#if defined SUBGHZSPI_BASE
491+
if (handle->Instance == SUBGHZSPI) {
492+
__HAL_RCC_SUBGHZSPI_FORCE_RESET();
493+
__HAL_RCC_SUBGHZSPI_RELEASE_RESET();
494+
__HAL_RCC_SUBGHZSPI_CLK_DISABLE();
495+
}
496+
#endif
451497
}
452498

453499
/**

0 commit comments

Comments
 (0)