|  | 
|  | 1 | +/* | 
|  | 2 | + * Copyright (c) 2020 Google LLC. | 
|  | 3 | + * | 
|  | 4 | + * SPDX-License-Identifier: Apache-2.0 | 
|  | 5 | + */ | 
|  | 6 | + | 
|  | 7 | +#include <soc.h> | 
|  | 8 | +#include <zephyr/init.h> | 
|  | 9 | +#include <zephyr/retention/retention.h> | 
|  | 10 | +#include <zephyr/retention/bootmode.h> | 
|  | 11 | +#include <stm32_ll_system.h> | 
|  | 12 | + | 
|  | 13 | +#if defined(CONFIG_ARM_MPU) | 
|  | 14 | +extern void arm_core_mpu_disable(void); | 
|  | 15 | +#endif | 
|  | 16 | + | 
|  | 17 | +static const uint32_t bootloader = DT_REG_ADDR(DT_INST(0, st_stm32_bootloader)); | 
|  | 18 | +static FUNC_NORETURN void jump_to_bootloader(void) | 
|  | 19 | +{ | 
|  | 20 | +	int i; | 
|  | 21 | +	void (*jmp)(void); | 
|  | 22 | + | 
|  | 23 | +	__disable_irq(); | 
|  | 24 | + | 
|  | 25 | +	for (i = 0; i < ARRAY_SIZE(NVIC->ICER); i++) { | 
|  | 26 | +		NVIC->ICER[i] = 0xFFFFFFFF; | 
|  | 27 | +		NVIC->ICPR[i] = 0xFFFFFFFF; | 
|  | 28 | +	} | 
|  | 29 | + | 
|  | 30 | +#if defined(CONFIG_ARM_MPU) | 
|  | 31 | +	/* | 
|  | 32 | +	 * Needed to allow the bootloader to erase/write to flash, and the MPU | 
|  | 33 | +	 * is set up in the arch init phase. | 
|  | 34 | +	 */ | 
|  | 35 | +	arm_core_mpu_disable(); | 
|  | 36 | +#endif | 
|  | 37 | + | 
|  | 38 | +	LL_SYSCFG_SetRemapMemory(LL_SYSCFG_REMAP_SYSTEMFLASH); | 
|  | 39 | + | 
|  | 40 | +	jmp = (void (*)(void))(void (*)(void))(*((uint32_t *)((bootloader + 4)))); | 
|  | 41 | + | 
|  | 42 | +	/* | 
|  | 43 | +	 * We need to clear a few things set by the Zephyr early startup code | 
|  | 44 | +	 */ | 
|  | 45 | +	__set_CONTROL(0); | 
|  | 46 | +#if !defined(CONFIG_CPU_CORTEX_M0) | 
|  | 47 | +	__set_BASEPRI(0); | 
|  | 48 | +#endif | 
|  | 49 | + | 
|  | 50 | +	__set_MSP(*(uint32_t *)bootloader); | 
|  | 51 | + | 
|  | 52 | +	__enable_irq(); | 
|  | 53 | + | 
|  | 54 | +	jmp(); | 
|  | 55 | + | 
|  | 56 | +	CODE_UNREACHABLE; | 
|  | 57 | +} | 
|  | 58 | + | 
|  | 59 | +static int bootloader_check_boot_init(void) | 
|  | 60 | +{ | 
|  | 61 | +	if (bootmode_check(BOOT_MODE_TYPE_BOOTLOADER) > 0) { | 
|  | 62 | +		bootmode_clear(); | 
|  | 63 | +		jump_to_bootloader(); | 
|  | 64 | +	} | 
|  | 65 | + | 
|  | 66 | +	return 0; | 
|  | 67 | +} | 
|  | 68 | + | 
|  | 69 | +SYS_INIT(bootloader_check_boot_init, PRE_KERNEL_1, 3); | 
0 commit comments