diff --git a/arch/arm/core/cortex_m/reset.S b/arch/arm/core/cortex_m/reset.S index 6bdf8d4a8e9..85002c275f7 100644 --- a/arch/arm/core/cortex_m/reset.S +++ b/arch/arm/core/cortex_m/reset.S @@ -35,6 +35,10 @@ GTEXT(z_arm_init_arch_hw_at_boot) #if defined(CONFIG_PM_S2RAM) GTEXT(arch_pm_s2ram_resume) #endif +#if defined(CONFIG_SOC_EARLY_RESET_HOOK) +GTEXT(soc_early_reset_hook) +#endif + /* * PACBTI Mask for CONTROL register: @@ -100,18 +104,11 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start) #endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */ +#if defined(CONFIG_SOC_EARLY_RESET_HOOK) + /* Call custom code that executes before any stack is set up or RAM memory is accessed */ + bl soc_early_reset_hook +#endif #if defined(CONFIG_PM_S2RAM) -#if DT_NODE_EXISTS(DT_NODELABEL(pm_s2ram_stack)) &&\ - DT_NODE_HAS_COMPAT(DT_NODELABEL(pm_s2ram_stack), zephyr_memory_region) - /* In certain scenarios, the interrupt stack is actually not safe to overwrite. - * For example, when MCUboot is used, the bootloader's "z_interrupt_stack" and the - * loaded image's "z_interrupt_stacks" are NOT at the same address, and writing to - * the former would corrupt unrelated data from the loaded image. To support such - * scenarios, if the Device Tree provides a specially named "zephyr,memory-region", - * use it as the stack to run arch_pm_s2ram_resume instead of the interrupt stack. - */ - ldr r0, =DT_REG_ADDR(DT_NODELABEL(pm_s2ram_stack)) + DT_REG_SIZE(DT_NODELABEL(pm_s2ram_stack)) -#else /* * Temporarily set MSP to interrupt stack so that arch_pm_s2ram_resume can * use stack for calling pm_s2ram_mark_check_and_clear. @@ -124,7 +121,6 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start) * a short while, there is no change in behavior in either of the paths. */ ldr r0, =z_interrupt_stacks + CONFIG_ISR_STACK_SIZE + MPU_GUARD_ALIGN_AND_SIZE -#endif msr msp, r0 bl arch_pm_s2ram_resume diff --git a/include/zephyr/platform/hooks.h b/include/zephyr/platform/hooks.h index 9989f640d65..12defd10ab8 100644 --- a/include/zephyr/platform/hooks.h +++ b/include/zephyr/platform/hooks.h @@ -19,6 +19,19 @@ * directly from application code but may be freely used within the OS. */ +#ifdef CONFIG_SOC_EARLY_RESET_HOOK +/** + * @brief SoC hook executed before data RAM initialization, at the beginning + * of the reset vector. + * + * This hook is implemented by the SoC and can be used to perform any + * SoC-specific initialization. Refer to :kconfig:option:`SOC_EARLY_RESET_HOOK` + * and relevant architecture zephyr-rtos startup implementation for more details. + */ +void soc_early_reset_hook(void); +#else +#define soc_early_reset_hook() do { } while (0) +#endif /** * @brief SoC hook executed at the beginning of the reset vector. diff --git a/kernel/Kconfig.init b/kernel/Kconfig.init index 495381638fb..c752fa5a0e4 100644 --- a/kernel/Kconfig.init +++ b/kernel/Kconfig.init @@ -6,6 +6,28 @@ menu "SoC and Board Hooks" +config SOC_EARLY_RESET_HOOK + bool "Run SoC-specific early reset hook" + help + Run a SoC-specific hook early in the reset/startup code (__start). + A custom hook soc_early_reset_hook() will be executed at the beginning + of the architecture-specific startup code, after hardware has been + configured (as required by CONFIG_INIT_ARCH_HW_AT_BOOT) but before + architecture's own resume logic. + + Returning from this hook is not mandatory: it can be used to implement + special logic to resume execution in some scenarios (for example, when + a bootloader is used). + + The stack pointer register should be considered as not initialized upon + call to this hook. In particular, this means that the hook is NOT allowed + to "push" any data using this stack pointer value. However, the hook may + use an implementation-specific area as stack if desired; in such case, + the original value of the stack pointer needs not to be "restored" before + returning control to the hook's caller. + + Additional constraints may be imposed on the hook by the architecture. + config SOC_RESET_HOOK bool "Run early SoC reset hook" help diff --git a/subsys/pm/Kconfig b/subsys/pm/Kconfig index 53c649799cc..af0409de559 100644 --- a/subsys/pm/Kconfig +++ b/subsys/pm/Kconfig @@ -41,11 +41,6 @@ config PM_S2RAM When enabled on Cortex-M, and a 'zephyr,memory-region' compatible node with nodelabel 'pm_s2ram' is defined in DT, _cpu_context symbol (located in arch/arm/core/cortex_m/pm_s2ram.c) is placed in linker section given by 'zephyr,memory-region' property of aforementioned node. - Additionally on Cortex-M, if a 'zephyr,memory-region' compatible node with nodelabel - 'pm_s2ram_stack' is defined in DT, this region will be used as a temporary program stack - for the S2RAM resume logic. The assembly reset handling code itself makes a single push of - the return address, but the SoC-specific function (pm_s2ram_mark_check_and_clear) must be - analyzed to determine the required stack size. config PM_S2RAM_CUSTOM_MARKING bool "Use custom marking functions"