Skip to content

Commit 4ea1751

Browse files
authored
Merge pull request #1839 from fpistm/stm32wlspi
Add SUBGHZSPI support to SPI library.
2 parents 280efe1 + b192b02 commit 4ea1751

File tree

22 files changed

+904
-159
lines changed

22 files changed

+904
-159
lines changed

CI/update/stm32variant.py

+60-15
Original file line numberDiff line numberDiff line change
@@ -30,10 +30,10 @@
3030
uartrx_list = [] # ['PIN','name','UARTrx', ['af']]
3131
uartcts_list = [] # ['PIN','name','UARTcts', ['af']]
3232
uartrts_list = [] # ['PIN','name','UARTrts', ['af']]
33-
spimosi_list = [] # ['PIN','name','SPIMOSI', ['af']]
34-
spimiso_list = [] # ['PIN','name','SPIMISO', ['af']]
35-
spissel_list = [] # ['PIN','name','SPISSEL', ['af']]
36-
spisclk_list = [] # ['PIN','name','SPISCLK', ['af']]
33+
spimosi_list = [] # ['PIN','name','SPIMOSI', 'sort name', ['af']]
34+
spimiso_list = [] # ['PIN','name','SPIMISO', 'sort name', ['af']]
35+
spissel_list = [] # ['PIN','name','SPISSEL', 'sort name', ['af']]
36+
spisclk_list = [] # ['PIN','name','SPISCLK', 'sort name', ['af']]
3737
cantd_list = [] # ['PIN','name','CANTD', ['af']]
3838
canrd_list = [] # ['PIN','name','CANRD', ['af']]
3939
eth_list = [] # ['PIN','name','ETH', ['af']]
@@ -464,14 +464,14 @@ def store_uart(pin, name, signal):
464464

465465
# Store SPI pins
466466
def store_spi(pin, name, signal):
467-
if "_MISO" in signal:
468-
spimiso_list.append([pin, name, signal])
469-
if "_MOSI" in signal:
470-
spimosi_list.append([pin, name, signal])
471-
if "_SCK" in signal:
472-
spisclk_list.append([pin, name, signal])
473-
if "_NSS" in signal:
474-
spissel_list.append([pin, name, signal])
467+
if re.search("[-_]MISO", signal):
468+
spimiso_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])
469+
if re.search("[-_]MOSI", signal):
470+
spimosi_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])
471+
if re.search("[-_]SCK", signal):
472+
spisclk_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])
473+
if re.search("[-_]NSS", signal):
474+
spissel_list.append([pin, name, signal, signal.removeprefix("DEBUG_")])
475475

476476

