From 06a50df2d549c8ccc57b9355fae4249f8439a7a1 Mon Sep 17 00:00:00 2001 From: Jerzy Kasenberg Date: Sun, 26 May 2024 12:41:07 +0200 Subject: [PATCH] hw/mcu/stm32: Add option to place WFI in RAM Some STM32 devices have erratas for flash related issues that recommend workaround of placing WFI instruction in RAM. This is the case for STM32F4xx devices where other solution was to put WFI instruction at specific address locations (divisible by 8). New syscfg value STM32_WFI_FROM_RAM is introduced that adds function stm32_wfi_from_ram(). STM32_WFI is also added and can be used instead of WFI when needed BSP for affected STM32F4xx devices now use WFI from RAM instead of placing WFI instruction at aligne address. STM32L0 devices are also updated since anomally was also observed there. Signed-off-by: Jerzy Kasenberg --- hw/bsp/ada_feather_stm32f405/syscfg.yml | 1 + hw/bsp/b-l072z-lrwan1/syscfg.yml | 1 + hw/bsp/black_vet6/syscfg.yml | 1 + hw/bsp/nucleo-l073rz/syscfg.yml | 1 + hw/bsp/olimex_stm32-e407_devboard/syscfg.yml | 1 + .../stm32_common/include/stm32_common/mcu.h | 7 ++++ hw/mcu/stm/stm32_common/src/hal_os_tick.c | 39 +++++++------------ hw/mcu/stm/stm32_common/syscfg.yml | 6 +++ 8 files changed, 33 insertions(+), 24 deletions(-) diff --git a/hw/bsp/ada_feather_stm32f405/syscfg.yml b/hw/bsp/ada_feather_stm32f405/syscfg.yml index 3e0ff75463..fc9fcd2fc3 100644 --- a/hw/bsp/ada_feather_stm32f405/syscfg.yml +++ b/hw/bsp/ada_feather_stm32f405/syscfg.yml @@ -48,6 +48,7 @@ syscfg.vals: STM32_FLASH_PREFETCH_ENABLE: 1 STM32_INSTRUCTION_CACHE_ENABLE: 1 STM32_DATA_CACHE_ENABLE: 1 + STM32_WFI_FROM_RAM: 1 WATCHDOG_INTERVAL: 28000 # UART0 is on the large breakout connector, pins TX and RX. UART_0_PIN_TX: 'MCU_GPIO_PORTB(10)' diff --git a/hw/bsp/b-l072z-lrwan1/syscfg.yml b/hw/bsp/b-l072z-lrwan1/syscfg.yml index ca61b36b64..c893b7f7ba 100644 --- a/hw/bsp/b-l072z-lrwan1/syscfg.yml +++ b/hw/bsp/b-l072z-lrwan1/syscfg.yml @@ -51,6 +51,7 @@ syscfg.vals: STM32_CLOCK_APB2_DIVIDER: 'RCC_HCLK_DIV1' STM32_FLASH_LATENCY: 1 # max 32MHz STM32_FLASH_PREFETCH_ENABLE: 0 + STM32_WFI_FROM_RAM: 1 WATCHDOG_INTERVAL: 25000 UART_0_PIN_TX: 'MCU_GPIO_PORTA(2)' UART_0_PIN_RX: 'MCU_GPIO_PORTA(3)' diff --git a/hw/bsp/black_vet6/syscfg.yml b/hw/bsp/black_vet6/syscfg.yml index e5653b1a04..82335b00a8 100644 --- a/hw/bsp/black_vet6/syscfg.yml +++ b/hw/bsp/black_vet6/syscfg.yml @@ -64,6 +64,7 @@ syscfg.vals: STM32_FLASH_PREFETCH_ENABLE: 1 STM32_INSTRUCTION_CACHE_ENABLE: 1 STM32_DATA_CACHE_ENABLE: 1 + STM32_WFI_FROM_RAM: 1 WATCHDOG_INTERVAL: 25000 SPI_0_MASTER: 1 diff --git a/hw/bsp/nucleo-l073rz/syscfg.yml b/hw/bsp/nucleo-l073rz/syscfg.yml index a964b30ff5..fa2678abe1 100644 --- a/hw/bsp/nucleo-l073rz/syscfg.yml +++ b/hw/bsp/nucleo-l073rz/syscfg.yml @@ -57,6 +57,7 @@ syscfg.vals: STM32_CLOCK_APB2_DIVIDER: 'RCC_HCLK_DIV1' STM32_FLASH_LATENCY: 1 # max 32MHz STM32_FLASH_PREFETCH_ENABLE: 0 + STM32_WFI_FROM_RAM: 1 WATCHDOG_INTERVAL: 25000 UART_0_PIN_TX: 'MCU_GPIO_PORTA(2)' UART_0_PIN_RX: 'MCU_GPIO_PORTA(3)' diff --git a/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml b/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml index 27cc90cce0..e6fb90f580 100644 --- a/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml +++ b/hw/bsp/olimex_stm32-e407_devboard/syscfg.yml @@ -48,6 +48,7 @@ syscfg.vals: STM32_FLASH_PREFETCH_ENABLE: 1 STM32_INSTRUCTION_CACHE_ENABLE: 1 STM32_DATA_CACHE_ENABLE: 1 + STM32_WFI_FROM_RAM: 1 WATCHDOG_INTERVAL: 28000 UART_0_PIN_TX: 'MCU_GPIO_PORTC(6)' UART_0_PIN_RX: 'MCU_GPIO_PORTC(7)' diff --git a/hw/mcu/stm/stm32_common/include/stm32_common/mcu.h b/hw/mcu/stm/stm32_common/include/stm32_common/mcu.h index b0612b58fd..a6c67fe212 100644 --- a/hw/mcu/stm/stm32_common/include/stm32_common/mcu.h +++ b/hw/mcu/stm/stm32_common/include/stm32_common/mcu.h @@ -108,6 +108,13 @@ extern "C" { void stm32_start_bootloader(void); +#if MYNEWT_VAL_STM32_WFI_FROM_RAM +extern void stm32_wfi_from_ram(void); +#define STM32_WFI stm32_wfi_from_ram +#else +#define STM32_WFI __WFI +#endif + #ifdef __cplusplus } #endif diff --git a/hw/mcu/stm/stm32_common/src/hal_os_tick.c b/hw/mcu/stm/stm32_common/src/hal_os_tick.c index fa7d14fdab..5323f2912e 100644 --- a/hw/mcu/stm/stm32_common/src/hal_os_tick.c +++ b/hw/mcu/stm/stm32_common/src/hal_os_tick.c @@ -18,7 +18,8 @@ */ #include -#include "os/mynewt.h" +#include +#include #include #if MYNEWT_VAL(OS_TICKS_USE_RTC) @@ -26,33 +27,23 @@ #include #endif +#if MYNEWT_VAL(STM32_WFI_FROM_RAM) +__attribute__((section(".text_ram"))) void +stm32_wfi_from_ram(void) +{ + __ASM volatile("wfi\n" + "bx lr"); +} +#endif + /* * ST's MCUs seems to have problem with accessing AHB interface from SWD during SLEEP. * This makes it almost impossible to use with SEGGER SystemView, therefore when OS_SYSVIEW * is defined __WFI will become a loop waiting for pending interrupts. */ #if MYNEWT_VAL(OS_SYSVIEW) -#undef __WFI -#define __WFI() do { } while ((SCB->ICSR & (SCB_ICSR_ISRPENDING_Msk | SCB_ICSR_PENDSTSET_Msk)) == 0) -#else -/* - * Errata for STM32F405, STM32F407, STM32F415, STM32F417. - * When WFI instruction is placed at address like 0x080xxxx4 - * (also seen for addresses ending with xxx2). System may - * crash. - * __WFI function places WFI instruction at address ending with x0 or x8 - * for affected MCUs. - */ -#if defined(STM32F405xx) || defined(STM32F407xx) || \ - defined(STM32F415xx) || defined(STM32F417xx) -#undef __WFI -__attribute__((aligned(8), naked)) void static -__WFI(void) -{ - __ASM volatile("wfi\n" - "bx lr"); -} -#endif +#undef STM32_WFI +#define STM32_WFI() do { } while ((SCB->ICSR & (SCB_ICSR_ISRPENDING_Msk | SCB_ICSR_PENDSTSET_Msk)) == 0) #endif #if MYNEWT_VAL(OS_TICKS_USE_RTC) @@ -219,7 +210,7 @@ os_tick_idle(os_time_t ticks) } __DSB(); - __WFI(); + STM32_WFI(); if (ticks > 0) { rtc_update_time(); @@ -389,7 +380,7 @@ os_tick_idle(os_time_t ticks) { OS_ASSERT_CRITICAL(); __DSB(); - __WFI(); + STM32_WFI(); } void diff --git a/hw/mcu/stm/stm32_common/syscfg.yml b/hw/mcu/stm/stm32_common/syscfg.yml index eeef9d7a09..1603bced6b 100644 --- a/hw/mcu/stm/stm32_common/syscfg.yml +++ b/hw/mcu/stm/stm32_common/syscfg.yml @@ -466,5 +466,11 @@ syscfg.defs: When enabled, OS_TICKS_PER_SEC should be one of 128, 256, 512, 1024. value: 0 + STM32_WFI_FROM_RAM: + description: > + Place WFI instruction in RAM instead of flash. + This may be needed for several MCU's including STM32F40x. + value: + syscfg.vals: OS_TICKS_PER_SEC: 1000