Skip to content

Commit

Permalink
hw/mcu/stm32: Add option to place WFI in RAM
Browse files Browse the repository at this point in the history
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 <jerzy@apache.org>
  • Loading branch information
kasjer committed Jun 2, 2024
1 parent 5c11744 commit 06a50df
Show file tree
Hide file tree
Showing 8 changed files with 33 additions and 24 deletions.
1 change: 1 addition & 0 deletions hw/bsp/ada_feather_stm32f405/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)'
Expand Down
1 change: 1 addition & 0 deletions hw/bsp/b-l072z-lrwan1/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)'
Expand Down
1 change: 1 addition & 0 deletions hw/bsp/black_vet6/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
1 change: 1 addition & 0 deletions hw/bsp/nucleo-l073rz/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)'
Expand Down
1 change: 1 addition & 0 deletions hw/bsp/olimex_stm32-e407_devboard/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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)'
Expand Down
7 changes: 7 additions & 0 deletions hw/mcu/stm/stm32_common/include/stm32_common/mcu.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
39 changes: 15 additions & 24 deletions hw/mcu/stm/stm32_common/src/hal_os_tick.c
Original file line number Diff line number Diff line change
Expand Up @@ -18,41 +18,32 @@
*/

#include <assert.h>
#include "os/mynewt.h"
#include <os/mynewt.h>
#include <stm32_common/mcu.h>
#include <hal/hal_os_tick.h>

#if MYNEWT_VAL(OS_TICKS_USE_RTC)
#include <stm32_common/stm32_hal.h>
#include <datetime/datetime.h>
#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)
Expand Down Expand Up @@ -219,7 +210,7 @@ os_tick_idle(os_time_t ticks)
}

__DSB();
__WFI();
STM32_WFI();

if (ticks > 0) {
rtc_update_time();
Expand Down Expand Up @@ -389,7 +380,7 @@ os_tick_idle(os_time_t ticks)
{
OS_ASSERT_CRITICAL();
__DSB();
__WFI();
STM32_WFI();
}

void
Expand Down
6 changes: 6 additions & 0 deletions hw/mcu/stm/stm32_common/syscfg.yml
Original file line number Diff line number Diff line change
Expand Up @@ -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

0 comments on commit 06a50df

Please sign in to comment.