@@ -21,6 +21,7 @@ _ASM_FILE_PROLOGUE
2121GTEXT(z_arm_reset)
2222GTEXT(z_early_memset)
2323GDATA(z_interrupt_stacks)
24+ GDATA(z_main_stack)
2425#if defined(CONFIG_DEBUG_THREAD_INFO)
2526GDATA(z_sys_post_kernel)
2627#endif
@@ -29,7 +30,6 @@ GTEXT(soc_reset_hook)
2930#endif
3031#if defined(CONFIG_INIT_ARCH_HW_AT_BOOT)
3132GTEXT(z_arm_init_arch_hw_at_boot)
32- GDATA(z_main_stack)
3333#endif
3434#if defined(CONFIG_PM_S2RAM)
3535GTEXT(arch_pm_s2ram_resume)
@@ -83,9 +83,44 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
8383#endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */
8484
8585#if defined(CONFIG_PM_S2RAM)
86+ /*
87+ * Temporarily set MSP to interrupt stack so that arch_pm_s2ram_resume can
88+ * use stack for calling pm_s2ram_mark_check_and_clear.
89+ * This is safe because suspend never being called from an ISR ensures that
90+ * interrupt stack was not live during suspend.
91+ * Note:
92+ * if resuming from suspend, MSP is restored from cpu context
93+ * if not resuming, MSP will be set back to z_main_stack for proper init
94+ * And, apart from arch_pm_s2ram_resume being able to use the stack for
95+ * a short while, there is no change in behavior in either of the paths.
96+ */
97+ ldr r0, =z_interrupt_stacks + CONFIG_ISR_STACK_SIZE + MPU_GUARD_ALIGN_AND_SIZE
98+ msr msp, r0
99+
86100 bl arch_pm_s2ram_resume
87101#endif /* CONFIG_PM_S2RAM */
88102
103+ /*
104+ * MSP needs to be set to main stack for following scenarios:
105+ * - If CONFIG_PM_S2RAM is enabled, MSP is set to z_interrupt_stacks
106+ * for resume functions to make use of a stack. However,
107+ * if the device was not suspended and if resume functions return,
108+ * MSP needs to be set back to z_main_stack to ensure proper
109+ * initialization.
110+ * - If CONFIG_PM_S2RAM is not enabled but CONFIG_INIT_ARCH_HW_AT_BOOT is,
111+ * MSP needs to be set to z_main_stack for proper initialization in case
112+ * device was loaded through chain loading or a debugger, as the initial
113+ * value of MSP would be anything that the previous image loaded.
114+ * - If CONFIG_INIT_STACKS is enabled, we need to ensure MSP is not set
115+ * to z_interrupt_stacks, so we set it to z_main_stack.
116+ *
117+ * Since these scenarios cover most of the cases, we set MSP to
118+ * z_main_stack here.
119+ *
120+ */
121+ ldr r0, =z_main_stack + CONFIG_MAIN_STACK_SIZE
122+ msr msp, r0
123+
89124 /* Note: Make sure that variables like z_sys_post_kernel
90125 * are set after the call to arch_pm_s2ram_resume
91126 * to avoid any issues with suspend/resume path.
@@ -110,8 +145,6 @@ SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start)
110145 str r0, [r1]
111146 dsb
112147#endif /* CONFIG_CPU_HAS_ARM_MPU */
113- ldr r0, =z_main_stack + CONFIG_MAIN_STACK_SIZE
114- msr msp, r0
115148
116149 /* Initialize core architecture registers and system blocks */
117150 bl z_arm_init_arch_hw_at_boot
0 commit comments