477477
# Store CAN pins
@@ -749,6 +749,7 @@ def spi_pinmap(lst):
749749
spi_pins_list = []
750750
winst = []
751751
wpin = []
752+
sp = re.compile(r"-|_")
752753
if lst == spimosi_list:
753754
aname = "SPI_MOSI"
754755
elif lst == spimiso_list:
@@ -759,16 +760,18 @@ def spi_pinmap(lst):
759760
aname = "SPI_SSEL"
760761
for p in lst:
761762
# 2nd element is the SPI_XXXX signal
762-
inst = p[2].split("_")[0]
763+
# but using 3rd which contains the stripped one
764+
# used to properly sort them
765+
inst = sp.split(p[3])[0]
763766
winst.append(len(inst))
764767
wpin.append(len(p[0]))
765768
spi_pins_list.append(
766769
{
767770
"pin": p[0],
768771
"inst": inst,
769772
"mode": "STM_MODE_AF_PP",
770-
"pull": "GPIO_PULLUP",
771-
"af": p[3],
773+
"pull": "GPIO_PULLUP" if inst != "SUBGHZSPI" else "GPIO_NOPULL",
774+
"af": p[4],
772775
}
773776
)
774777
return dict(
@@ -1278,6 +1281,36 @@ def timer_variant():
12781281
return dict(tone=tone, servo=servo)
12791282

12801283

1284+
def alias_definition():
1285+
# alias for STM32WL
1286+
alias_list = []
1287+
if mcu_family == "STM32WL":
1288+
mosi = [
1289+
mosi[0].replace("_", "", 1)
1290+
for mosi in spimosi_list
1291+
if "SUBGHZSPI" in mosi[2]
1292+
]
1293+
miso = [
1294+
miso[0].replace("_", "", 1)
1295+
for miso in spimiso_list
1296+
if "SUBGHZSPI" in miso[2]
1297+
]
1298+
sck = [
1299+
sck[0].replace("_", "", 1) for sck in spisclk_list if "SUBGHZSPI" in sck[2]
1300+
]
1301+
ssel = [
1302+
ssel[0].replace("_", "", 1)
1303+
for ssel in spissel_list
1304+
if "SUBGHZSPI" in ssel[2]
1305+
]
1306+
if mosi and miso and sck and ssel:
1307+
alias_list.append(("DEBUG_SUBGHZSPI_MOSI", mosi[0]))
1308+
alias_list.append(("DEBUG_SUBGHZSPI_MISO", miso[0]))
1309+
alias_list.append(("DEBUG_SUBGHZSPI_SCLK", sck[0]))
1310+
alias_list.append(("DEBUG_SUBGHZSPI_SS", ssel[0]))
1311+
return alias_list
1312+
1313+
12811314
def print_variant(generic_list, alt_syswkup_list):
12821315
variant_h_template = j2_env.get_template(variant_h_filename)
12831316
variant_cpp_template = j2_env.get_template(variant_cpp_filename)
@@ -1299,6 +1332,9 @@ def print_variant(generic_list, alt_syswkup_list):
12991332
# Timers definition
13001333
timer = timer_variant()
13011334

1335+
# Alias to ease some usage
1336+
alias_list = alias_definition()
1337+
13021338
# Manage all pins number, PinName and analog pins
13031339
analog_index = 0
13041340
pins_number_list = []
@@ -1379,6 +1415,7 @@ def print_variant(generic_list, alt_syswkup_list):
13791415
timer=timer,
13801416
serial=serial,
13811417
hal_modules_list=hal_modules_list,
1418+
alias_list=alias_list,
13821419
)
13831420
)
13841421

@@ -1536,6 +1573,10 @@ def natural_sortkey2(list_2_elem):
15361573
return tuple(int(num) if num else alpha for num, alpha in tokenize(list_2_elem[2]))
15371574

15381575

1576+
def natural_sortkey3(list_2_elem):
1577+
return tuple(int(num) if num else alpha for num, alpha in tokenize(list_2_elem[3]))
1578+
1579+
15391580
def sort_my_lists():
15401581
io_list.sort(key=natural_sortkey)
15411582
dualpad_list.sort(key=natural_sortkey)
@@ -1550,9 +1591,13 @@ def sort_my_lists():
15501591
uartrx_list.sort(key=natural_sortkey)
15511592
uartcts_list.sort(key=natural_sortkey)
15521593
uartrts_list.sort(key=natural_sortkey)
1594+
spimosi_list.sort(key=natural_sortkey3)
15531595
spimosi_list.sort(key=natural_sortkey)
1596+
spimiso_list.sort(key=natural_sortkey3)
15541597
spimiso_list.sort(key=natural_sortkey)
1598+
spissel_list.sort(key=natural_sortkey3)
15551599
spissel_list.sort(key=natural_sortkey)
1600+
spisclk_list.sort(key=natural_sortkey3)
15561601
spisclk_list.sort(key=natural_sortkey)
15571602
cantd_list.sort(key=natural_sortkey)
15581603
canrd_list.sort(key=natural_sortkey)

CI/update/templates/variant_generic.h

+9
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,15 @@
9999
#define PIN_SERIAL_TX {{serial.tx}}
100100
#endif
101101

102+
{% if alias_list %}
103+
// Alias
104+
{% for alias in alias_list %}
105+
#ifndef {{alias[0]}}
106+
#define {{"%-21s %s"|format(alias[0], alias[1])}}
107+
#endif
108+
{% endfor %}
109+
110+
{% endif %}
102111
{% if hal_modules_list %}
103112
// Extra HAL modules
104113
{% for hal_module in hal_modules_list %}

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

