From 1e2f136252132397b2796c0e20f88e570b98f545 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 2 Dec 2024 00:21:45 -0700 Subject: [PATCH 1/6] arm: stm32: Add DTS describing ROM bootloader for f0 Add the ROM bootloader devicetree details for a stm32f072 SoC. Signed-off-by: Peter Johanson --- dts/arm/st/f0/stm32f072.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dts/arm/st/f0/stm32f072.dtsi b/dts/arm/st/f0/stm32f072.dtsi index c495d9af24f20..74dbbbfa30b40 100644 --- a/dts/arm/st/f0/stm32f072.dtsi +++ b/dts/arm/st/f0/stm32f072.dtsi @@ -10,6 +10,12 @@ soc { compatible = "st,stm32f072", "st,stm32f0", "simple-bus"; + rom_bootloader: rom_bootloader@1fffc800 { + compatible = "st,stm32-bootloader"; + reg = <0x1fffc800 DT_SIZE_K(12)>; + status = "okay"; + }; + can1: can@40006400 { compatible = "st,stm32-bxcan"; reg = <0x40006400 0x400>; From 15ebd8923863960e7bd41ed60556b970d8873f60 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 30 Sep 2025 23:20:38 -0600 Subject: [PATCH 2/6] dts: arm: st: Add STM32WB bootloader information Add the STM32 bootloader details to the relevant STM32WB .dtsi file. Signed-off-by: Peter Johanson --- dts/arm/st/wb/stm32wb.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dts/arm/st/wb/stm32wb.dtsi b/dts/arm/st/wb/stm32wb.dtsi index d467cdcc332bb..b931d73211b6e 100644 --- a/dts/arm/st/wb/stm32wb.dtsi +++ b/dts/arm/st/wb/stm32wb.dtsi @@ -145,6 +145,12 @@ }; soc { + rom_bootloader: rom_bootloader@1fff0000 { + compatible = "st,stm32-bootloader"; + reg = <0x1fff0000 DT_SIZE_K(28)>; + status = "okay"; + }; + flash: flash-controller@58004000 { compatible = "st,stm32-flash-controller", "st,stm32wb-flash-controller"; reg = <0x58004000 0x400>; From 1665daf5e431dbcc761f0fcacc0aae6aac4e5b23 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 30 Sep 2025 23:21:39 -0600 Subject: [PATCH 3/6] boards: st: Add boot mode retention support to Nucleo WB55RG board Setup a section of retained memory for boot mode retention on the Nucleo WB55RG board. Signed-off-by: Peter Johanson --- boards/st/nucleo_wb55rg/nucleo_wb55rg.dts | 27 +++++++++++++++++++++++ 1 file changed, 27 insertions(+) diff --git a/boards/st/nucleo_wb55rg/nucleo_wb55rg.dts b/boards/st/nucleo_wb55rg/nucleo_wb55rg.dts index 8c4c56d294ee3..680c646416b15 100644 --- a/boards/st/nucleo_wb55rg/nucleo_wb55rg.dts +++ b/boards/st/nucleo_wb55rg/nucleo_wb55rg.dts @@ -10,12 +10,18 @@ #include "arduino_r3_connector.dtsi" #include + +&sram0 { + reg = <0x20000000 (DT_SIZE_K(192) - 4)>; +}; + / { model = "STMicroelectronics STM32WB55RG-NUCLEO board"; compatible = "st,stm32wb55rg-nucleo"; chosen { zephyr,console = &usart1; + zephyr,boot-mode = &boot_mode; zephyr,shell-uart = &usart1; zephyr,bt-mon-uart = &lpuart1; zephyr,bt-c2h-uart = &lpuart1; @@ -24,6 +30,27 @@ zephyr,code-partition = &slot0_partition; }; + sram_ret@2002fffc { + compatible = "zephyr,memory-region", "mmio-sram"; + reg = <0x2002fffc 0x4>; + zephyr,memory-region = "RetainedMem"; + status = "okay"; + + retainedmem { + compatible = "zephyr,retained-ram"; + status = "okay"; + #address-cells = <1>; + #size-cells = <1>; + + boot_mode: retention@0 { + compatible = "zephyr,retention"; + status = "okay"; + reg = <0x0 0x1>; + }; + }; + }; + + leds: leds { compatible = "gpio-leds"; From c7e3b111e1bbdf46b44e86eebbbc9a985a3619a2 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Wed, 1 Oct 2025 02:49:39 -0600 Subject: [PATCH 4/6] arm: stm32: Add DTS describing ROM bootloader for f411 Add the ROM bootloader devicetree details for a stm32f411 SoC. Signed-off-by: Peter Johanson --- dts/arm/st/f4/stm32f411.dtsi | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/dts/arm/st/f4/stm32f411.dtsi b/dts/arm/st/f4/stm32f411.dtsi index 1cf4355bb3d5a..eba75034d195b 100644 --- a/dts/arm/st/f4/stm32f411.dtsi +++ b/dts/arm/st/f4/stm32f411.dtsi @@ -18,6 +18,12 @@ soc { compatible = "st,stm32f411", "st,stm32f4", "simple-bus"; + rom_bootloader: rom_bootloader@1fff0000 { + compatible = "st,stm32-bootloader"; + reg = <0x1fff0000 DT_SIZE_K(29)>; + status = "okay"; + }; + spi5: spi@40015000 { compatible = "st,stm32-spi"; #address-cells = <1>; From e6468414f60a9fd968f6a10a1327e2afaee319c9 Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Tue, 7 Oct 2025 15:05:23 -0600 Subject: [PATCH 5/6] retention: Skip mutex usage when in pre-kernel For early boot mode checking during initalization, skip mutex lock/unlock if in pre-kernel state for the retention and retained mem zephyr ram driver. Signed-off-by: Peter Johanson --- drivers/retained_mem/retained_mem_zephyr_ram.c | 8 ++++++-- subsys/retention/retention.c | 8 ++++++-- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/drivers/retained_mem/retained_mem_zephyr_ram.c b/drivers/retained_mem/retained_mem_zephyr_ram.c index 3410af1cbac09..f71742f41dc4c 100644 --- a/drivers/retained_mem/retained_mem_zephyr_ram.c +++ b/drivers/retained_mem/retained_mem_zephyr_ram.c @@ -33,7 +33,9 @@ static inline void zephyr_retained_mem_ram_lock_take(const struct device *dev) #ifdef CONFIG_RETAINED_MEM_MUTEXES struct zephyr_retained_mem_ram_data *data = dev->data; - k_mutex_lock(&data->lock, K_FOREVER); + if (!k_is_pre_kernel()) { + k_mutex_lock(&data->lock, K_FOREVER); + } #else ARG_UNUSED(dev); #endif @@ -44,7 +46,9 @@ static inline void zephyr_retained_mem_ram_lock_release(const struct device *dev #ifdef CONFIG_RETAINED_MEM_MUTEXES struct zephyr_retained_mem_ram_data *data = dev->data; - k_mutex_unlock(&data->lock); + if (!k_is_pre_kernel()) { + k_mutex_unlock(&data->lock); + } #else ARG_UNUSED(dev); #endif diff --git a/subsys/retention/retention.c b/subsys/retention/retention.c index b259b19886212..da7c0de652a95 100644 --- a/subsys/retention/retention.c +++ b/subsys/retention/retention.c @@ -63,7 +63,9 @@ static inline void retention_lock_take(const struct device *dev) #ifdef CONFIG_RETENTION_MUTEXES struct retention_data *data = dev->data; - k_mutex_lock(&data->lock, K_FOREVER); + if (!k_is_pre_kernel()) { + k_mutex_lock(&data->lock, K_FOREVER); + } #else ARG_UNUSED(dev); #endif @@ -74,7 +76,9 @@ static inline void retention_lock_release(const struct device *dev) #ifdef CONFIG_RETENTION_MUTEXES struct retention_data *data = dev->data; - k_mutex_unlock(&data->lock); + if (!k_is_pre_kernel()) { + k_mutex_unlock(&data->lock); + } #else ARG_UNUSED(dev); #endif From 65e92569679ee727f67a7236dd35483c82615c6f Mon Sep 17 00:00:00 2001 From: Peter Johanson Date: Mon, 2 Dec 2024 00:20:43 -0700 Subject: [PATCH 6/6] soc: arm: stm32: Add ROM bootloader support Add jump to ROM bootloader for STM32 when bootmode is set via retention boot mode feature. Signed-off-by: Peter Johanson --- dts/bindings/arm/st,stm32-bootloader.yaml | 12 ++++ soc/st/stm32/Kconfig | 15 +++++ soc/st/stm32/Kconfig.defconfig | 10 +++ soc/st/stm32/common/CMakeLists.txt | 2 + soc/st/stm32/common/stm32_bootloader.c | 74 +++++++++++++++++++++++ 5 files changed, 113 insertions(+) create mode 100644 dts/bindings/arm/st,stm32-bootloader.yaml create mode 100644 soc/st/stm32/common/stm32_bootloader.c diff --git a/dts/bindings/arm/st,stm32-bootloader.yaml b/dts/bindings/arm/st,stm32-bootloader.yaml new file mode 100644 index 0000000000000..ec1375a8bac5f --- /dev/null +++ b/dts/bindings/arm/st,stm32-bootloader.yaml @@ -0,0 +1,12 @@ +# Copyright (c) 2025 Peter Johanson +# SPDX-License-Identifier: Apache-2.0 + +description: ST STM32 ROM Bootloader Details + +compatible: "st,stm32-bootloader" + +include: base.yaml + +properties: + reg: + required: true diff --git a/soc/st/stm32/Kconfig b/soc/st/stm32/Kconfig index 812e4fb1c889d..ee943e3a0c653 100644 --- a/soc/st/stm32/Kconfig +++ b/soc/st/stm32/Kconfig @@ -38,6 +38,21 @@ config STM32_BACKUP_SRAM_INIT_PRIORITY help STM32 Backup SRAM device initialization priority. +config STM32_BOOTLOADER + bool "STM32 Bootloader Support" + default y + depends on RETENTION_BOOT_MODE && DT_HAS_ST_STM32_BOOTLOADER_ENABLED + help + Enable support for jumping into the STM32 bootloader when the + bootmode is set. + +config STM32_BOOTLOADER_INIT_PRIORITY + int "STM32 bootloader check init priority" + default 3 + help + STM32 bootloader check initialization priority (must be higher than init + priorities for retention/retained memory drivers). + config STM32_ENABLE_DEBUG_SLEEP_STOP bool "Allow debugger attach in stop/sleep Mode" help diff --git a/soc/st/stm32/Kconfig.defconfig b/soc/st/stm32/Kconfig.defconfig index 767b6c2321c5c..dfb78fcb41194 100644 --- a/soc/st/stm32/Kconfig.defconfig +++ b/soc/st/stm32/Kconfig.defconfig @@ -91,6 +91,16 @@ config CLOCK_CONTROL_INIT_PRIORITY default 1 depends on CLOCK_CONTROL +if STM32_BOOTLOADER + +config RETAINED_MEM_INIT_PRIORITY + default 1 + +config RETENTION_INIT_PRIORITY + default 2 + +endif + # Get flash configuration for NS image from dts flash partition config USE_DT_CODE_PARTITION default y if TRUSTED_EXECUTION_NONSECURE diff --git a/soc/st/stm32/common/CMakeLists.txt b/soc/st/stm32/common/CMakeLists.txt index ab854348305c9..be196a3b12ada 100644 --- a/soc/st/stm32/common/CMakeLists.txt +++ b/soc/st/stm32/common/CMakeLists.txt @@ -19,6 +19,8 @@ endif() zephyr_sources_ifdef(CONFIG_STM32_BACKUP_SRAM stm32_backup_sram.c) zephyr_linker_sources_ifdef(CONFIG_STM32_BACKUP_SRAM SECTIONS stm32_backup_sram.ld) +zephyr_sources_ifdef(CONFIG_STM32_BOOTLOADER stm32_bootloader.c) + if (NOT CONFIG_DEBUG AND CONFIG_PM) zephyr_sources_ifdef(CONFIG_DT_HAS_SWJ_CONNECTOR_ENABLED pm_debug_swj.c) endif() diff --git a/soc/st/stm32/common/stm32_bootloader.c b/soc/st/stm32/common/stm32_bootloader.c new file mode 100644 index 0000000000000..ebe891fe12e9b --- /dev/null +++ b/soc/st/stm32/common/stm32_bootloader.c @@ -0,0 +1,74 @@ +/* + * Copyright (c) 2020 Google LLC. + * + * SPDX-License-Identifier: Apache-2.0 + */ + +#include +#include +#include +#include +#include + +#if defined(CONFIG_ARM_MPU) +extern void arm_core_mpu_disable(void); +#endif + +static const uint32_t bootloader = DT_REG_ADDR(DT_INST(0, st_stm32_bootloader)); +static FUNC_NORETURN void jump_to_bootloader(void) +{ + int i; + void (*jmp)(void); + + __disable_irq(); + + for (i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) { + NVIC->ICER[i] = 0xFFFFFFFF; + NVIC->ICPR[i] = 0xFFFFFFFF; + } + +#if defined(CONFIG_ARM_MPU) + /* + * Needed to allow the bootloader to erase/write to flash, and the MPU + * is set up in the arch init phase. + */ + arm_core_mpu_disable(); +#endif + + /* + * Disable SysTick before jumping, to keep the bootloader happy + */ + SysTick->CTRL = 0; + + LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SYSTEMFLASH); + + jmp = (void (*)(void))(void (*)(void))(*((uint32_t *)((bootloader + 4)))); + + /* + * We need to clear a few things set by the Zephyr early startup code + */ + __set_CONTROL(0); +#if !defined(CONFIG_CPU_CORTEX_M0) + __set_BASEPRI(0); +#endif + + __set_MSP(*(uint32_t *)bootloader); + + __enable_irq(); + + jmp(); + + CODE_UNREACHABLE; +} + +static int bootloader_check_boot_init(void) +{ + if (bootmode_check(BOOT_MODE_TYPE_BOOTLOADER) > 0) { + bootmode_clear(); + jump_to_bootloader(); + } + + return 0; +} + +SYS_INIT(bootloader_check_boot_init, POST_KERNEL, CONFIG_STM32_BOOTLOADER_INIT_PRIORITY);