1/* 2 * Copyright (c) 2013-2014 Wind River Systems, Inc. 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 */ 6 7/** 8 * @file 9 * @brief Reset handler 10 * 11 * Reset handler that prepares the system for running C code. 12 */ 13 14#include <zephyr/toolchain.h> 15#include <zephyr/linker/sections.h> 16#include <zephyr/arch/cpu.h> 17#include "vector_table.h" 18 19_ASM_FILE_PROLOGUE 20 21GTEXT(z_arm_reset) 22GTEXT(z_early_memset) 23GDATA(z_interrupt_stacks) 24#if defined(CONFIG_DEBUG_THREAD_INFO) 25GDATA(z_sys_post_kernel) 26#endif 27#if defined(CONFIG_SOC_RESET_HOOK) 28GTEXT(soc_reset_hook) 29#endif 30#if defined(CONFIG_INIT_ARCH_HW_AT_BOOT) 31GTEXT(z_arm_init_arch_hw_at_boot) 32GDATA(z_main_stack) 33#endif 34#if defined(CONFIG_PM_S2RAM) 35GTEXT(arch_pm_s2ram_resume) 36#endif 37 38/** 39 * 40 * @brief Reset vector 41 * 42 * Ran when the system comes out of reset, or when the firmware image is chain- 43 * loaded by another application (for instance, a bootloader). At minimum, the 44 * processor must be in thread mode with privileged level. At this point, the 45 * main stack pointer (MSP) should be already pointing to a valid area in SRAM. 46 * 47 * Locking interrupts prevents anything but NMIs and hard faults from 48 * interrupting the CPU. A default NMI handler is already in place in the 49 * vector table, and the boot code should not generate hard fault, or we're in 50 * deep trouble. 51 * 52 * We want to use the process stack pointer (PSP) instead of the MSP, since the 53 * MSP is to be set up to point to the one-and-only interrupt stack during 54 * later boot. That would not be possible if in use for running C code. 55 * 56 * When these steps are completed, jump to z_prep_c(), which will finish 57 * setting up the system for running C code. 58 * 59 */ 60 61SECTION_SUBSEC_FUNC(TEXT,_reset_section,z_arm_reset) 62 63/* 64 * The entry point is located at the z_arm_reset symbol, which 65 * is fetched by a XIP image playing the role of a bootloader, which jumps to 66 * it, not through the reset vector mechanism. Such bootloaders might want to 67 * search for a __start symbol instead, so create that alias here. 68 */ 69SECTION_SUBSEC_FUNC(TEXT,_reset_section,__start) 70 71#if defined(CONFIG_DEBUG_THREAD_INFO) 72 /* Clear z_sys_post_kernel flag for RTOS aware debuggers */ 73 movs.n r0, #0 74 ldr r1, =z_sys_post_kernel 75 strb r0, [r1] 76#endif /* CONFIG_DEBUG_THREAD_INFO */ 77 78#if defined(CONFIG_INIT_ARCH_HW_AT_BOOT) 79 /* Reset CONTROL register */ 80 movs.n r0, #0 81 msr CONTROL, r0 82 isb 83#if defined(CONFIG_CPU_CORTEX_M_HAS_SPLIM) 84 /* Clear SPLIM registers */ 85 movs.n r0, #0 86 msr MSPLIM, r0 87 msr PSPLIM, r0 88#endif /* CONFIG_CPU_CORTEX_M_HAS_SPLIM */ 89 90#endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */ 91 92#if defined(CONFIG_PM_S2RAM) 93 bl arch_pm_s2ram_resume 94#endif /* CONFIG_PM_S2RAM */ 95 96#if defined(CONFIG_SOC_RESET_HOOK) 97 bl soc_reset_hook 98#endif 99 100#if defined(CONFIG_INIT_ARCH_HW_AT_BOOT) 101#if defined(CONFIG_CPU_HAS_ARM_MPU) 102 /* Disable MPU */ 103 movs.n r0, #0 104 ldr r1, =_SCS_MPU_CTRL 105 str r0, [r1] 106 dsb 107#endif /* CONFIG_CPU_HAS_ARM_MPU */ 108 ldr r0, =z_main_stack + CONFIG_MAIN_STACK_SIZE 109 msr msp, r0 110 111 /* Initialize core architecture registers and system blocks */ 112 bl z_arm_init_arch_hw_at_boot 113#endif /* CONFIG_INIT_ARCH_HW_AT_BOOT */ 114 115 /* lock interrupts: will get unlocked when switch to main task */ 116#if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) 117 cpsid i 118#elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) 119 movs.n r0, #_EXC_IRQ_DEFAULT_PRIO 120 msr BASEPRI, r0 121#else 122#error Unknown ARM architecture 123#endif 124 125#ifdef CONFIG_WDOG_INIT 126 /* board-specific watchdog initialization is necessary */ 127 bl z_arm_watchdog_init 128#endif 129 130/* 131 * 132 * Note: in all Cortex-M variants the interrupt stack area is at 133 * least equal to CONFIG_ISR_STACK_SIZE + MPU_GUARD_ALIGN_AND_SIZE 134 * (may be larger due to rounding up for stack pointer aligning 135 * purposes but this is sufficient during initialization). 136 */ 137 138#ifdef CONFIG_INIT_STACKS 139 ldr r0, =z_interrupt_stacks 140 ldr r1, =0xaa 141 ldr r2, =CONFIG_ISR_STACK_SIZE + MPU_GUARD_ALIGN_AND_SIZE 142 bl z_early_memset 143#endif 144 145 /* 146 * Set PSP and use it to boot without using MSP, so that it 147 * gets set to z_interrupt_stacks during initialization. 148 */ 149 ldr r0, =z_interrupt_stacks 150 ldr r1, =CONFIG_ISR_STACK_SIZE + MPU_GUARD_ALIGN_AND_SIZE 151 adds r0, r0, r1 152 msr PSP, r0 153 mrs r0, CONTROL 154 movs r1, #2 155 orrs r0, r1 /* CONTROL_SPSEL_Msk */ 156 msr CONTROL, r0 157 /* 158 * When changing the stack pointer, software must use an ISB instruction 159 * immediately after the MSR instruction. This ensures that instructions 160 * after the ISB instruction execute using the new stack pointer. 161 */ 162 isb 163 164 /* 165 * 'bl' jumps the furthest of the branch instructions that are 166 * supported on all platforms. So it is used when jumping to z_prep_c 167 * (even though we do not intend to return). 168 */ 169 bl z_prep_c 170