+53-33
Original file line numberDiff line numberDiff line change
@@ -74,29 +74,26 @@ enum SPITransferMode {
7474

7575
class SPISettings {
7676
public:
77-
SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE)
78-
{
79-
clk = clock;
80-
bOrder = bitOrder;
81-
noReceive = noRecv;
82-
83-
if (SPI_MODE0 == dataMode) {
84-
dMode = SPI_MODE_0;
85-
} else if (SPI_MODE1 == dataMode) {
86-
dMode = SPI_MODE_1;
87-
} else if (SPI_MODE2 == dataMode) {
88-
dMode = SPI_MODE_2;
89-
} else if (SPI_MODE3 == dataMode) {
90-
dMode = SPI_MODE_3;
91-
}
92-
}
93-
SPISettings()
94-
{
95-
pinCS = -1;
96-
clk = SPI_SPEED_CLOCK_DEFAULT;
97-
bOrder = MSBFIRST;
98-
dMode = SPI_MODE_0;
99-
}
77+
constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE)
78+
: pinCS(-1),
79+
clk(clock),
80+
bOrder(bitOrder),
81+
dMode((spi_mode_e)(
82+
(SPI_MODE0 == dataMode) ? SPI_MODE_0 :
83+
(SPI_MODE1 == dataMode) ? SPI_MODE_1 :
84+
(SPI_MODE2 == dataMode) ? SPI_MODE_2 :
85+
(SPI_MODE3 == dataMode) ? SPI_MODE_3 :
86+
SPI_MODE0
87+
)),
88+
noReceive(noRecv)
89+
{ }
90+
constexpr SPISettings()
91+
: pinCS(-1),
92+
clk(SPI_SPEED_CLOCK_DEFAULT),
93+
bOrder(MSBFIRST),
94+
dMode(SPI_MODE_0),
95+
noReceive(SPI_TRANSMITRECEIVE)
96+
{ }
10097
private:
10198
int16_t pinCS; //CS pin associated to the configuration
10299
uint32_t clk; //specifies the spi bus maximum clock speed
@@ -151,15 +148,15 @@ class SPIClass {
151148
_spi.pin_ssel = (ssel);
152149
};
153150

154-
void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
151+
virtual void begin(uint8_t _pin = CS_PIN_CONTROLLED_BY_USER);
155152
void end(void);
156153

157154
/* This function should be used to configure the SPI instance in case you
158155
* don't use default parameters.
159156
* You can attach another CS pin to the SPI instance and each CS pin can be
160157
* attach with specific SPI settings.
161158
*/
162-
void beginTransaction(uint8_t pin, SPISettings settings);
159+
virtual void beginTransaction(uint8_t pin, SPISettings settings);
163160
void beginTransaction(SPISettings settings)
164161
{
165162
beginTransaction(CS_PIN_CONTROLLED_BY_USER, settings);
@@ -175,10 +172,10 @@ class SPIClass {
175172
* instance with begin() or beginTransaction().
176173
* You can specify the CS pin to use.
177174
*/
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);
175+
virtual byte transfer(uint8_t pin, uint8_t _data, SPITransferMode _mode = SPI_LAST);
176+
virtual uint16_t transfer16(uint8_t pin, uint16_t _data, SPITransferMode _mode = SPI_LAST);
177+
virtual void transfer(uint8_t pin, void *_buf, size_t _count, SPITransferMode _mode = SPI_LAST);
178+
virtual void transfer(byte _pin, void *_bufout, void *_bufin, size_t _count, SPITransferMode _mode = SPI_LAST);
182179

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

233+
protected:
234+
// spi instance
235+
spi_t _spi;
236+
236237
private:
237238
/* Contains various spiSettings for the same spi instance. Each spi spiSettings
238239
is associated to a CS pin. */
@@ -241,10 +242,6 @@ class SPIClass {
241242
// Use to know which configuration is selected.
242243
int16_t _CSPinConfig;
243244

244-
// spi instance
245-
spi_t _spi;
246-
247-
248245
typedef enum {
249246
GET_IDX = 0,
250247
ADD_NEW_PIN = 1
@@ -304,4 +301,27 @@ class SPIClass {
304301

305302
extern SPIClass SPI;
306303

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

0 commit comments

Comments
 (0)