diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index 4c90c6f1ef..dd86f1e3f3 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -353,8 +353,6 @@ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ hal_flash_ex.c \ hal_gpio.c \ hal_i2c.c \ - hal_pcd.c \ - hal_pcd_ex.c \ hal_pwr.c \ hal_pwr_ex.c \ hal_rcc.c \ @@ -368,8 +366,10 @@ HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ ll_utils.c \ ) -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4 wb)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 g4 h7 l0 l4 wb)) HAL_SRC_C += $(addprefix $(STM32LIB_HAL_BASE)/Src/stm32$(MCU_SERIES)xx_,\ + hal_pcd.c \ + hal_pcd_ex.c \ ll_usb.c \ ) endif diff --git a/ports/stm32/adc.h b/ports/stm32/adc.h index db706ea494..3b79dc01f5 100644 --- a/ports/stm32/adc.h +++ b/ports/stm32/adc.h @@ -56,6 +56,8 @@ static inline void adc_deselect_vbat(ADC_TypeDef *adc, uint32_t channel) { adc_common = adc == ADC3 ? ADC3_COMMON : ADC12_COMMON; #elif defined(STM32L4) adc_common = __LL_ADC_COMMON_INSTANCE(0); + #elif defined(STM32WL) + adc_common = ADC_COMMON; #endif adc_common->CCR &= ~LL_ADC_PATH_INTERNAL_VBAT; diff --git a/ports/stm32/boards/stm32wl55_af.csv b/ports/stm32/boards/stm32wl55_af.csv new file mode 100644 index 0000000000..219b8b08b7 --- /dev/null +++ b/ports/stm32/boards/stm32wl55_af.csv @@ -0,0 +1,45 @@ +Port,,AF0,AF1,AF2,AF3,AF4,AF5,AF6,AF7,AF8,AF9,AF10,AF11,AF12,AF13,AF14,AF15, +,,SYS_AF,TIM1/TIM2/LPTIM1,TIM1/TIM2,SPI2S2/TIM1/LPTIM3,I2C1/I2C2/I2C3,SPI1/SPI2S2,RF,USART1/USART2,LPUART1,,,,COMP1/COMP2/TIM1,DEBUG,TIM2/TIM16/TIM17/LPTIM2,EVENOUT,ADC +PortA,PA0,,TIM2_CH1,,,I2C3_SMBA,I2S_CKIN,,USART2_CTS,,,,,COMP1_OUT,DEBUG_PWR_REGLP1S,TIM2_ETR,EVENTOUT,ADC123_IN0 +PortA,PA1,,TIM2_CH2,,LPTIM3_OUT,I2C1_SMBA,SPI1_SCK,,USART2_RTS,LPUART1_RTS,,,,,DEBUG_PWR_REGLP2S,,EVENTOUT,ADC123_IN1 +PortA,PA2,LSCO,TIM2_CH3,,,,,,USART2_TX,LPUART1_TX,,,,COMP2_OUT,DEBUG_PWR_LDORDY,,EVENTOUT,ADC123_IN2 +PortA,PA3,,TIM2_CH4,,,,I2S2_MCK,,USART2_RX,LPUART1_RX,,,,,,,EVENTOUT,ADC123_IN3 +PortA,PA4,RTC_OUT2,LPTIM1_OUT,,,,SPI1_NSS,,USART2_CK,,,,,,DEBUG_SUBGHZSPI_NSSOUT,LPTIM2_OUT,EVENTOUT,ADC12_IN4 +PortA,PA5,,TIM2_CH1,TIM2_ETR,SPI2_MISO,,SPI1_SCK,,,,,,,,DEBUG_SUBGHZSPI_SCKOUT,LPTIM2_ETR,EVENTOUT,ADC12_IN5 +PortA,PA6,,TIM1_BKIN,,,I2C2_SMBA,SPI1_MISO,,,LPUART1_CTS,,,,TIM1_BKIN,DEBUG_SUBGHZSPI_MISOOUT,TIM16_CH1,EVENTOUT,ADC12_IN6 +PortA,PA7,,TIM1_CH1N,,,I2C3_SCL,SPI1_MOSI,,,,,,,COMP2_OUT,DEBUG_SUBGHZSPI_MOSIOUT,TIM17_CH1,EVENTOUT,ADC12_IN7 +PortA,PA8,MCO,TIM1_CH1,,,,SPI2_SCK/I2S2_CK,,USART1_CK,,,,,,,LPTIM2_OUT,EVENTOUT, +PortA,PA9,,TIM1_CH2,,SPI2_NSS/I2S2_WS,I2C1_SCL,SPI2_SCK/I2S2_CK,,USART1_TX,,,,,,,,EVENTOUT, +PortA,PA10,RTC_REFIN,TIM1_CH3,,,I2C1_SDA,SPI2_MOSI/I2S2_SD,,USART1_RX,,,,,,DEBUG_RF_HSE32RDY,TIM17_BKIN,EVENTOUT, +PortA,PA11,,TIM1_CH4,TIM1_BKIN2,LPTIM3_ETR,I2C2_SDA,SPI1_MISO,,USART1_CTS,,,,,TIM1_BKIN2,DEBUG_RF_NRESET,,EVENTOUT, +PortA,PA12,,TIM1_ETR,,LPTIM3_IN1,I2C2_SCL,SPI1_MOSI,RF_BUSY,USART1_RTS,,,,,,,,EVENTOUT, +PortA,PA13,JTMS/SWDIO,,,,I2C2_SMBA,,,,IR_OUT,,,,,,,EVENTOUT, +PortA,PA14,JTCK/SWCLK,LPTIM1_OUT,,,I2C1_SMBA,,,,,,,,,,,EVENTOUT, +PortA,PA15,JTDI,TIM2_CH1,TIM2_ETR,,I2C2_SDA,SPI1_NSS,,,,,,,,,,EVENTOUT, +PortB,PB0,,,,,,,,,,,,,COMP1_OUT,,,EVENTOUT,ADC12_IN8 +PortB,PB1,,,,,,,,,LPUART1_RTS_DE,,,,,,LPTIM2_IN1,EVENTOUT,ADC12_IN9 +PortB,PB2,,LPTIM1_OUT,,,I2C3_SMBA,SPI1_NSS,,,,,,,,DEBUG_RF_SMPSRDY,,EVENTOUT, +PortB,PB3,JTDO/TRACESWO,TIM2_CH2,,,,SPI1_SCK,RF_IRQ0,USART1_RTS,,,,,,DEBUG_RF_DTB1,,EVENTOUT, +PortB,PB4,NJTRST,,,,I2C3_SDA,SPI1_MISO,,USART1_CTS,,,,,,DEBUG_RF_LDORDY,TIM17_BKIN,EVENTOUT, +PortB,PB5,,LPTIM1_IN1,,,I2C1_SMBA,SPI1_MOSI,RF_IRQ1,USART1_CK,,,,,COMP2_OUT,,TIM16_BKIN,EVENTOUT, +PortB,PB6,,LPTIM1_ETR,,,I2C1_SCL,,,USART1_TX,,,,,,,TIM16_CH1N,EVENTOUT, +PortB,PB7,,LPTIM1_IN2,,TIM1_BKIN,I2C1_SDA,,,USART1_RX,,,,,,,TIM17_CH1N,EVENTOUT, +PortB,PB8,,TIM1_CH2N,,,I2C1_SCL,,RF_IRQ2,,,,,,,,TIM16_CH1,EVENTOUT, +PortB,PB9,,TIM1_CH3N,,,I2C1_SDA,SPI2_NSS/I2S2_WS,,,IR_OUT,,,,,,TIM17_CH1,EVENTOUT, +PortB,PB10,,TIM2_CH3,,,I2C3_SCL,SPI2_SCK/I2S2_CK,,,LPUART1_RX,,,,COMP1_OUT,,,EVENTOUT, +PortB,PB11,,TIM2_CH4,,,I2C3_SDA,,,,LPUART1_TX,,,,COMP2_OUT,,,EVENTOUT, +PortB,PB12,,TIM1_BKIN,,TIM1_BKIN,I2C3_SMBA,SPI2_NSS/I2S2_WS,,,LPUART1_RTS,,,,,,,EVENTOUT, +PortB,PB13,,TIM1_CH1N,,,I2C3_SCL,SPI2_SCK/I2S2_CK,,,LPUART1_CTS,,,,,,,EVENTOUT, +PortB,PB14,,TIM1_CH2N,,I2S2_MCK,I2C3_SDA,SPI2_MISO,,,,,,,,,,EVENTOUT, +PortB,PB15,,TIM1_CH3N,,,I2C2_SCL,SPI2_MOSI/I2S2_SD,,,,,,,,,,EVENTOUT, +PortC,PC0,,LPTIM1_IN1,,,I2C3_SCL,,,,LPUART1_RX,,,,,,LPTIM2_IN1,EVENTOUT,ADC123_IN10 +PortC,PC1,,LPTIM1_OUT,,SPI2_MOSI/I2S2_SD,I2C3_SDA,,,,LPUART1_TX,,,,,,,EVENTOUT,ADC123_IN11 +PortC,PC2,,LPTIM1_IN2,,,,SPI2_MISO,,,,,,,,,,EVENTOUT,ADC123_IN12 +PortC,PC3,,LPTIM1_ETR,,,,SPI2_MOSI/I2S2_SD,,,,,,,,,LPTIM2_ETR,EVENTOUT,ADC123_IN13 +PortC,PC4,,,,,,,,,,,,,,,,EVENTOUT,ADC12_IN14 +PortC,PC5,,,,,,,,,,,,,,,,EVENTOUT,ADC12_IN15 +PortC,PC6,,,,,,I2S2_MCK,,,,,,,,,,EVENTOUT, +PortC,PC13,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC14,,,,,,,,,,,,,,,,EVENTOUT, +PortC,PC15,,,,,,,,,,,,,,,,EVENTOUT, +PortH,PH3,,,,,,,,,,,,,,,,EVENTOUT, diff --git a/ports/stm32/boards/stm32wl55xc.ld b/ports/stm32/boards/stm32wl55xc.ld new file mode 100644 index 0000000000..109675bb5e --- /dev/null +++ b/ports/stm32/boards/stm32wl55xc.ld @@ -0,0 +1,34 @@ +/* + GNU linker script for STM32WL55xC +*/ + +/* Specify the memory areas */ +MEMORY +{ + FLASH (rx) : ORIGIN = 0x08000000, LENGTH = 256K /* sectors 0-127 */ + FLASH_APP (rx) : ORIGIN = 0x08000000, LENGTH = 232K /* sectors 0-115 */ + FLASH_FS (r) : ORIGIN = 0x0803a000, LENGTH = 24K /* sectors 116-127 */ + RAM (xrw) : ORIGIN = 0x20000000, LENGTH = 64K /* SRAM1+SRAM2 */ +} + +/* produce a link error if there is not this amount of RAM for these sections */ +_minimum_stack_size = 2K; +_minimum_heap_size = 16K; + +/* RAM extents for the garbage collector */ +_ram_start = ORIGIN(RAM); +_ram_end = ORIGIN(RAM) + LENGTH(RAM); + +_micropy_hw_internal_flash_storage_ram_cache_end = ORIGIN(RAM) + LENGTH(RAM); +_micropy_hw_internal_flash_storage_ram_cache_start = _micropy_hw_internal_flash_storage_ram_cache_end - 2K; /* fs cache = 2K */ + +/* Define the stack. The stack is full descending so begins at the bottom of FS cache. + Note that EABI requires the stack to be 8-byte aligned for a call. */ +_estack = _micropy_hw_internal_flash_storage_ram_cache_start - _estack_reserve; +_sstack = _estack - 6K; + +_heap_start = _ebss; /* heap starts just after statically allocated memory */ +_heap_end = _sstack; + +_micropy_hw_internal_flash_storage_start = ORIGIN(FLASH_FS); +_micropy_hw_internal_flash_storage_end = ORIGIN(FLASH_FS) + LENGTH(FLASH_FS); diff --git a/ports/stm32/boards/stm32wlxx_hal_conf_base.h b/ports/stm32/boards/stm32wlxx_hal_conf_base.h new file mode 100644 index 0000000000..e98b0525bd --- /dev/null +++ b/ports/stm32/boards/stm32wlxx_hal_conf_base.h @@ -0,0 +1,78 @@ +/* + * This file is part of the MicroPython project, http://micropython.org/ + * + * The MIT License (MIT) + * + * Copyright (c) 2021 Damien P. George + * + * Permission is hereby granted, free of charge, to any person obtaining a copy + * of this software and associated documentation files (the "Software"), to deal + * in the Software without restriction, including without limitation the rights + * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell + * copies of the Software, and to permit persons to whom the Software is + * furnished to do so, subject to the following conditions: + * + * The above copyright notice and this permission notice shall be included in + * all copies or substantial portions of the Software. + * + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE + * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN + * THE SOFTWARE. + */ +#ifndef MICROPY_INCLUDED_STM32WLXX_HAL_CONF_BASE_H +#define MICROPY_INCLUDED_STM32WLXX_HAL_CONF_BASE_H + +// Include various HAL modules for convenience +#include "stm32wlxx_hal_dma.h" +#include "stm32wlxx_hal_adc.h" +#include "stm32wlxx_hal_cortex.h" +#include "stm32wlxx_hal_flash.h" +#include "stm32wlxx_hal_gpio.h" +#include "stm32wlxx_hal_i2c.h" +#include "stm32wlxx_hal_pwr.h" +#include "stm32wlxx_hal_rcc.h" +#include "stm32wlxx_hal_rtc.h" +#include "stm32wlxx_hal_spi.h" +#include "stm32wlxx_hal_tim.h" +#include "stm32wlxx_hal_uart.h" +#include "stm32wlxx_hal_usart.h" +#include "stm32wlxx_ll_adc.h" +#include "stm32wlxx_ll_lpuart.h" +#include "stm32wlxx_ll_rtc.h" +#include "stm32wlxx_ll_usart.h" + +// Enable various HAL modules +#define HAL_MODULE_ENABLED +#define HAL_CORTEX_MODULE_ENABLED +#define HAL_DMA_MODULE_ENABLED +#define HAL_FLASH_MODULE_ENABLED +#define HAL_GPIO_MODULE_ENABLED +#define HAL_PWR_MODULE_ENABLED +#define HAL_RCC_MODULE_ENABLED +#define HAL_RTC_MODULE_ENABLED +#define HAL_SPI_MODULE_ENABLED +#define HAL_TIM_MODULE_ENABLED +#define HAL_UART_MODULE_ENABLED +#define HAL_USART_MODULE_ENABLED + +// Oscillator values in Hz +#define MSI_VALUE (4000000) + +// SysTick has the highest priority +#define TICK_INT_PRIORITY (0x00) + +// Miscellaneous HAL settings +#define DATA_CACHE_ENABLE 1 +#define INSTRUCTION_CACHE_ENABLE 1 +#define PREFETCH_ENABLE 0 +#define USE_SPI_CRC 0 +#define USE_RTOS 0 + +// HAL parameter assertions are disabled +#define assert_param(expr) ((void)0) + +#endif // MICROPY_INCLUDED_STM32WLXX_HAL_CONF_BASE_H diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index dc706e68aa..75c34325d7 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -74,7 +74,7 @@ typedef union { struct _dma_descr_t { #if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) DMA_Stream_TypeDef *instance; - #elif defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32F0) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) DMA_Channel_TypeDef *instance; #else #error "Unsupported Processor" @@ -89,7 +89,7 @@ struct _dma_descr_t { static const DMA_InitTypeDef dma_init_struct_spi_i2c = { #if defined(STM32F4) || defined(STM32F7) .Channel = 0, - #elif defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) .Request = 0, #endif .Direction = 0, @@ -467,7 +467,7 @@ static const uint8_t dma_irqn[NSTREAM] = { DMA2_Channel7_IRQn, }; -#elif defined(STM32WB) +#elif defined(STM32WB) || defined(STM32WL) #define NCONTROLLERS (2) #define NSTREAMS_PER_CONTROLLER (7) @@ -1152,7 +1152,7 @@ void dma_init_handle(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint3 dma->Instance = dma_descr->instance; dma->Init = *dma_descr->init; dma->Init.Direction = dir; - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) dma->Init.Request = dma_descr->sub_instance; #else #if !defined(STM32F0) @@ -1179,7 +1179,7 @@ void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir dma_enable_clock(dma_id); - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) // Always reset and configure the H7 and L0/L4 DMA peripheral // (dma->State is set to HAL_DMA_STATE_RESET by memset above) // TODO: understand how L0/L4 DMA works so this is not needed @@ -1353,7 +1353,7 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a dma->CCR |= DMA_CCR_EN; } -#elif defined(STM32WB) +#elif defined(STM32WB) || defined(STM32WL) // These functions are currently not implemented or needed for this MCU. diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 29d5c3d2eb..9b0b4c77a6 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -100,7 +100,7 @@ extern const dma_descr_t dma_I2C_2_RX; extern const dma_descr_t dma_I2C_1_TX; extern const dma_descr_t dma_I2C_1_RX; -#elif defined(STM32L4) || defined(STM32WB) +#elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL) extern const dma_descr_t dma_ADC_1_RX; extern const dma_descr_t dma_ADC_2_RX; diff --git a/ports/stm32/extint.c b/ports/stm32/extint.c index bb26b00dde..55c9095f11 100644 --- a/ports/stm32/extint.c +++ b/ports/stm32/extint.c @@ -91,7 +91,7 @@ #define EXTI_SWIER_BB(line) (*(__IO uint32_t *)(PERIPH_BB_BASE + ((EXTI_OFFSET + offsetof(EXTI_TypeDef, SWIER)) * 32) + ((line) * 4))) #endif -#if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) +#if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) // The L4 MCU supports 40 Events/IRQs lines of the type configurable and direct. // Here we only support configurable line types. Details, see page 330 of RM0351, Rev 1. // The USB_FS_WAKUP event is a direct type and there is no support for it. @@ -181,6 +181,12 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { RTC_Alarm_IRQn, TAMP_STAMP_LSECSS_IRQn, RTC_WKUP_IRQn, + #elif defined(STM32WL) + PVD_PVM_IRQn, + RTC_Alarm_IRQn, + TAMP_STAMP_LSECSS_SSRU_IRQn, // SSRU + TAMP_STAMP_LSECSS_SSRU_IRQn, // TAMP, RTC_STAMP, LSE_CSS + RTC_WKUP_IRQn, #else #if defined(STM32G4) || defined(STM32L4) PVD_PVM_IRQn, @@ -308,7 +314,7 @@ void extint_register_pin(const pin_obj_t *pin, uint32_t mode, bool hard_irq, mp_ pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI - #if !defined(STM32WB) + #if !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif SYSCFG->EXTICR[line >> 2] = @@ -345,7 +351,7 @@ void extint_set(const pin_obj_t *pin, uint32_t mode) { pyb_extint_callback_arg[line] = MP_OBJ_FROM_PTR(pin); // Route the GPIO to EXTI - #if !defined(STM32WB) + #if !defined(STM32WB) && !defined(STM32WL) __HAL_RCC_SYSCFG_CLK_ENABLE(); #endif SYSCFG->EXTICR[line >> 2] = @@ -385,7 +391,7 @@ void extint_enable(uint line) { if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { #if defined(STM32H7) EXTI_D1->IMR1 |= (1 << line); - #elif defined(STM32G4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= (1 << line); #else EXTI->IMR |= (1 << line); @@ -393,7 +399,7 @@ void extint_enable(uint line) { } else { #if defined(STM32H7) EXTI_D1->EMR1 |= (1 << line); - #elif defined(STM32G4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32WB) || defined(STM32WL) EXTI->EMR1 |= (1 << line); #else EXTI->EMR |= (1 << line); @@ -419,7 +425,7 @@ void extint_disable(uint line) { #if defined(STM32H7) EXTI_D1->IMR1 &= ~(1 << line); EXTI_D1->EMR1 &= ~(1 << line); - #elif defined(STM32G4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 &= ~(1 << line); EXTI->EMR1 &= ~(1 << line); #else @@ -441,7 +447,7 @@ void extint_swint(uint line) { return; } // we need 0 to 1 transition to trigger the interrupt - #if defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->SWIER1 &= ~(1 << line); EXTI->SWIER1 |= (1 << line); #else @@ -519,7 +525,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(extint_obj_swint_obj, extint_obj_swint); /// \classmethod regs() /// Dump the values of the EXTI registers. STATIC mp_obj_t extint_regs(void) { - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) printf("EXTI_IMR1 %08x\n", (unsigned int)EXTI->IMR1); printf("EXTI_IMR2 %08x\n", (unsigned int)EXTI->IMR2); printf("EXTI_EMR1 %08x\n", (unsigned int)EXTI->EMR1); diff --git a/ports/stm32/extint.h b/ports/stm32/extint.h index 0cdf5024a0..247852fa19 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -43,7 +43,7 @@ #endif #define EXTI_ETH_WAKEUP (19) #define EXTI_USB_OTG_HS_WAKEUP (20) -#if defined(STM32F0) || defined(STM32G4) || defined(STM32L4) +#if defined(STM32F0) || defined(STM32G4) || defined(STM32L4) || defined(STM32WL) #define EXTI_RTC_TIMESTAMP (19) #define EXTI_RTC_WAKEUP (20) #elif defined(STM32H7) || defined(STM32WB) diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index eeeab52049..0c4d2cf5b9 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -97,7 +97,7 @@ static const flash_layout_t flash_layout[] = { }; #endif -#elif defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) +#elif defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, @@ -159,7 +159,7 @@ static uint32_t get_page(uint32_t addr) { } #endif -#elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) +#elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) || defined(STM32WL) static uint32_t get_page(uint32_t addr) { return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; @@ -263,7 +263,7 @@ int flash_erase(uint32_t flash_dest, uint32_t num_word32) { EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.PageAddress = flash_dest; EraseInitStruct.NbPages = (4 * num_word32 + FLASH_PAGE_SIZE - 4) / FLASH_PAGE_SIZE; - #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) + #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) || defined(STM32WL) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); @@ -370,7 +370,7 @@ int flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { HAL_StatusTypeDef status = HAL_OK; - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) // program the flash uint64 by uint64 for (int i = 0; i < num_word32 / 2; i++) { diff --git a/ports/stm32/machine_adc.c b/ports/stm32/machine_adc.c index 21b35cdcdb..819fd3414f 100644 --- a/ports/stm32/machine_adc.c +++ b/ports/stm32/machine_adc.c @@ -28,7 +28,7 @@ #include "py/mphal.h" #include "adc.h" -#if defined(STM32F0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) +#if defined(STM32F0) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define ADC_V2 (1) #else #define ADC_V2 (0) @@ -42,7 +42,7 @@ #define ADCx_COMMON __LL_ADC_COMMON_INSTANCE(0) #endif -#if defined(STM32F0) || defined(STM32L0) +#if defined(STM32F0) || defined(STM32L0) || defined(STM32WL) #define ADC_STAB_DELAY_US (1) #define ADC_TEMPSENSOR_DELAY_US (10) #elif defined(STM32G4) @@ -65,7 +65,7 @@ #elif defined(STM32H7) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_8CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_387CYCLES_5 -#elif defined(STM32L0) +#elif defined(STM32L0) || defined(STM32WL) #define ADC_SAMPLETIME_DEFAULT ADC_SAMPLETIME_12CYCLES_5 #define ADC_SAMPLETIME_DEFAULT_INT ADC_SAMPLETIME_160CYCLES_5 #elif defined(STM32L4) || defined(STM32WB) @@ -105,7 +105,7 @@ STATIC const uint8_t adc_cr_to_bits_table[] = {12, 10, 8, 6}; void adc_config(ADC_TypeDef *adc, uint32_t bits) { // Configure ADC clock source and enable ADC clock - #if defined(STM32L4) || defined(STM32WB) + #if defined(STM32L4) || defined(STM32WB) || defined(STM32WL) __HAL_RCC_ADC_CONFIG(RCC_ADCCLKSOURCE_SYSCLK); __HAL_RCC_ADC_CLK_ENABLE(); #else @@ -150,6 +150,8 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { ADC1_COMMON->CCR = 0; // ADCPR=PCLK/2 #elif defined(STM32WB) ADC1_COMMON->CCR = 0 << ADC_CCR_PRESC_Pos | 0 << ADC_CCR_CKMODE_Pos; // PRESC=1, MODE=ASYNC + #elif defined(STM32WL) + ADC_COMMON->CCR = 0 << ADC_CCR_PRESC_Pos; // PRESC=1 #endif #if defined(STM32H7) || defined(STM32L4) || defined(STM32WB) @@ -158,7 +160,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { } #endif - #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) if (!(adc->CR & ADC_CR_ADVREGEN)) { adc->CR = ADC_CR_ADVREGEN; // enable VREG #if defined(STM32H7) @@ -172,7 +174,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { #if ADC_V2 if (!(adc->CR & ADC_CR_ADEN)) { // ADC isn't enabled so calibrate it now - #if defined(STM32F0) || defined(STM32L0) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32WL) LL_ADC_StartCalibration(adc); #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) LL_ADC_StartCalibration(adc, LL_ADC_SINGLE_ENDED); @@ -235,7 +237,7 @@ void adc_config(ADC_TypeDef *adc, uint32_t bits) { } STATIC int adc_get_bits(ADC_TypeDef *adc) { - #if defined(STM32F0) || defined(STM32L0) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32WL) uint32_t res = (adc->CFGR1 & ADC_CFGR1_RES) >> ADC_CFGR1_RES_Pos; #elif defined(STM32F4) || defined(STM32F7) uint32_t res = (adc->CR1 & ADC_CR1_RES) >> ADC_CR1_RES_Pos; @@ -409,7 +411,11 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s uint32_t sample_time = ADC_SAMPLETIME_DEFAULT; ADC_TypeDef *adc; if (mp_obj_is_int(source)) { + #if defined(STM32WL) + adc = ADC; + #else adc = ADC1; + #endif channel = mp_obj_get_int(source); if (channel == ADC_CHANNEL_VREFINT #if defined(STM32G4) @@ -426,7 +432,11 @@ STATIC mp_obj_t machine_adc_make_new(const mp_obj_type_t *type, size_t n_args, s } else { const pin_obj_t *pin = pin_find(source); if (pin->adc_num & PIN_ADC1) { + #if defined(STM32WL) + adc = ADC; + #else adc = ADC1; + #endif #if defined(ADC2) } else if (pin->adc_num & PIN_ADC2) { adc = ADC2; diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 6a12fad324..681939094b 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -459,7 +459,7 @@ STATIC MP_DEFINE_CONST_FUN_OBJ_1(pyb_uart_readchar_obj, pyb_uart_readchar); // uart.sendbreak() STATIC mp_obj_t pyb_uart_sendbreak(mp_obj_t self_in) { pyb_uart_obj_t *self = MP_OBJ_TO_PTR(self_in); - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G4) || defined(STM32H7) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) self->uartx->RQR = USART_RQR_SBKRQ; // write-only register #else self->uartx->CR1 |= USART_CR1_SBK; diff --git a/ports/stm32/modmachine.c b/ports/stm32/modmachine.c index f9026bc370..57b8ef5e6b 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -63,7 +63,7 @@ #define RCC_CSR_BORRSTF RCC_CSR_PORRSTF #endif -#if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) +#if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) // L4 does not have a POR, so use BOR instead #define RCC_CSR_PORRSTF RCC_CSR_BORRSTF #endif diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 17a4ad26e4..7c8662318d 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -404,6 +404,16 @@ #define MICROPY_HW_RFCORE_BLE_LL_ONLY (1) // use LL only, we provide the rest of the BLE stack #endif +// Configuration for STM32WL series +#elif defined(STM32WL) + +#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE) +#define PYB_EXTI_NUM_VECTORS (21) // up to RTC_WKUP +#define MICROPY_HW_MAX_I2C (3) +#define MICROPY_HW_MAX_TIMER (17) +#define MICROPY_HW_MAX_UART (2) +#define MICROPY_HW_MAX_LPUART (1) + #else #error Unsupported MCU series #endif diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index 2b98a620ef..2025388413 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -99,7 +99,7 @@ void mp_hal_gpio_clock_enable(GPIO_TypeDef *gpio) { #elif defined(STM32L0) #define AHBxENR IOPENR #define AHBxENR_GPIOAEN_Pos RCC_IOPENR_IOPAEN_Pos - #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #elif defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define AHBxENR AHB2ENR #define AHBxENR_GPIOAEN_Pos RCC_AHB2ENR_GPIOAEN_Pos #endif diff --git a/ports/stm32/powerctrl.c b/ports/stm32/powerctrl.c index ad3a3ea4c2..a2e3b5c71b 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -151,7 +151,7 @@ void powerctrl_check_enter_bootloader(void) { #endif } -#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32WB) +#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32WB) && !defined(STM32WL) typedef struct _sysclk_scaling_table_entry_t { uint16_t mhz; @@ -542,9 +542,15 @@ set_clk: return 0; } -#elif defined(STM32WB) +#elif defined(STM32WB) || defined(STM32WL) +#if defined(STM32WB) #include "stm32wbxx_ll_utils.h" +#define FLASH_LATENCY_MAX LL_FLASH_LATENCY_3 +#else +#include "stm32wlxx_ll_utils.h" +#define FLASH_LATENCY_MAX LL_FLASH_LATENCY_2 +#endif #define LPR_THRESHOLD (2000000) #define VOS2_THRESHOLD (16000000) @@ -605,8 +611,8 @@ int powerctrl_set_sysclk(uint32_t sysclk, uint32_t ahb, uint32_t apb1, uint32_t } else if (sysclk_mode == SYSCLK_MODE_MSI) { // Set flash latency to maximum to ensure the latency is large enough for // both the current SYSCLK and the SYSCLK that will be selected below. - LL_FLASH_SetLatency(LL_FLASH_LATENCY_3); - while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_3) { + LL_FLASH_SetLatency(FLASH_LATENCY_MAX); + while (LL_FLASH_GetLatency() != FLASH_LATENCY_MAX) { } // Before changing the MSIRANGE value, if MSI is on then it must also be ready. @@ -686,7 +692,7 @@ void powerctrl_enter_stop_mode(void) { __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif - #if !defined(STM32F0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) + #if !defined(STM32F0) && !defined(STM32G4) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) && !defined(STM32WL) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif @@ -765,7 +771,7 @@ void powerctrl_enter_stop_mode(void) { #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } - #elif defined(STM32WB) + #elif defined(STM32WB) || defined(STM32WL) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { } #else @@ -861,7 +867,7 @@ void powerctrl_enter_standby_mode(void) { #if defined(STM32F0) || defined(STM32L0) #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_WUTIE | RTC_CR_TSIE) #define ISR_BITS (RTC_ISR_ALRAF | RTC_ISR_WUTF | RTC_ISR_TSF) - #elif defined(STM32G4) + #elif defined(STM32G4) || defined(STM32WL) #define CR_BITS (RTC_CR_ALRAIE | RTC_CR_ALRBIE | RTC_CR_WUTIE | RTC_CR_TSIE) #define ISR_BITS (RTC_MISR_ALRAMF | RTC_MISR_ALRBMF | RTC_MISR_WUTMF | RTC_MISR_TSMF) #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) @@ -885,7 +891,7 @@ void powerctrl_enter_standby_mode(void) { // clear RTC wake-up flags #if defined(SR_BITS) RTC->SR &= ~SR_BITS; - #elif defined(STM32G4) + #elif defined(STM32G4) || defined(STM32WL) RTC->MISR &= ~ISR_BITS; #else RTC->ISR &= ~ISR_BITS; @@ -907,6 +913,9 @@ void powerctrl_enter_standby_mode(void) { // clear all wake-up flags PWR->SCR |= PWR_SCR_CWUF5 | PWR_SCR_CWUF4 | PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1; // TODO + #elif defined(STM32WL) + // clear all wake-up flags + PWR->SCR |= PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1; #else // clear global wake-up flag PWR->CR |= PWR_CR_CWUF; diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index 41b56296e0..4ecd83e2c6 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -212,4 +212,41 @@ void SystemClock_Config(void) { powerctrl_config_systick(); } +#elif defined(STM32WL) + +#include "stm32wlxx_ll_utils.h" + +void SystemClock_Config(void) { + // Set flash latency + LL_FLASH_SetLatency(LL_FLASH_LATENCY_2); + while (LL_FLASH_GetLatency() != LL_FLASH_LATENCY_2) { + } + + LL_PWR_SetRegulVoltageScaling(LL_PWR_REGU_VOLTAGE_SCALE1); + + // Enable MSI + LL_RCC_MSI_Enable(); + while (!LL_RCC_MSI_IsReady()) { + } + + // Configure MSI + LL_RCC_MSI_EnableRangeSelection(); + LL_RCC_MSI_SetRange(LL_RCC_MSIRANGE_11); + LL_RCC_MSI_SetCalibTrimming(0); + + // Select SYSCLK source + LL_RCC_SetSysClkSource(LL_RCC_SYS_CLKSOURCE_MSI); + while (LL_RCC_GetSysClkSource() != LL_RCC_SYS_CLKSOURCE_STATUS_MSI) { + } + + // Set bus dividers + LL_RCC_SetAHBPrescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAHB3Prescaler(LL_RCC_SYSCLK_DIV_1); + LL_RCC_SetAPB1Prescaler(LL_RCC_APB1_DIV_1); + LL_RCC_SetAPB2Prescaler(LL_RCC_APB2_DIV_1); + + SystemCoreClockUpdate(); + powerctrl_config_systick(); +} + #endif diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index 1164e71e08..e776f67bb9 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -94,6 +94,11 @@ STATIC bool rtc_need_init_finalise = false; #endif void rtc_init_start(bool force_init) { + #if defined(STM32WL) + // Enable the RTC APB bus clock, to communicate with the RTC. + __HAL_RCC_RTCAPB_CLK_ENABLE(); + #endif + RTCHandle.Instance = RTC; /* Configure RTC prescaler and RTC data registers */ @@ -220,7 +225,7 @@ void rtc_init_finalise() { // fresh reset; configure RTC Calendar RTC_CalendarConfig(); - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) if (__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET) { #else if (__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) { @@ -252,7 +257,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct /*------------------------------ LSE Configuration -------------------------*/ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) { - #if !defined(STM32H7) && !defined(STM32WB) + #if !defined(STM32H7) && !defined(STM32WB) && !defined(STM32WL) // Enable Power Clock __HAL_RCC_PWR_CLK_ENABLE(); #endif @@ -261,7 +266,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruct HAL_PWR_EnableBkUpAccess(); uint32_t tickstart = HAL_GetTick(); - #if defined(STM32F7) || defined(STM32G4) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) + #if defined(STM32F7) || defined(STM32G4) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) // __HAL_RCC_PWR_CLK_ENABLE(); // Enable write access to Backup domain // PWR->CR1 |= PWR_CR1_DBP; @@ -349,7 +354,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) { #elif defined(STM32F7) hrtc->Instance->OR &= (uint32_t) ~RTC_OR_ALARMTYPE; hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType); - #elif defined(STM32G4) + #elif defined(STM32G4) || defined(STM32WL) hrtc->Instance->CR &= (uint32_t) ~RTC_CR_TAMPALRM_TYPE_Msk; hrtc->Instance->CR |= (uint32_t)(hrtc->Init.OutPutType); #else @@ -714,7 +719,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { RTC->WPR = 0xff; // enable external interrupts on line EXTI_RTC_WAKEUP - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) @@ -726,14 +731,14 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { #endif // clear interrupt flags - #if defined(STM32G4) + #if defined(STM32G4) || defined(STM32WL) RTC->ICSR &= ~RTC_ICSR_WUTWF; #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; #else RTC->ISR &= ~RTC_ISR_WUTF; #endif - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->PR1 = 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) EXTI_D1->PR1 = 1 << EXTI_RTC_WAKEUP; @@ -753,7 +758,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { RTC->WPR = 0xff; // disable external interrupts on line EXTI_RTC_WAKEUP - #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32L4) || defined(STM32WB) || defined(STM32WL) EXTI->IMR1 &= ~(1 << EXTI_RTC_WAKEUP); #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; diff --git a/ports/stm32/stm32.mk b/ports/stm32/stm32.mk index f17351cdca..4de101ce7a 100644 --- a/ports/stm32/stm32.mk +++ b/ports/stm32/stm32.mk @@ -48,7 +48,7 @@ CFLAGS_CORTEX_M += -mfpu=fpv5-d16 -mfloat-abi=hard SUPPORTS_HARDWARE_FP_SINGLE = 1 SUPPORTS_HARDWARE_FP_DOUBLE = 1 else -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 l0 wl)) CFLAGS_CORTEX_M += -msoft-float else CFLAGS_CORTEX_M += -mfpu=fpv4-sp-d16 -mfloat-abi=hard @@ -66,3 +66,4 @@ CFLAGS_MCU_l0 = $(CFLAGS_CORTEX_M) -mtune=cortex-m0plus -mcpu=cortex-m0plus CFLAGS_MCU_l4 = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 CFLAGS_MCU_h7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 CFLAGS_MCU_wb = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 +CFLAGS_MCU_wl = $(CFLAGS_CORTEX_M) -mtune=cortex-m4 -mcpu=cortex-m4 diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 84274e3c62..39229a143b 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -529,7 +529,7 @@ void TAMP_STAMP_IRQHandler(void) { void RTC_WKUP_IRQHandler(void) { IRQ_ENTER(RTC_WKUP_IRQn); - #if defined(STM32G4) + #if defined(STM32G4) || defined(STM32WL) RTC->MISR &= ~RTC_MISR_WUTMF; // clear wakeup interrupt flag #elif defined(STM32H7A3xx) || defined(STM32H7A3xxQ) || defined(STM32H7B3xx) || defined(STM32H7B3xxQ) RTC->SR &= ~RTC_SR_WUTF; // clear wakeup interrupt flag diff --git a/ports/stm32/timer.c b/ports/stm32/timer.c index 57c8dc6c7b..12f0515d4e 100644 --- a/ports/stm32/timer.c +++ b/ports/stm32/timer.c @@ -873,14 +873,14 @@ STATIC const uint32_t tim_instance_table[MICROPY_HW_MAX_TIMER] = { #endif #endif #if defined(TIM16) - #if defined(STM32F0) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32H7) || defined(STM32WL) TIM_ENTRY(16, TIM16_IRQn), #else TIM_ENTRY(16, TIM1_UP_TIM16_IRQn), #endif #endif #if defined(TIM17) - #if defined(STM32F0) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32H7) || defined(STM32WL) TIM_ENTRY(17, TIM17_IRQn), #else TIM_ENTRY(17, TIM1_TRG_COM_TIM17_IRQn), diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 61e72999e2..13e1667d2c 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -41,16 +41,25 @@ #if defined(STM32F4) #define UART_RXNE_IS_SET(uart) ((uart)->SR & USART_SR_RXNE) #else -#if defined(STM32H7) +#if defined(STM32H7) || defined(STM32WL) #define USART_ISR_RXNE USART_ISR_RXNE_RXFNE #endif #define UART_RXNE_IS_SET(uart) ((uart)->ISR & USART_ISR_RXNE) #endif +#if defined(STM32WL) +#define UART_RXNE_IT_EN(uart) do { (uart)->CR1 |= USART_CR1_RXNEIE_RXFNEIE; } while (0) +#define UART_RXNE_IT_DIS(uart) do { (uart)->CR1 &= ~USART_CR1_RXNEIE_RXFNEIE; } while (0) +#else #define UART_RXNE_IT_EN(uart) do { (uart)->CR1 |= USART_CR1_RXNEIE; } while (0) #define UART_RXNE_IT_DIS(uart) do { (uart)->CR1 &= ~USART_CR1_RXNEIE; } while (0) +#endif +#if defined(STM32WL) +#define USART_CR1_IE_BASE (USART_CR1_PEIE | USART_CR1_TXEIE_TXFNFIE | USART_CR1_TCIE | USART_CR1_RXNEIE_RXFNEIE | USART_CR1_IDLEIE) +#else #define USART_CR1_IE_BASE (USART_CR1_PEIE | USART_CR1_TXEIE | USART_CR1_TCIE | USART_CR1_RXNEIE | USART_CR1_IDLEIE) +#endif #define USART_CR2_IE_BASE (USART_CR2_LBDIE) #define USART_CR3_IE_BASE (USART_CR3_CTSIE | USART_CR3_EIE) @@ -92,7 +101,7 @@ #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #define USART_CR3_IE_ALL (USART_CR3_IE_BASE | USART_CR3_WUFIE) -#elif defined(STM32L4) || defined(STM32WB) +#elif defined(STM32L4) || defined(STM32WB) || defined(STM32WL) #define USART_CR1_IE_ALL (USART_CR1_IE_BASE | USART_CR1_EOBIE | USART_CR1_RTOIE | USART_CR1_CMIE) #define USART_CR2_IE_ALL (USART_CR2_IE_BASE) #if defined(USART_CR3_TCBGTIE) @@ -113,9 +122,17 @@ typedef struct _pyb_uart_irq_map_t { STATIC const pyb_uart_irq_map_t mp_uart_irq_map[] = { { USART_CR1_IDLEIE, UART_FLAG_IDLE}, // RX idle { USART_CR1_PEIE, UART_FLAG_PE}, // parity error + #if defined(STM32WL) + { USART_CR1_TXEIE_TXFNFIE, UART_FLAG_TXE}, // TX register empty + #else { USART_CR1_TXEIE, UART_FLAG_TXE}, // TX register empty + #endif { USART_CR1_TCIE, UART_FLAG_TC}, // TX complete + #if defined(STM32WL) + { USART_CR1_RXNEIE_RXFNEIE, UART_FLAG_RXNE}, // RX register not empty + #else { USART_CR1_RXNEIE, UART_FLAG_RXNE}, // RX register not empty + #endif #if 0 // For now only IRQs selected by CR1 are supported #if defined(STM32F4) @@ -813,14 +830,14 @@ uint32_t uart_get_baudrate(pyb_uart_obj_t *self) { #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { return LL_LPUART_GetBaudRate(self->uartx, uart_get_source_freq(self) - #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) , self->uartx->PRESC #endif ); } #endif return LL_USART_GetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) self->uartx->PRESC, #endif LL_USART_OVERSAMPLING_16); @@ -830,7 +847,7 @@ void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) { #if defined(LPUART1) if (self->uart_id == PYB_LPUART_1) { LL_LPUART_SetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) LL_LPUART_PRESCALER_DIV1, #endif baudrate); @@ -838,7 +855,7 @@ void uart_set_baudrate(pyb_uart_obj_t *self, uint32_t baudrate) { } #endif LL_USART_SetBaudRate(self->uartx, uart_get_source_freq(self), - #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) + #if defined(STM32G4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) LL_USART_PRESCALER_DIV1, #endif LL_USART_OVERSAMPLING_16, baudrate); @@ -889,7 +906,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) int data = self->uartx->RDR & self->char_mask; self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set return data; @@ -1039,7 +1056,7 @@ void uart_irq_handler(mp_uint_t uart_id) { uint16_t next_head = (self->read_buf_head + 1) % self->read_buf_len; if (next_head != self->read_buf_tail) { // only read data if room in buf - #if defined(STM32F0) || defined(STM32F7) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32G4) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) || defined(STM32WL) int data = self->uartx->RDR; // clears UART_FLAG_RXNE #else self->mp_irq_flags = self->uartx->SR; // resample to get any new flags since next read of DR will clear SR diff --git a/ports/stm32/uart.h b/ports/stm32/uart.h index 0a268ad465..5fee841f8f 100644 --- a/ports/stm32/uart.h +++ b/ports/stm32/uart.h @@ -102,7 +102,7 @@ void uart_tx_strn(pyb_uart_obj_t *uart_obj, const char *str, uint len); static inline bool uart_tx_avail(pyb_uart_obj_t *self) { #if defined(STM32F4) return self->uartx->SR & USART_SR_TXE; - #elif defined(STM32H7) + #elif defined(STM32H7) || defined(STM32WL) return self->uartx->ISR & USART_ISR_TXE_TXFNF; #else return self->uartx->ISR & USART_ISR_TXE;