From 295cec2ea8dbf4d3ed7dc94fdd7c5b35c68eb982 Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 29 Sep 2022 17:17:05 +0200 Subject: [PATCH 1/5] ci(stm32variant): add SUBGHZSPI support Signed-off-by: Frederic Pillon --- CI/update/stm32variant.py | 75 +++++++++++++++++++++------ CI/update/templates/variant_generic.h | 9 ++++ 2 files changed, 69 insertions(+), 15 deletions(-) diff --git a/CI/update/stm32variant.py b/CI/update/stm32variant.py index d7e01146d7..f1f1d5ff57 100644 --- a/CI/update/stm32variant.py +++ b/CI/update/stm32variant.py @@ -30,10 +30,10 @@ uartrx_list = [] # ['PIN','name','UARTrx', ['af']] uartcts_list = [] # ['PIN','name','UARTcts', ['af']] uartrts_list = [] # ['PIN','name','UARTrts', ['af']] -spimosi_list = [] # ['PIN','name','SPIMOSI', ['af']] -spimiso_list = [] # ['PIN','name','SPIMISO', ['af']] -spissel_list = [] # ['PIN','name','SPISSEL', ['af']] -spisclk_list = [] # ['PIN','name','SPISCLK', ['af']] +spimosi_list = [] # ['PIN','name','SPIMOSI', 'sort name', ['af']] +spimiso_list = [] # ['PIN','name','SPIMISO', 'sort name', ['af']] +spissel_list = [] # ['PIN','name','SPISSEL', 'sort name', ['af']] +spisclk_list = [] # ['PIN','name','SPISCLK', 'sort name', ['af']] cantd_list = [] # ['PIN','name','CANTD', ['af']] canrd_list = [] # ['PIN','name','CANRD', ['af']] eth_list = [] # ['PIN','name','ETH', ['af']] @@ -464,14 +464,14 @@ def store_uart(pin, name, signal): # Store SPI pins def store_spi(pin, name, signal): - if "_MISO" in signal: - spimiso_list.append([pin, name, signal]) - if "_MOSI" in signal: - spimosi_list.append([pin, name, signal]) - if "_SCK" in signal: - spisclk_list.append([pin, name, signal]) - if "_NSS" in signal: - spissel_list.append([pin, name, signal]) + if re.search("[-_]MISO", signal): + spimiso_list.append([pin, name, signal, signal.removeprefix("DEBUG_")]) + if re.search("[-_]MOSI", signal): + spimosi_list.append([pin, name, signal, signal.removeprefix("DEBUG_")]) + if re.search("[-_]SCK", signal): + spisclk_list.append([pin, name, signal, signal.removeprefix("DEBUG_")]) + if re.search("[-_]NSS", signal): + spissel_list.append([pin, name, signal, signal.removeprefix("DEBUG_")]) # Store CAN pins @@ -749,6 +749,7 @@ def spi_pinmap(lst): spi_pins_list = [] winst = [] wpin = [] + sp = re.compile(r"-|_") if lst == spimosi_list: aname = "SPI_MOSI" elif lst == spimiso_list: @@ -759,7 +760,9 @@ def spi_pinmap(lst): aname = "SPI_SSEL" for p in lst: # 2nd element is the SPI_XXXX signal - inst = p[2].split("_")[0] + # but using 3rd which contains the stripped one + # used to properly sort them + inst = sp.split(p[3])[0] winst.append(len(inst)) wpin.append(len(p[0])) spi_pins_list.append( @@ -767,8 +770,8 @@ def spi_pinmap(lst): "pin": p[0], "inst": inst, "mode": "STM_MODE_AF_PP", - "pull": "GPIO_PULLUP", - "af": p[3], + "pull": "GPIO_PULLUP" if inst != "SUBGHZSPI" else "GPIO_NOPULL", + "af": p[4], } ) return dict( @@ -1278,6 +1281,36 @@ def timer_variant(): return dict(tone=tone, servo=servo) +def alias_definition(): + # alias for STM32WL + alias_list = [] + if mcu_family == "STM32WL": + mosi = [ + mosi[0].replace("_", "", 1) + for mosi in spimosi_list + if "SUBGHZSPI" in mosi[2] + ] + miso = [ + miso[0].replace("_", "", 1) + for miso in spimiso_list + if "SUBGHZSPI" in miso[2] + ] + sck = [ + sck[0].replace("_", "", 1) for sck in spisclk_list if "SUBGHZSPI" in sck[2] + ] + ssel = [ + ssel[0].replace("_", "", 1) + for ssel in spissel_list + if "SUBGHZSPI" in ssel[2] + ] + if mosi and miso and sck and ssel: + alias_list.append(("DEBUG_SUBGHZSPI_MOSI", mosi[0])) + alias_list.append(("DEBUG_SUBGHZSPI_MISO", miso[0])) + alias_list.append(("DEBUG_SUBGHZSPI_SCLK", sck[0])) + alias_list.append(("DEBUG_SUBGHZSPI_SS", ssel[0])) + return alias_list + + def print_variant(generic_list, alt_syswkup_list): variant_h_template = j2_env.get_template(variant_h_filename) variant_cpp_template = j2_env.get_template(variant_cpp_filename) @@ -1299,6 +1332,9 @@ def print_variant(generic_list, alt_syswkup_list): # Timers definition timer = timer_variant() + # Alias to ease some usage + alias_list = alias_definition() + # Manage all pins number, PinName and analog pins analog_index = 0 pins_number_list = [] @@ -1379,6 +1415,7 @@ def print_variant(generic_list, alt_syswkup_list): timer=timer, serial=serial, hal_modules_list=hal_modules_list, + alias_list=alias_list, ) ) @@ -1536,6 +1573,10 @@ def natural_sortkey2(list_2_elem): return tuple(int(num) if num else alpha for num, alpha in tokenize(list_2_elem[2])) +def natural_sortkey3(list_2_elem): + return tuple(int(num) if num else alpha for num, alpha in tokenize(list_2_elem[3])) + + def sort_my_lists(): io_list.sort(key=natural_sortkey) dualpad_list.sort(key=natural_sortkey) @@ -1550,9 +1591,13 @@ def sort_my_lists(): uartrx_list.sort(key=natural_sortkey) uartcts_list.sort(key=natural_sortkey) uartrts_list.sort(key=natural_sortkey) + spimosi_list.sort(key=natural_sortkey3) spimosi_list.sort(key=natural_sortkey) + spimiso_list.sort(key=natural_sortkey3) spimiso_list.sort(key=natural_sortkey) + spissel_list.sort(key=natural_sortkey3) spissel_list.sort(key=natural_sortkey) + spisclk_list.sort(key=natural_sortkey3) spisclk_list.sort(key=natural_sortkey) cantd_list.sort(key=natural_sortkey) canrd_list.sort(key=natural_sortkey) diff --git a/CI/update/templates/variant_generic.h b/CI/update/templates/variant_generic.h index c2d8750726..8b2c96d2b4 100644 --- a/CI/update/templates/variant_generic.h +++ b/CI/update/templates/variant_generic.h @@ -99,6 +99,15 @@ #define PIN_SERIAL_TX {{serial.tx}} #endif +{% if alias_list %} +// Alias + {% for alias in alias_list %} +#ifndef {{alias[0]}} + #define {{"%-21s %s"|format(alias[0], alias[1])}} +#endif + {% endfor %} + +{% endif %} {% if hal_modules_list %} // Extra HAL modules {% for hal_module in hal_modules_list %} From 37757faf27be0642d3781b39b051e053e752261e Mon Sep 17 00:00:00 2001 From: Frederic Pillon Date: Thu, 29 Sep 2022 17:20:35 +0200 Subject: [PATCH 2/5] variant(WL): update with SUBGHZSPI debug pins Signed-off-by: Frederic Pillon --- .../PeripheralPins.c | 48 +++++++------- .../PinNamesVar.h | 3 + .../variant_GENERIC_NODE_SE_TTI.h | 17 +++++ .../variant_generic.h | 17 +++++ .../PeripheralPins.c | 64 ++++++++++--------- .../PinNamesVar.h | 3 + .../variant_NUCLEO_WL55JC1.h | 17 +++++ .../variant_generic.h | 17 +++++ variants/STM32WLxx/WL5MOCH/PeripheralPins.c | 62 +++++++++--------- variants/STM32WLxx/WL5MOCH/PinNamesVar.h | 3 + variants/STM32WLxx/WL5MOCH/variant_generic.h | 17 +++++ 11 files changed, 187 insertions(+), 81 deletions(-) diff --git a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PeripheralPins.c b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PeripheralPins.c index c8488d2ee7..cff0c71170 100644 --- a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PeripheralPins.c +++ b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PeripheralPins.c @@ -155,43 +155,47 @@ WEAK const PinMap PinMap_UART_CTS[] = { #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_MOSI[] = { - {PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {NC, NP, 0} + {PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_7_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_MISO[] = { - {PA_5, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {NC, NP, 0} + {PA_5, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_6_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_SCLK[] = { - {PA_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_8, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {NC, NP, 0} + {PA_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_5_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_8, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_SSEL[] = { - {PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_2, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_4_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_2, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif diff --git a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PinNamesVar.h b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PinNamesVar.h index 5aa6cf6543..b36a4a9d2f 100644 --- a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PinNamesVar.h +++ b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/PinNamesVar.h @@ -2,6 +2,9 @@ PA_1_ALT1 = PA_1 | ALT1, PA_2_ALT1 = PA_2 | ALT1, PA_3_ALT1 = PA_3 | ALT1, +PA_4_ALT1 = PA_4 | ALT1, +PA_5_ALT1 = PA_5 | ALT1, +PA_6_ALT1 = PA_6 | ALT1, PA_7_ALT1 = PA_7 | ALT1, PB_8_ALT1 = PB_8 | ALT1, diff --git a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_GENERIC_NODE_SE_TTI.h b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_GENERIC_NODE_SE_TTI.h index 6a340aecef..a78616b745 100644 --- a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_GENERIC_NODE_SE_TTI.h +++ b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_GENERIC_NODE_SE_TTI.h @@ -49,6 +49,9 @@ #define PA1_ALT1 (PA1 | ALT1) #define PA2_ALT1 (PA2 | ALT1) #define PA3_ALT1 (PA3 | ALT1) +#define PA4_ALT1 (PA4 | ALT1) +#define PA5_ALT1 (PA5 | ALT1) +#define PA6_ALT1 (PA6 | ALT1) #define PA7_ALT1 (PA7 | ALT1) #define PB8_ALT1 (PB8 | ALT1) @@ -123,6 +126,20 @@ #define PIN_SERIAL_TX PA2 #endif +// Alias +#ifndef DEBUG_SUBGHZSPI_MOSI + #define DEBUG_SUBGHZSPI_MOSI PA7_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_MISO + #define DEBUG_SUBGHZSPI_MISO PA6_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SCLK + #define DEBUG_SUBGHZSPI_SCLK PA5_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SS + #define DEBUG_SUBGHZSPI_SS PA4_ALT1 +#endif + // Extra HAL modules #if !defined(HAL_DAC_MODULE_DISABLED) #define HAL_DAC_MODULE_ENABLED diff --git a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_generic.h b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_generic.h index 6038da8435..144ef2cba8 100644 --- a/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_generic.h +++ b/variants/STM32WLxx/WL54CCU_WL55CCU_WLE4C(8-B-C)U_WLE5C(8-B-C)U/variant_generic.h @@ -49,6 +49,9 @@ #define PA1_ALT1 (PA1 | ALT1) #define PA2_ALT1 (PA2 | ALT1) #define PA3_ALT1 (PA3 | ALT1) +#define PA4_ALT1 (PA4 | ALT1) +#define PA5_ALT1 (PA5 | ALT1) +#define PA6_ALT1 (PA6 | ALT1) #define PA7_ALT1 (PA7 | ALT1) #define PB8_ALT1 (PB8 | ALT1) @@ -119,6 +122,20 @@ #define PIN_SERIAL_TX PA2 #endif +// Alias +#ifndef DEBUG_SUBGHZSPI_MOSI + #define DEBUG_SUBGHZSPI_MOSI PA7_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_MISO + #define DEBUG_SUBGHZSPI_MISO PA6_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SCLK + #define DEBUG_SUBGHZSPI_SCLK PA5_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SS + #define DEBUG_SUBGHZSPI_SS PA4_ALT1 +#endif + // Extra HAL modules #if !defined(HAL_DAC_MODULE_DISABLED) #define HAL_DAC_MODULE_ENABLED diff --git a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PeripheralPins.c b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PeripheralPins.c index f8a212bbe1..71bec16a32 100644 --- a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PeripheralPins.c +++ b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PeripheralPins.c @@ -179,51 +179,55 @@ WEAK const PinMap PinMap_UART_CTS[] = { #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_MOSI[] = { - {PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_15, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PC_1, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {PC_3, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_7_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_15, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_1, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {PC_3, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_MISO[] = { - {PA_5, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_14, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PC_2, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_5, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_6_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_14, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_2, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_SCLK[] = { - {PA_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_8, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PB_13, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_5_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_8, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_13, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_SSEL[] = { - {PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_2, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_4_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_2, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif diff --git a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PinNamesVar.h b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PinNamesVar.h index 9374b2016e..83bd4524b6 100644 --- a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PinNamesVar.h +++ b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/PinNamesVar.h @@ -2,6 +2,9 @@ PA_1_ALT1 = PA_1 | ALT1, PA_2_ALT1 = PA_2 | ALT1, PA_3_ALT1 = PA_3 | ALT1, +PA_4_ALT1 = PA_4 | ALT1, +PA_5_ALT1 = PA_5 | ALT1, +PA_6_ALT1 = PA_6 | ALT1, PA_7_ALT1 = PA_7 | ALT1, PB_8_ALT1 = PB_8 | ALT1, PB_9_ALT1 = PB_9 | ALT1, diff --git a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_NUCLEO_WL55JC1.h b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_NUCLEO_WL55JC1.h index dce3129a8a..58e2880e35 100644 --- a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_NUCLEO_WL55JC1.h +++ b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_NUCLEO_WL55JC1.h @@ -72,6 +72,9 @@ #define PA1_ALT1 (PA1 | ALT1) #define PA2_ALT1 (PA2 | ALT1) #define PA3_ALT1 (PA3 | ALT1) +#define PA4_ALT1 (PA4 | ALT1) +#define PA5_ALT1 (PA5 | ALT1) +#define PA6_ALT1 (PA6 | ALT1) #define PA7_ALT1 (PA7 | ALT1) #define PB8_ALT1 (PB8 | ALT1) #define PB9_ALT1 (PB9 | ALT1) @@ -121,6 +124,20 @@ #define PIN_SERIAL_TX PA2 #endif +// Alias +#ifndef DEBUG_SUBGHZSPI_MOSI + #define DEBUG_SUBGHZSPI_MOSI PA7_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_MISO + #define DEBUG_SUBGHZSPI_MISO PA6_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SCLK + #define DEBUG_SUBGHZSPI_SCLK PA5_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SS + #define DEBUG_SUBGHZSPI_SS PA4_ALT1 +#endif + #ifndef UART_WAKEUP_EXTI_LINE // For LPUART1 #define UART_WAKEUP_EXTI_LINE LL_EXTI_LINE_28 diff --git a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_generic.h b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_generic.h index 10fd4af5e5..fc1f2a61e5 100644 --- a/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_generic.h +++ b/variants/STM32WLxx/WL54JCI_WL55JCI_WLE4J(8-B-C)I_WLE5J(8-B-C)I/variant_generic.h @@ -63,6 +63,9 @@ #define PA1_ALT1 (PA1 | ALT1) #define PA2_ALT1 (PA2 | ALT1) #define PA3_ALT1 (PA3 | ALT1) +#define PA4_ALT1 (PA4 | ALT1) +#define PA5_ALT1 (PA5 | ALT1) +#define PA6_ALT1 (PA6 | ALT1) #define PA7_ALT1 (PA7 | ALT1) #define PB8_ALT1 (PB8 | ALT1) #define PB9_ALT1 (PB9 | ALT1) @@ -134,6 +137,20 @@ #define PIN_SERIAL_TX PA2 #endif +// Alias +#ifndef DEBUG_SUBGHZSPI_MOSI + #define DEBUG_SUBGHZSPI_MOSI PA7_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_MISO + #define DEBUG_SUBGHZSPI_MISO PA6_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SCLK + #define DEBUG_SUBGHZSPI_SCLK PA5_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SS + #define DEBUG_SUBGHZSPI_SS PA4_ALT1 +#endif + // Extra HAL modules #if !defined(HAL_DAC_MODULE_DISABLED) #define HAL_DAC_MODULE_ENABLED diff --git a/variants/STM32WLxx/WL5MOCH/PeripheralPins.c b/variants/STM32WLxx/WL5MOCH/PeripheralPins.c index 6d6a538cfb..0fc9d2abf9 100644 --- a/variants/STM32WLxx/WL5MOCH/PeripheralPins.c +++ b/variants/STM32WLxx/WL5MOCH/PeripheralPins.c @@ -176,50 +176,54 @@ WEAK const PinMap PinMap_UART_CTS[] = { #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_MOSI[] = { - {PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_15, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PC_1, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {NC, NP, 0} + {PA_7, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_7_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PA_12, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_15, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_1, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_MISO[] = { - {PA_5, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_14, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PC_2, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_5, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {PA_6, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_6_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_11, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_14, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PC_2, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_SCLK[] = { - {PA_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_8, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PB_13, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_1, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_5, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_5_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_8, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_3, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_10, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_13, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif #ifdef HAL_SPI_MODULE_ENABLED WEAK const PinMap PinMap_SPI_SSEL[] = { - {PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, - {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_2, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, - {PB_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, - {NC, NP, 0} + {PA_4, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PA_4_ALT1, SUBGHZSPI, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_NOPULL, GPIO_AF13_DEBUG_SUBGHZSPI)}, + {PA_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF3_SPI2)}, + {PA_15, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_2, SPI1, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI1)}, + {PB_9, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {PB_12, SPI2, STM_PIN_DATA(STM_MODE_AF_PP, GPIO_PULLUP, GPIO_AF5_SPI2)}, + {NC, NP, 0} }; #endif diff --git a/variants/STM32WLxx/WL5MOCH/PinNamesVar.h b/variants/STM32WLxx/WL5MOCH/PinNamesVar.h index 9374b2016e..83bd4524b6 100644 --- a/variants/STM32WLxx/WL5MOCH/PinNamesVar.h +++ b/variants/STM32WLxx/WL5MOCH/PinNamesVar.h @@ -2,6 +2,9 @@ PA_1_ALT1 = PA_1 | ALT1, PA_2_ALT1 = PA_2 | ALT1, PA_3_ALT1 = PA_3 | ALT1, +PA_4_ALT1 = PA_4 | ALT1, +PA_5_ALT1 = PA_5 | ALT1, +PA_6_ALT1 = PA_6 | ALT1, PA_7_ALT1 = PA_7 | ALT1, PB_8_ALT1 = PB_8 | ALT1, PB_9_ALT1 = PB_9 | ALT1, diff --git a/variants/STM32WLxx/WL5MOCH/variant_generic.h b/variants/STM32WLxx/WL5MOCH/variant_generic.h index 1bfe070b62..9e57b091f1 100644 --- a/variants/STM32WLxx/WL5MOCH/variant_generic.h +++ b/variants/STM32WLxx/WL5MOCH/variant_generic.h @@ -57,6 +57,9 @@ #define PA1_ALT1 (PA1 | ALT1) #define PA2_ALT1 (PA2 | ALT1) #define PA3_ALT1 (PA3 | ALT1) +#define PA4_ALT1 (PA4 | ALT1) +#define PA5_ALT1 (PA5 | ALT1) +#define PA6_ALT1 (PA6 | ALT1) #define PA7_ALT1 (PA7 | ALT1) #define PB8_ALT1 (PB8 | ALT1) #define PB9_ALT1 (PB9 | ALT1) @@ -128,6 +131,20 @@ #define PIN_SERIAL_TX PA2 #endif +// Alias +#ifndef DEBUG_SUBGHZSPI_MOSI + #define DEBUG_SUBGHZSPI_MOSI PA7_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_MISO + #define DEBUG_SUBGHZSPI_MISO PA6_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SCLK + #define DEBUG_SUBGHZSPI_SCLK PA5_ALT1 +#endif +#ifndef DEBUG_SUBGHZSPI_SS + #define DEBUG_SUBGHZSPI_SS PA4_ALT1 +#endif + // Extra HAL modules #if !defined(HAL_DAC_MODULE_DISABLED) #define HAL_DAC_MODULE_ENABLED From aab7d100628d89fb44500c2c6d427cc3f7605c51 Mon Sep 17 00:00:00 2001 From: Peter Lawrence <12226419+majbthrd@users.noreply.github.com> Date: Sun, 14 Aug 2022 12:32:58 -0500 Subject: [PATCH 3/5] 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 --- libraries/SPI/src/SPI.cpp | 75 ++++++++++++++++++++ libraries/SPI/src/SPI.h | 43 ++++++++--- libraries/SPI/src/utility/spi_com.c | 106 ++++++++++++++++++++-------- 3 files changed, 184 insertions(+), 40 deletions(-) diff --git a/libraries/SPI/src/SPI.cpp b/libraries/SPI/src/SPI.cpp index 0d836a0295..eab0792182 100644 --- a/libraries/SPI/src/SPI.cpp +++ b/libraries/SPI/src/SPI.cpp @@ -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 diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 72f6d59fda..91a413eeb0 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -151,7 +151,7 @@ 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 @@ -159,7 +159,7 @@ class SPIClass { * 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); @@ -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) @@ -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. */ @@ -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 @@ -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 */ diff --git a/libraries/SPI/src/utility/spi_com.c b/libraries/SPI/src/utility/spi_com.c index 32d46261dc..e00256cc4b 100644 --- a/libraries/SPI/src/utility/spi_com.c +++ b/libraries/SPI/src/utility/spi_com.c @@ -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; @@ -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); @@ -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) { @@ -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)) { @@ -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) { @@ -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 */ @@ -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 } /** From cf79dc6015c8aa23938fccc8c00e24cf0e08b241 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Tue, 20 Dec 2022 13:39:29 +0100 Subject: [PATCH 4/5] feat(SPI): Make SPISettings constructors constexpr This turns SPISettings into a "literal type" and allows variables using it to be constexpr to guarantee the constructor is executed at compiletime. This requires (with C++11) that all variables are set using initializers instead of assignments and that the regular if cascade is replaced by a ternary if. It also requires explicit initializers for all values (omitted variables were previously initialized to zero anyway). --- libraries/SPI/src/SPI.h | 43 +++++++++++++++++++---------------------- 1 file changed, 20 insertions(+), 23 deletions(-) diff --git a/libraries/SPI/src/SPI.h b/libraries/SPI/src/SPI.h index 91a413eeb0..7bde790337 100644 --- a/libraries/SPI/src/SPI.h +++ b/libraries/SPI/src/SPI.h @@ -74,29 +74,26 @@ enum SPITransferMode { class SPISettings { public: - SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE) - { - clk = clock; - bOrder = bitOrder; - noReceive = noRecv; - - if (SPI_MODE0 == dataMode) { - dMode = SPI_MODE_0; - } else if (SPI_MODE1 == dataMode) { - dMode = SPI_MODE_1; - } else if (SPI_MODE2 == dataMode) { - dMode = SPI_MODE_2; - } else if (SPI_MODE3 == dataMode) { - dMode = SPI_MODE_3; - } - } - SPISettings() - { - pinCS = -1; - clk = SPI_SPEED_CLOCK_DEFAULT; - bOrder = MSBFIRST; - dMode = SPI_MODE_0; - } + constexpr SPISettings(uint32_t clock, BitOrder bitOrder, uint8_t dataMode, bool noRecv = SPI_TRANSMITRECEIVE) + : pinCS(-1), + clk(clock), + bOrder(bitOrder), + dMode((spi_mode_e)( + (SPI_MODE0 == dataMode) ? SPI_MODE_0 : + (SPI_MODE1 == dataMode) ? SPI_MODE_1 : + (SPI_MODE2 == dataMode) ? SPI_MODE_2 : + (SPI_MODE3 == dataMode) ? SPI_MODE_3 : + SPI_MODE0 + )), + noReceive(noRecv) + { } + constexpr SPISettings() + : pinCS(-1), + clk(SPI_SPEED_CLOCK_DEFAULT), + bOrder(MSBFIRST), + dMode(SPI_MODE_0), + noReceive(SPI_TRANSMITRECEIVE) + { } private: int16_t pinCS; //CS pin associated to the configuration uint32_t clk; //specifies the spi bus maximum clock speed From b192b021dea93240b2db3b98e6b4ebc49a8996c0 Mon Sep 17 00:00:00 2001 From: Matthijs Kooijman Date: Wed, 7 Dec 2022 09:12:22 +0100 Subject: [PATCH 5/5] feat: Add SubGhz library to access SubGhz module This allows accessing some of the signals internally connected to the SubGhz radio (that would have been GPIO signals if the radio was external). This also allocates and exposes the SPI object connected to the SubGhz radio block and handles attaching handlers to the radio interrupt. Note that the DIO signals are *not* exposed, since there is no way to read them directly (and indirectly reading them through the IRQ pending flag does not work in all cases). --- libraries/SubGhz/README.md | 133 ++++++++++++++++++ .../examples/ReadRegister/ReadRegister.ino | 56 ++++++++ libraries/SubGhz/keywords.txt | 26 ++++ libraries/SubGhz/library.properties | 9 ++ libraries/SubGhz/src/SubGhz.cpp | 102 ++++++++++++++ libraries/SubGhz/src/SubGhz.h | 118 ++++++++++++++++ 6 files changed, 444 insertions(+) create mode 100644 libraries/SubGhz/README.md create mode 100644 libraries/SubGhz/examples/ReadRegister/ReadRegister.ino create mode 100644 libraries/SubGhz/keywords.txt create mode 100644 libraries/SubGhz/library.properties create mode 100644 libraries/SubGhz/src/SubGhz.cpp create mode 100644 libraries/SubGhz/src/SubGhz.h diff --git a/libraries/SubGhz/README.md b/libraries/SubGhz/README.md new file mode 100644 index 0000000000..5ab0408d37 --- /dev/null +++ b/libraries/SubGhz/README.md @@ -0,0 +1,133 @@ +## SubGhz library + +This library gives some low-level control over the SubGhz radio module +present in the STM32WL series of microcontrollers. + +This radio module is integrated into the microcontroller chip. It is +essentially a Semtech SX126x radio chip (a combination of the SX1261 and +SX1262 really), connected to a dedicated internal SPI bus. + +This library offers an Arduino-style API to access this module on a low +level, where the user is responsible for composing and sending the right +SPI commands to operate the module. It does *not* offer a high-level +interface for sending or receiving data. + +### Using this library +This library defines a single class and predefines an instance of that +class called `SubGhz`. To use this library, call methods on this +instance, e.g.: + +``` +SubGhz.setNssActive(true); +``` + +#### SPI access +Access to the dedicated SPI bus happens through the `SubGhz.SPI` object. +This behaves just like the normal Arduino SPI object (it is in fact +a customized subclass of the normal SPIClass, provided by the normal SPI +library). + +If you use the `beginTransaction()` method, you can pass the +`SubGhz.spi_settings` variable to get the right settings and run at the +maximum supported speed. If not using `beginTransaction()`, the default +settings are also fine, just a bit slower. + +#### "GPIO" signals +Some of the signals which are normally (on an actual external SX126x +radio chip) available externally and controlled by GPIO are now +internally connected to registers in the RCC and PWR modules. These +signals (Nss, Reset and Busy) can be controlled and/or read through this +library. + +The Nss signal can be written (and read back) using +`SubGhz.setNssActive(bool)` and `SubGhz.isNssActive()`, the Reset signal +using `SubGhz.setResetActive(bool)` and `SubGhz.isResetActive()` and the +busy signal can only be read using `SubGhz.isBusy()`. + +There is no need to configure these signals before using them (i.e. +nothing like `pinMode()` is needed). + +Note that there is no way to read the DIO signals directly, since they +are not directly available to the MCU anywhere (only through the +interrupt controller, so with some care the DIO signal status could be +derived from the interrupt pending status if needed). + +#### Interrupts +In addition, the DIO signals produced by the radio module are connected +together in an "OR" configuration and drive the radio interrupt. This +interrupt can be enabled and configured using various methods in this +library. + +The interrupt can be attached (and enabled) using the +`SubGhz.attachInterrupt(callback)` method. You can pass any callable here that +`std::function` accepts (global function, method bound with `std::bind`, +callable object or a lambda). Attaching an interrupt clears any +previously pending interrupts and enables the interrupt. + +The `SubGhz.detachInterrupt()` method can be used to disable the +interrupt and clear the handler and the `SubGhz.hasInterrupt()` method +can be used to query if a handler was attached (regardless of whether it +is currently enabled). + +The `SubGhz.disableInterrupt()` and `SubGhz.enableInterrupt()` method +can be used to temporarily disable the interrupt. If the interrupt is +triggered while it is disabled, it will become pending (indicated by the +`SubGhz.isInterruptPending()` method) and the interrupt handler will run +directly when the interrupt is enabled again (unless cleared with +`SubGhz.clearPendingInterrupt()`). Note that there is no method to query +whether the interrupt is currently enabled, as the interrupt controller +hardware does allow reading back this value. + +Note that there is there is hardly any point in having multiple DIO +signals, since they are all wired together into a single interrupt and +cannot be individually read, but this is just how the original Semtech +radio was designed. + +Also note that the DIO lines are directly connected to the MCU interrupt +controller (NVIC), which is level sensitive. When the ISR is triggered, +it should always either clear the interrupt flag in the radio, or +disable the interrupt in the NVIC (using `SubGhz.disableInterrupt()` in +this library) to prevent the ISR from triggering again (and again and +again etc.) after it completes. + +### Example + +This is a basic example of initializing the radio and SPI bus and +reading a register through an SPI command. See the examples folder for +a full example sketch. + +```C++ + // initialize SPI: + SubGhz.SPI.begin(); + + // clear reset to + SubGhz.setResetActive(false); + + // Start SPI transaction and wait for the radio to wake up (it starts + // in sleep mode with its busy signal active). + SubGhz.SPI.beginTransaction(SubGhz.spi_settings); + SubGhz.setNssActive(true); + while (SubGhz.isBusy()) /* wait */; + + // Write a command and read the result + SubGhz.SPI.transfer(0x1D); // Write command: Read_Register() + SubGhz.SPI.transfer(0x07); // Write MSB of register address: SUBGHZ_LSYNCRH + SubGhz.SPI.transfer(0x40); // Write LSB of register address: SUBGHZ_LSYNCRH + uint8_t status = SubGhz.SPI.transfer(0x0); // Read status + uint8_t value = SubGhz.SPI.transfer(0x0); // Read register value + + // End transaction + SubGhz.setNssActive(false); + SubGhz.SPI.endTransaction(); + + // value now has the register value read +``` + +### License +Copyright (c) 2022, STMicroelectronics +All rights reserved. + +This software component is licensed by ST under BSD 3-Clause license, +the "License"; You may not use this file except in compliance with the +License. You may obtain a copy of the License at: + opensource.org/licenses/BSD-3-Clause diff --git a/libraries/SubGhz/examples/ReadRegister/ReadRegister.ino b/libraries/SubGhz/examples/ReadRegister/ReadRegister.ino new file mode 100644 index 0000000000..80cf6123e7 --- /dev/null +++ b/libraries/SubGhz/examples/ReadRegister/ReadRegister.ino @@ -0,0 +1,56 @@ +/* + ******************************************************************************* + * Copyright (c) 2022, STMicroelectronics + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + * + * This example shows how to use the SubGhz library to start up the + * radio module and read a register through it using an SPI command. + * This reads the sync word MSB register, since that has a specific + * reset value. + */ +#include + + +void setup() { + Serial.begin(115200); + + // initialize SPI: + SubGhz.SPI.begin(); + + // clear reset to + SubGhz.setResetActive(false); + + // Start SPI transaction and wait for the radio to wake up (it starts + // in sleep mode with its busy signal active). + SubGhz.SPI.beginTransaction(SubGhz.spi_settings); + SubGhz.setNssActive(true); + while (SubGhz.isBusy()) /* wait */; + + // Write a command and read the result + SubGhz.SPI.transfer(0x1D); // Write command: Read_Register() + SubGhz.SPI.transfer(0x07); // Write MSB of register address: SUBGHZ_LSYNCRH + SubGhz.SPI.transfer(0x40); // Write LSB of register address: SUBGHZ_LSYNCRH + uint8_t status = SubGhz.SPI.transfer(0x0); // Read status + uint8_t value = SubGhz.SPI.transfer(0x0); // Read register value + + // End transaction + SubGhz.setNssActive(false); + SubGhz.SPI.endTransaction(); + + // This should print a register value 0x14 (reset value of the LoRa sync word MSB) + Serial.print("Status: 0x"); + Serial.println(status, HEX); + Serial.print("Register value: 0x"); + Serial.println(value, HEX); +} + +void loop() { + /* Nothing to do */ +} diff --git a/libraries/SubGhz/keywords.txt b/libraries/SubGhz/keywords.txt new file mode 100644 index 0000000000..ef4bff18c8 --- /dev/null +++ b/libraries/SubGhz/keywords.txt @@ -0,0 +1,26 @@ +####################################### +# Datatypes (KEYWORD1) +####################################### +callback_function_t KEYWORD1 +SubGhzClass KEYWORD1 +SubGhz KEYWORD1 + +####################################### +# Functions (KEYWORD2) +####################################### +attachInterrupt KEYWORD2 +clearPendingInterrupt KEYWORD2 +detachInterrupt KEYWORD2 +disableInterrupt KEYWORD2 +enableInterrupt KEYWORD2 +hasInterrupt KEYWORD2 +isBusy KEYWORD2 +isInterruptPending KEYWORD2 +isNssActive KEYWORD2 +isResetActive KEYWORD2 +setNssActive KEYWORD2 +setResetActive KEYWORD2 + +####################################### +# Constants (LITERAL1) +####################################### diff --git a/libraries/SubGhz/library.properties b/libraries/SubGhz/library.properties new file mode 100644 index 0000000000..f57bbbc98f --- /dev/null +++ b/libraries/SubGhz/library.properties @@ -0,0 +1,9 @@ +name=SubGhz +version=1.0.0 +author=stm32duino +maintainer=stm32duino +sentence=Allows controlling the SubGhz radio on STM32WL MCUs +paragraph=This library allows access to some internal control signals and predefines the right SPI bus to talk to the radio module. +category=Communication +url=https://github.com/stm32duino/Arduino_Core_STM32 +architectures=stm32 diff --git a/libraries/SubGhz/src/SubGhz.cpp b/libraries/SubGhz/src/SubGhz.cpp new file mode 100644 index 0000000000..b5394fd55f --- /dev/null +++ b/libraries/SubGhz/src/SubGhz.cpp @@ -0,0 +1,102 @@ +/* + ******************************************************************************* + * Copyright (c) 2022, STMicroelectronics + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +#include +#include "SubGhz.h" + +SubGhzClass SubGhz; + +extern "C" void SUBGHZ_Radio_IRQHandler(void) +{ + SubGhz.handleIrq(); +} + +constexpr SPISettings SubGhzClass::spi_settings; + +void SubGhzClass::handleIrq() +{ + if (callback) { + callback(); + } +} + +void SubGhzClass::attachInterrupt(callback_function_t callback) +{ + this->callback = callback; + HAL_NVIC_ClearPendingIRQ(SUBGHZ_Radio_IRQn); + enableInterrupt(); +} + +void SubGhzClass::detachInterrupt() +{ + disableInterrupt(); + this->callback = nullptr; +} + +bool SubGhzClass::hasInterrupt() +{ + return (bool)this->callback; +} + +void SubGhzClass::enableInterrupt() +{ + HAL_NVIC_EnableIRQ(SUBGHZ_Radio_IRQn); +} + +void SubGhzClass::disableInterrupt() +{ + HAL_NVIC_DisableIRQ(SUBGHZ_Radio_IRQn); +} + +void SubGhzClass::clearPendingInterrupt() +{ + HAL_NVIC_ClearPendingIRQ(SUBGHZ_Radio_IRQn); +} + +bool SubGhzClass::isInterruptPending() +{ + return HAL_NVIC_GetPendingIRQ(SUBGHZ_Radio_IRQn); +} + +void SubGhzClass::setNssActive(bool value) +{ + if (value) { + LL_PWR_SelectSUBGHZSPI_NSS(); + } else { + LL_PWR_UnselectSUBGHZSPI_NSS(); + } +} + +bool SubGhzClass::isNssActive() +{ + return LL_PWR_IsSUBGHZSPI_NSS_Selected(); +} + +void SubGhzClass::setResetActive(bool value) +{ + if (value) { + LL_RCC_RF_EnableReset(); + } else { + LL_RCC_RF_DisableReset(); + } +} + +bool SubGhzClass::isResetActive() +{ + return LL_RCC_RF_IsEnabledReset(); +} + +bool SubGhzClass::isBusy() +{ + return (LL_PWR_IsActiveFlag_RFBUSYS()); +} diff --git a/libraries/SubGhz/src/SubGhz.h b/libraries/SubGhz/src/SubGhz.h new file mode 100644 index 0000000000..178998ad9f --- /dev/null +++ b/libraries/SubGhz/src/SubGhz.h @@ -0,0 +1,118 @@ +/* + ******************************************************************************* + * Copyright (c) 2022, STMicroelectronics + * All rights reserved. + * + * This software component is licensed by ST under BSD 3-Clause license, + * the "License"; You may not use this file except in compliance with the + * License. You may obtain a copy of the License at: + * opensource.org/licenses/BSD-3-Clause + * + ******************************************************************************* + */ + +#ifndef __SUBGHZ_H +#define __SUBGHZ_H + +#include +#include +#include + +#if !defined(SUBGHZSPI_BASE) + #error "This board does not seem to have a SubGhz radio module, cannot use this library." +#endif + +extern "C" void SUBGHZ_Radio_IRQHandler(); + +/** + * Singleton class to manage the SubGHZ ISR and internal signals + */ +class SubGhzClass { + public: + using callback_function_t = std::function; + + // Attach the passed handler to be called (from ISR context) when + // the radio IRQ triggers, then clear any pending IRQs and enable + // it. + // + // Note that the radio IRQ is *level* triggered, so the callback + // should either disable directly process the IRQ and clear the IRQ + // flags in the radio (so the radio module clears its DIO lines + // before the ISR returns), or the callback should disable the IRQ + // to prevent it from being triggered over and over again. + void attachInterrupt(callback_function_t callback); + + // Detach the interrupt handler, disabling the IRQ too. + void detachInterrupt(); + + // Return whether an interrupt callback is currently attached + // (regardless of whether it is enabled or not). + bool hasInterrupt(); + + // Enable the interrupt again if it was previously disabled using + // disableInterrupt(). This does *not* clear any pending interrupts, + // so if the IRQ was triggered while it was disabled, this will + // cause the callback (previously registered with attachInterrupt) + // to fire directly. + void enableInterrupt(); + + // Temporarily disable interrupt processing by disabling the IRQ in + // the NVIC. + void disableInterrupt(); + + // Clear the interrupt pending flag (to suppress an IRQs that + // happened while the interrupt was disabled). + void clearPendingInterrupt(); + + // Returns whether the interrupt is currently pending (only really + // useful when the interrupt is disabled, or while some higher + // priority interrupt is currently running). + bool isInterruptPending(); + + // Update the NSS signal that is internally connected to the radio + // SPI block. + // This signal is active-low, so passing LOW activates the block, + // HIGH deactivates it. + void setNssActive(bool value); + + // Read back the value written to NSS + bool isNssActive(); + + // Update the RESET signal that is internally connected to the + // radio. Pass true to put the module in reset, or false to enable + // the module. + void setResetActive(bool value); + + // Read back the value written to RESET + bool isResetActive(); + + // Return the state of busy signal exported by the radio module. + // Note that this uses the RFBUSYS flag that returns the radio busy + // signal directly, not the RFBUSYMS flag that also returns an extra + // busy period after every SPI transaction. + bool isBusy(); + + // The SPI object that can be used to talk to the radio. Works + // like regular SPI objects, except that writeNSS() above must be + // used to control the (internal) NSS "pin". + SUBGHZSPIClass SPI; + + // SPI settings to use for the radio. This uses the maximum speed + // supported by the radio, which should always work (no chance of + // bad wiring that requires reducing the speed). + // This value should be passed to `SubGhz.SPI.beginTransaction()`. + static constexpr SPISettings spi_settings = {16000000, MSBFIRST, SPI_MODE_0}; + + protected: + // To access handleIrq() + friend void SUBGHZ_Radio_IRQHandler(); + void handleIrq(); + + private: + callback_function_t callback; +}; + +// Singleton instance, no other instances should be created +extern SubGhzClass SubGhz; + +#endif // __SUBGHZ_H