From 59b7166d87b480517ca5905ee2239dc2cace18b9 Mon Sep 17 00:00:00 2001 From: Damien George Date: Wed, 17 Jul 2019 16:33:31 +1000 Subject: [PATCH] stm32: Add initial support for STM32WBxx MCUs. This new series of MCUs is similar to the L4 series with an additional Cortex-M0 coprocessor. The firmware for the wireless stack must be managed separately and MicroPython does not currently interface to it. Supported features so far include: RTC, UART, USB, internal flash filesystem. --- ports/stm32/Makefile | 5 ++-- ports/stm32/dma.c | 14 +++++++++ ports/stm32/dma.h | 2 +- ports/stm32/extint.c | 28 ++++++++++++++++-- ports/stm32/extint.h | 2 +- ports/stm32/flash.c | 8 +++--- ports/stm32/flashbdev.c | 3 +- ports/stm32/machine_uart.c | 2 +- ports/stm32/modmachine.c | 4 +-- ports/stm32/mpconfigboard_common.h | 9 ++++++ ports/stm32/mphalport.c | 2 +- ports/stm32/powerctrl.c | 13 +++++---- ports/stm32/powerctrlboot.c | 46 ++++++++++++++++++++++++++++++ ports/stm32/rtc.c | 22 +++++++++----- ports/stm32/stm32_it.c | 8 ++++++ ports/stm32/system_stm32.c | 4 +++ ports/stm32/uart.c | 8 ++++-- ports/stm32/usbd_cdc_interface.c | 4 +-- ports/stm32/usbd_conf.c | 19 ++++++++---- 19 files changed, 165 insertions(+), 38 deletions(-) diff --git a/ports/stm32/Makefile b/ports/stm32/Makefile index f74180d397..e868d6de1b 100644 --- a/ports/stm32/Makefile +++ b/ports/stm32/Makefile @@ -79,6 +79,7 @@ CFLAGS_MCU_f7 = $(CFLAGS_CORTEX_M) -mtune=cortex-m7 -mcpu=cortex-m7 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 = $(INC) -Wall -Wpointer-arith -Werror -std=gnu99 -nostdlib $(CFLAGS_MOD) $(CFLAGS_EXTRA) CFLAGS += -D$(CMSIS_MCU) @@ -335,7 +336,7 @@ SRC_HAL = $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ hal_uart.c \ ) -ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f4 f7 h7 l0 l4 wb)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_,\ ll_usb.c \ ) @@ -361,7 +362,7 @@ endif ifeq ($(CMSIS_MCU),$(filter $(CMSIS_MCU),STM32H743xx)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_fdcan.c) else -ifneq ($(MCU_SERIES),$(filter $(MCU_SERIES),l0)) +ifeq ($(MCU_SERIES),$(filter $(MCU_SERIES),f0 f4 f7 h7 l4)) SRC_HAL += $(addprefix $(HAL_DIR)/Src/stm32$(MCU_SERIES)xx_, hal_can.c) endif endif diff --git a/ports/stm32/dma.c b/ports/stm32/dma.c index 2c7371e010..8a3f743fe7 100644 --- a/ports/stm32/dma.c +++ b/ports/stm32/dma.c @@ -34,6 +34,18 @@ #include "dma.h" #include "irq.h" +#if defined(STM32WB) + +// DMA is currently not implemented for this MCU + +void dma_init(DMA_HandleTypeDef *dma, const dma_descr_t *dma_descr, uint32_t dir, void *data) { +} + +void dma_deinit(const dma_descr_t *dma_descr) { +} + +#else + #define DMA_IDLE_ENABLED() (dma_idle.enabled != 0) #define DMA_SYSTICK_LOG2 (3) #define DMA_SYSTICK_MASK ((1 << DMA_SYSTICK_LOG2) - 1) @@ -919,3 +931,5 @@ void dma_nohal_start(const dma_descr_t *descr, uint32_t src_addr, uint32_t dst_a } #endif + +#endif // defined(STM32WB) diff --git a/ports/stm32/dma.h b/ports/stm32/dma.h index 6d07a94ed9..5a17276a49 100644 --- a/ports/stm32/dma.h +++ b/ports/stm32/dma.h @@ -73,7 +73,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) +#elif defined(STM32L4) || defined(STM32WB) 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 9a7295995a..836b0c5954 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(STM32L4) +#if defined(STM32L4) || defined(STM32WB) // 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. @@ -140,6 +140,7 @@ STATIC mp_obj_t pyb_extint_callback_arg[EXTI_NUM_VECTORS]; STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { #if defined(STM32F0) || defined(STM32L0) + EXTI0_1_IRQn, EXTI0_1_IRQn, EXTI2_3_IRQn, EXTI2_3_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, EXTI4_15_IRQn, @@ -155,11 +156,19 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { RTC_IRQn, ADC1_COMP_IRQn, ADC1_COMP_IRQn, + #else + EXTI0_IRQn, EXTI1_IRQn, EXTI2_IRQn, EXTI3_IRQn, EXTI4_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI9_5_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, EXTI15_10_IRQn, + #if defined(STM32WB) + PVD_PVM_IRQn, + RTC_Alarm_IRQn, + TAMP_STAMP_LSECSS_IRQn, + RTC_WKUP_IRQn, + #else #if defined(STM32L4) PVD_PVM_IRQn, #else @@ -177,6 +186,8 @@ STATIC const uint8_t nvic_irq_channel[EXTI_NUM_VECTORS] = { TAMP_STAMP_IRQn, RTC_WKUP_IRQn, #endif + + #endif }; // Set override_callback_obj to true if you want to unconditionally set the @@ -285,7 +296,9 @@ 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) __HAL_RCC_SYSCFG_CLK_ENABLE(); + #endif SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); @@ -320,7 +333,9 @@ 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) __HAL_RCC_SYSCFG_CLK_ENABLE(); + #endif SYSCFG->EXTICR[line >> 2] = (SYSCFG->EXTICR[line >> 2] & ~(0x0f << (4 * (line & 0x03)))) | ((uint32_t)(GPIO_GET_INDEX(pin->gpio)) << (4 * (line & 0x03))); @@ -358,12 +373,16 @@ void extint_enable(uint line) { if (pyb_extint_mode[line] == EXTI_Mode_Interrupt) { #if defined(STM32H7) EXTI_D1->IMR1 |= (1 << line); + #elif defined(STM32WB) + EXTI->IMR1 |= (1 << line); #else EXTI->IMR |= (1 << line); #endif } else { #if defined(STM32H7) EXTI_D1->EMR1 |= (1 << line); + #elif defined(STM32WB) + EXTI->EMR1 |= (1 << line); #else EXTI->EMR |= (1 << line); #endif @@ -388,6 +407,9 @@ void extint_disable(uint line) { #if defined(STM32H7) EXTI_D1->IMR1 &= ~(1 << line); EXTI_D1->EMR1 &= ~(1 << line); + #elif defined(STM32WB) + EXTI->IMR1 &= ~(1 << line); + EXTI->EMR1 &= ~(1 << line); #else EXTI->IMR &= ~(1 << line); EXTI->EMR &= ~(1 << line); @@ -407,7 +429,7 @@ void extint_swint(uint line) { return; } // we need 0 to 1 transition to trigger the interrupt -#if defined(STM32L4) || defined(STM32H7) +#if defined(STM32L4) || defined(STM32H7) || defined(STM32WB) EXTI->SWIER1 &= ~(1 << line); EXTI->SWIER1 |= (1 << line); #else @@ -485,7 +507,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(STM32L4) + #if defined(STM32L4) || defined(STM32WB) 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 d275087c9e..907af53dc2 100644 --- a/ports/stm32/extint.h +++ b/ports/stm32/extint.h @@ -46,7 +46,7 @@ #if defined(STM32F0) || defined(STM32L4) #define EXTI_RTC_TIMESTAMP (19) #define EXTI_RTC_WAKEUP (20) -#elif defined(STM32H7) +#elif defined(STM32H7) || defined(STM32WB) #define EXTI_RTC_TIMESTAMP (18) #define EXTI_RTC_WAKEUP (19) #else diff --git a/ports/stm32/flash.c b/ports/stm32/flash.c index aff85f7e37..58cc012793 100644 --- a/ports/stm32/flash.c +++ b/ports/stm32/flash.c @@ -68,7 +68,7 @@ static const flash_layout_t flash_layout[] = { { 0x08040000, 0x40000, 3 }, }; -#elif defined(STM32L0) || defined(STM32L4) +#elif defined(STM32L0) || defined(STM32L4) || defined(STM32WB) static const flash_layout_t flash_layout[] = { { (uint32_t)FLASH_BASE, (uint32_t)FLASH_PAGE_SIZE, 512 }, @@ -122,7 +122,7 @@ static uint32_t get_page(uint32_t addr) { } #endif -#elif defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE) +#elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) static uint32_t get_page(uint32_t addr) { return (addr - FLASH_BASE) / FLASH_PAGE_SIZE; @@ -175,7 +175,7 @@ void 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) + #elif (defined(STM32L4) && !defined(SYSCFG_MEMRMP_FB_MODE)) || defined(STM32WB) __HAL_FLASH_CLEAR_FLAG(FLASH_FLAG_ALL_ERRORS); EraseInitStruct.TypeErase = FLASH_TYPEERASE_PAGES; EraseInitStruct.Page = get_page(flash_dest); @@ -247,7 +247,7 @@ void flash_erase_it(uint32_t flash_dest, uint32_t num_word32) { */ void flash_write(uint32_t flash_dest, const uint32_t *src, uint32_t num_word32) { - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) // program the flash uint64 by uint64 for (int i = 0; i < num_word32 / 2; i++) { diff --git a/ports/stm32/flashbdev.c b/ports/stm32/flashbdev.c index 0a5f417040..470f3d0860 100644 --- a/ports/stm32/flashbdev.c +++ b/ports/stm32/flashbdev.c @@ -105,7 +105,8 @@ STATIC byte flash_cache_mem[0x4000] __attribute__((aligned(4))); // 16k #elif defined(STM32L432xx) || \ defined(STM32L451xx) || defined(STM32L452xx) || defined(STM32L462xx) || \ - defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) + defined(STM32L475xx) || defined(STM32L476xx) || defined(STM32L496xx) || \ + defined(STM32WB) // The STM32L4xx doesn't have CCRAM, so we use SRAM2 for this, although // actual location and size is defined by the linker script. diff --git a/ports/stm32/machine_uart.c b/ports/stm32/machine_uart.c index 92343ba6d7..5dbc133310 100644 --- a/ports/stm32/machine_uart.c +++ b/ports/stm32/machine_uart.c @@ -489,7 +489,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(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) 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 8d6dbf4fec..e45f81479b 100644 --- a/ports/stm32/modmachine.c +++ b/ports/stm32/modmachine.c @@ -61,7 +61,7 @@ #define RCC_CSR_BORRSTF RCC_CSR_PORRSTF #endif -#if defined(STM32L4) +#if defined(STM32L4) || defined(STM32WB) // L4 does not have a POR, so use BOR instead #define RCC_CSR_PORRSTF RCC_CSR_BORRSTF #endif @@ -305,7 +305,7 @@ STATIC mp_obj_t machine_freq(size_t n_args, const mp_obj_t *args) { return mp_obj_new_tuple(MP_ARRAY_SIZE(tuple), tuple); } else { // set - #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) + #if defined(STM32F0) || defined(STM32L0) || defined(STM32L4) || defined(STM32WB) mp_raise_NotImplementedError("machine.freq set not supported yet"); #else mp_int_t sysclk = mp_obj_get_int(args[0]); diff --git a/ports/stm32/mpconfigboard_common.h b/ports/stm32/mpconfigboard_common.h index 63d4238020..121b64d038 100644 --- a/ports/stm32/mpconfigboard_common.h +++ b/ports/stm32/mpconfigboard_common.h @@ -202,6 +202,15 @@ #define MICROPY_HW_MAX_TIMER (17) #define MICROPY_HW_MAX_UART (6) +// Configuration for STM32WB series +#elif defined(STM32WB) + +#define MP_HAL_UNIQUE_ID_ADDRESS (UID_BASE) +#define PYB_EXTI_NUM_VECTORS (20) +#define MICROPY_HW_MAX_I2C (3) +#define MICROPY_HW_MAX_TIMER (17) +#define MICROPY_HW_MAX_UART (1) + #else #error Unsupported MCU series #endif diff --git a/ports/stm32/mphalport.c b/ports/stm32/mphalport.c index fe7772cf68..ec4590b06b 100644 --- a/ports/stm32/mphalport.c +++ b/ports/stm32/mphalport.c @@ -122,7 +122,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(STM32L4) + #elif defined(STM32L4) || defined(STM32WB) #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 067e4c176e..68a8bfdaf3 100644 --- a/ports/stm32/powerctrl.c +++ b/ports/stm32/powerctrl.c @@ -76,7 +76,7 @@ void powerctrl_check_enter_bootloader(void) { if ((bl_addr & 0xfff) == 0 && (RCC->RCC_SR & RCC_SR_SFTRSTF)) { // Reset by NVIC_SystemReset with bootloader data set -> branch to bootloader RCC->RCC_SR = RCC_SR_RMVF; - #if defined(STM32F0) || defined(STM32F4) || defined(STM32L4) + #if defined(STM32F0) || defined(STM32F4) || defined(STM32L4) || defined(STM32WB) __HAL_SYSCFG_REMAPMEMORY_SYSTEMFLASH(); #endif uint32_t r0 = BL_STATE[0]; @@ -84,7 +84,7 @@ void powerctrl_check_enter_bootloader(void) { } } -#if !defined(STM32F0) && !defined(STM32L0) +#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32WB) // Assumes that PLL is used as the SYSCLK source int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk_mhz, bool need_pllsai) { @@ -158,7 +158,7 @@ int powerctrl_rcc_clock_config_pll(RCC_ClkInitTypeDef *rcc_init, uint32_t sysclk #endif -#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) +#if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) STATIC uint32_t calc_ahb_div(uint32_t wanted_div) { if (wanted_div <= 1) { return RCC_SYSCLK_DIV1; } @@ -333,7 +333,7 @@ void powerctrl_enter_stop_mode(void) { __HAL_RCC_WAKEUPSTOP_CLK_CONFIG(RCC_STOP_WAKEUPCLOCK_MSI); #endif - #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) + #if !defined(STM32F0) && !defined(STM32L0) && !defined(STM32L4) && !defined(STM32WB) // takes longer to wake but reduces stop current HAL_PWREx_EnableFlashPowerDown(); #endif @@ -380,6 +380,9 @@ void powerctrl_enter_stop_mode(void) { #if defined(STM32H7) while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL1) { } + #elif defined(STM32WB) + while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_SYSCLKSOURCE_STATUS_PLLCLK) { + } #else while (__HAL_RCC_GET_SYSCLK_SOURCE() != RCC_CFGR_SWS_PLL) { } @@ -450,7 +453,7 @@ void powerctrl_enter_standby_mode(void) { PWR->CR2 |= PWR_CR2_CWUPF6 | PWR_CR2_CWUPF5 | PWR_CR2_CWUPF4 | PWR_CR2_CWUPF3 | PWR_CR2_CWUPF2 | PWR_CR2_CWUPF1; #elif defined(STM32H7) // TODO - #elif defined(STM32L4) + #elif defined(STM32L4) || defined(STM32WB) // clear all wake-up flags PWR->SCR |= PWR_SCR_CWUF5 | PWR_SCR_CWUF4 | PWR_SCR_CWUF3 | PWR_SCR_CWUF2 | PWR_SCR_CWUF1; // TODO diff --git a/ports/stm32/powerctrlboot.c b/ports/stm32/powerctrlboot.c index de7c9d88a7..8884f596ed 100644 --- a/ports/stm32/powerctrlboot.c +++ b/ports/stm32/powerctrlboot.c @@ -131,4 +131,50 @@ void SystemClock_Config(void) { #endif } +#elif defined(STM32WB) + +void SystemClock_Config(void) { + // Enable the 32MHz external oscillator + RCC->CR |= RCC_CR_HSEON; + while (!(RCC->CR & RCC_CR_HSERDY)) { + } + + // Use HSE and the PLL to get a 64MHz SYSCLK + #define PLLM (HSE_VALUE / 8000000) // VCO input is 8MHz + #define PLLN (24) // 24*8MHz = 192MHz + #define PLLQ (4) // f_Q = 48MHz + #define PLLR (3) // f_R = 64MHz + RCC->PLLCFGR = + (PLLR - 1) << RCC_PLLCFGR_PLLR_Pos | RCC_PLLCFGR_PLLREN + | (PLLQ - 1) << RCC_PLLCFGR_PLLQ_Pos | RCC_PLLCFGR_PLLQEN + | PLLN << RCC_PLLCFGR_PLLN_Pos + | (PLLM - 1) << RCC_PLLCFGR_PLLM_Pos + | 3 << RCC_PLLCFGR_PLLSRC_Pos; + RCC->CR |= RCC_CR_PLLON; + while (!(RCC->CR & RCC_CR_PLLRDY)) { + // Wait for PLL to lock + } + const uint32_t sysclk_src = 3; + + // Set divider for HCLK2 to 2 so f_HCLK2 = 32MHz + RCC->EXTCFGR = 8 << RCC_EXTCFGR_C2HPRE_Pos; + + // Set flash latency to 3 because SYSCLK > 54MHz + FLASH->ACR |= 3 << FLASH_ACR_LATENCY_Pos; + + // Select SYSCLK source + RCC->CFGR |= sysclk_src << RCC_CFGR_SW_Pos; + while (((RCC->CFGR >> RCC_CFGR_SWS_Pos) & 0x3) != sysclk_src) { + // Wait for SYSCLK source to change + } + + // Select PLLQ as 48MHz source for USB and RNG + RCC->CCIPR = 2 << RCC_CCIPR_CLK48SEL_Pos; + + SystemCoreClockUpdate(); + + HAL_SYSTICK_Config(HAL_RCC_GetHCLKFreq() / 1000); + HAL_SYSTICK_CLKSourceConfig(SYSTICK_CLKSOURCE_HCLK); +} + #endif diff --git a/ports/stm32/rtc.c b/ports/stm32/rtc.c index d0f444c216..4019617ac8 100644 --- a/ports/stm32/rtc.c +++ b/ports/stm32/rtc.c @@ -31,6 +31,14 @@ #include "rtc.h" #include "irq.h" +#if defined(STM32WB) +#define RCC_CSR_LSION RCC_CSR_LSI1ON +#define RCC_FLAG_LSIRDY RCC_FLAG_LSI1RDY +#define RCC_OSCILLATORTYPE_LSI RCC_OSCILLATORTYPE_LSI1 +#define __HAL_RCC_LSI_ENABLE __HAL_RCC_LSI1_ENABLE +#define __HAL_RCC_LSI_DISABLE __HAL_RCC_LSI1_DISABLE +#endif + /// \moduleref pyb /// \class RTC - real time clock /// @@ -177,7 +185,7 @@ void rtc_init_finalise() { // fresh reset; configure RTC Calendar RTC_CalendarConfig(); - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) if(__HAL_RCC_GET_FLAG(RCC_FLAG_BORRST) != RESET) { #else if(__HAL_RCC_GET_FLAG(RCC_FLAG_PORRST) != RESET) { @@ -209,7 +217,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc /*------------------------------ LSE Configuration -------------------------*/ if ((RCC_OscInitStruct->OscillatorType & RCC_OSCILLATORTYPE_LSE) == RCC_OSCILLATORTYPE_LSE) { - #if !defined(STM32H7) + #if !defined(STM32H7) && !defined(STM32WB) // Enable Power Clock __HAL_RCC_PWR_CLK_ENABLE(); #endif @@ -218,7 +226,7 @@ STATIC HAL_StatusTypeDef PYB_RCC_OscConfig(RCC_OscInitTypeDef *RCC_OscInitStruc HAL_PWR_EnableBkUpAccess(); uint32_t tickstart = HAL_GetTick(); - #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F7) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) //__HAL_RCC_PWR_CLK_ENABLE(); // Enable write access to Backup domain //PWR->CR1 |= PWR_CR1_DBP; @@ -298,7 +306,7 @@ STATIC HAL_StatusTypeDef PYB_RTC_Init(RTC_HandleTypeDef *hrtc) { // Exit Initialization mode hrtc->Instance->ISR &= (uint32_t)~RTC_ISR_INIT; - #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) hrtc->Instance->OR &= (uint32_t)~RTC_OR_ALARMOUTTYPE; hrtc->Instance->OR |= (uint32_t)(hrtc->Init.OutPutType); #elif defined(STM32F7) @@ -649,7 +657,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(STM32L4) + #if defined(STM32L4) || defined(STM32WB) EXTI->IMR1 |= 1 << EXTI_RTC_WAKEUP; EXTI->RTSR1 |= 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) @@ -662,7 +670,7 @@ mp_obj_t pyb_rtc_wakeup(size_t n_args, const mp_obj_t *args) { // clear interrupt flags RTC->ISR &= ~RTC_ISR_WUTF; - #if defined(STM32L4) + #if defined(STM32L4) || defined(STM32WB) EXTI->PR1 = 1 << EXTI_RTC_WAKEUP; #elif defined(STM32H7) EXTI_D1->PR1 = 1 << EXTI_RTC_WAKEUP; @@ -682,7 +690,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(STM32L4) + #if defined(STM32L4) || defined(STM32WB) EXTI->IMR1 &= ~(1 << EXTI_RTC_WAKEUP); #elif defined(STM32H7) EXTI_D1->IMR1 |= 1 << EXTI_RTC_WAKEUP; diff --git a/ports/stm32/stm32_it.c b/ports/stm32/stm32_it.c index 1e2712b05f..16db92d1d7 100644 --- a/ports/stm32/stm32_it.c +++ b/ports/stm32/stm32_it.c @@ -306,6 +306,14 @@ void USB_IRQHandler(void) { } #endif +#elif defined(STM32WB) + +#if MICROPY_HW_USB_FS +void USB_LP_IRQHandler(void) { + HAL_PCD_IRQHandler(&pcd_fs_handle); +} +#endif + #else /** diff --git a/ports/stm32/system_stm32.c b/ports/stm32/system_stm32.c index deb23e2f5f..0792d124d6 100644 --- a/ports/stm32/system_stm32.c +++ b/ports/stm32/system_stm32.c @@ -78,6 +78,8 @@ #include "py/mphal.h" #include "powerctrl.h" +#if defined(STM32F4) || defined(STM32F7) || defined(STM32H7) || defined(STM32L4) + void __fatal_error(const char *msg); /** @@ -392,3 +394,5 @@ void SystemClock_Config(void) NVIC_SetPriority(SysTick_IRQn, NVIC_EncodePriority(NVIC_PRIORITYGROUP_4, TICK_INT_PRIORITY, 0)); #endif } + +#endif diff --git a/ports/stm32/uart.c b/ports/stm32/uart.c index 0d46ea9473..f577eb787f 100644 --- a/ports/stm32/uart.c +++ b/ports/stm32/uart.c @@ -81,7 +81,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) +#elif defined(STM32L4) || defined(STM32WB) #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) @@ -439,11 +439,13 @@ void uart_deinit(pyb_uart_obj_t *self) { __HAL_RCC_USART1_FORCE_RESET(); __HAL_RCC_USART1_RELEASE_RESET(); __HAL_RCC_USART1_CLK_DISABLE(); + #if defined(USART2) } else if (self->uart_id == 2) { HAL_NVIC_DisableIRQ(USART2_IRQn); __HAL_RCC_USART2_FORCE_RESET(); __HAL_RCC_USART2_RELEASE_RESET(); __HAL_RCC_USART2_CLK_DISABLE(); + #endif #if defined(USART3) } else if (self->uart_id == 3) { #if !defined(STM32F0) @@ -653,7 +655,7 @@ int uart_rx_char(pyb_uart_obj_t *self) { return data; } else { // no buffering - #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) int data = self->uartx->RDR & self->char_mask; self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set return data; @@ -779,7 +781,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(STM32L0) || defined(STM32L4) || defined(STM32H7) + #if defined(STM32F0) || defined(STM32F7) || defined(STM32L0) || defined(STM32L4) || defined(STM32H7) || defined(STM32WB) int data = self->uartx->RDR; // clears UART_FLAG_RXNE self->uartx->ICR = USART_ICR_ORECF; // clear ORE if it was set #else diff --git a/ports/stm32/usbd_cdc_interface.c b/ports/stm32/usbd_cdc_interface.c index b27ea51d87..e234230196 100644 --- a/ports/stm32/usbd_cdc_interface.c +++ b/ports/stm32/usbd_cdc_interface.c @@ -142,7 +142,7 @@ int8_t usbd_cdc_control(usbd_cdc_state_t *cdc_in, uint8_t cmd, uint8_t* pbuf, ui // configure its serial port (in most cases to disable local echo) cdc->connect_state = USBD_CDC_CONNECT_STATE_CONNECTING; usbd_cdc_connect_tx_timer = 8; // wait for 8 SOF IRQs - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) USB->CNTR |= USB_CNTR_SOFM; #else PCD_HandleTypeDef *hpcd = cdc->base.usbd->pdev->pData; @@ -219,7 +219,7 @@ void HAL_PCD_SOFCallback(PCD_HandleTypeDef *hpcd) { --usbd_cdc_connect_tx_timer; } else { usbd_cdc_msc_hid_state_t *usbd = ((USBD_HandleTypeDef*)hpcd->pData)->pClassData; - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) USB->CNTR &= ~USB_CNTR_SOFM; #else hpcd->Instance->GINTMSK &= ~USB_OTG_GINTMSK_SOFM; diff --git a/ports/stm32/usbd_conf.c b/ports/stm32/usbd_conf.c index 8e62a9cc8c..437d96ae78 100644 --- a/ports/stm32/usbd_conf.c +++ b/ports/stm32/usbd_conf.c @@ -44,7 +44,7 @@ PCD_HandleTypeDef pcd_fs_handle; PCD_HandleTypeDef pcd_hs_handle; #endif -#if defined(STM32L0) +#if defined(STM32L0) || defined(STM32WB) // The STM32L0xx has a single USB device-only instance #define USB_OTG_FS USB #endif @@ -64,6 +64,8 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { const uint32_t otg_alt = GPIO_AF10_OTG1_FS; #elif defined(STM32L0) const uint32_t otg_alt = GPIO_AF0_USB; + #elif defined(STM32WB) + const uint32_t otg_alt = GPIO_AF10_USB; #else const uint32_t otg_alt = GPIO_AF10_OTG_FS; #endif @@ -90,7 +92,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #endif // Enable USB FS Clocks - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) __HAL_RCC_USB_CLK_ENABLE(); #else __USB_OTG_FS_CLK_ENABLE(); @@ -111,6 +113,9 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { #if defined(STM32L0) NVIC_SetPriority(USB_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(USB_IRQn); + #elif defined(STM32WB) + NVIC_SetPriority(USB_LP_IRQn, IRQ_PRI_OTG_FS); + HAL_NVIC_EnableIRQ(USB_LP_IRQn); #else NVIC_SetPriority(OTG_FS_IRQn, IRQ_PRI_OTG_FS); HAL_NVIC_EnableIRQ(OTG_FS_IRQn); @@ -190,7 +195,7 @@ void HAL_PCD_MspInit(PCD_HandleTypeDef *hpcd) { * @retval None */ void HAL_PCD_MspDeInit(PCD_HandleTypeDef *hpcd) { - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) __HAL_RCC_USB_CLK_DISABLE(); #else @@ -354,6 +359,10 @@ void HAL_PCD_DisconnectCallback(PCD_HandleTypeDef *hpcd) { USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { #if MICROPY_HW_USB_FS if (pdev->id == USB_PHY_FS_ID) { + #if defined(STM32WB) + PWR->CR2 |= PWR_CR2_USV; // USB supply is valid + #endif + // Set LL Driver parameters pcd_fs_handle.Instance = USB_OTG_FS; #if MICROPY_HW_USB_CDC_NUM == 2 @@ -370,7 +379,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { pcd_fs_handle.Init.lpm_enable = DISABLE; pcd_fs_handle.Init.battery_charging_enable = DISABLE; #endif - #if !defined(STM32L0) + #if !defined(STM32L0) && !defined(STM32WB) pcd_fs_handle.Init.use_dedicated_ep1 = 0; pcd_fs_handle.Init.dma_enable = 0; #if !defined(MICROPY_HW_USB_VBUS_DETECT_PIN) @@ -387,7 +396,7 @@ USBD_StatusTypeDef USBD_LL_Init(USBD_HandleTypeDef *pdev, int high_speed) { // Initialize LL Driver HAL_PCD_Init(&pcd_fs_handle); - #if defined(STM32L0) + #if defined(STM32L0) || defined(STM32WB) // We have 512 16-bit words it total to use here (when using PCD_SNG_BUF) HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x00, PCD_SNG_BUF, 64); // EP0 HAL_PCDEx_PMAConfig(&pcd_fs_handle, 0x80, PCD_SNG_BUF, 128); // EP0