Loading...
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 | /* * Copyright (c) 2013-2014 Wind River Systems, Inc. * * SPDX-License-Identifier: Apache-2.0 */ /** * @file * @brief Full C support initialization * * * Initialization of full C support: zero the .bss, copy the .data if XIP, * call z_cstart(). * * Stack is available in this module, but not the global data/bss until their * initialization is performed. */ #include <kernel.h> #include <zephyr/types.h> #include <toolchain.h> #include <linker/linker-defs.h> #include <kernel_internal.h> #include <arch/arm/cortex_m/cmsis.h> #include <cortex_m/stack.h> #if defined(__GNUC__) /* * GCC can detect if memcpy is passed a NULL argument, however one of * the cases of relocate_vector_table() it is valid to pass NULL, so we * supress the warning for this case. We need to do this before * string.h is included to get the declaration of memcpy. */ #pragma GCC diagnostic push #pragma GCC diagnostic ignored "-Wnonnull" #endif #include <string.h> static inline void switch_sp_to_psp(void) { __set_CONTROL(__get_CONTROL() | CONTROL_SPSEL_Msk); /* * When changing the stack pointer, software must use an ISB instruction * immediately after the MSR instruction. This ensures that instructions * after the ISB instruction execute using the new stack pointer. */ __ISB(); } static inline void set_and_switch_to_psp(void) { u32_t process_sp; process_sp = (u32_t)&_interrupt_stack + CONFIG_ISR_STACK_SIZE; __set_PSP(process_sp); switch_sp_to_psp(); } void lock_interrupts(void) { #if defined(CONFIG_ARMV6_M_ARMV8_M_BASELINE) __disable_irq(); #elif defined(CONFIG_ARMV7_M_ARMV8_M_MAINLINE) __set_BASEPRI(_EXC_IRQ_DEFAULT_PRIO); #else #error Unknown ARM architecture #endif /* CONFIG_ARMV6_M_ARMV8_M_BASELINE */ } #ifdef CONFIG_INIT_STACKS static inline void init_stacks(void) { memset(&_interrupt_stack, 0xAA, CONFIG_ISR_STACK_SIZE); } #endif #ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR #ifdef CONFIG_XIP #define VECTOR_ADDRESS ((uintptr_t)_vector_start) #else #define VECTOR_ADDRESS CONFIG_SRAM_BASE_ADDRESS #endif static inline void relocate_vector_table(void) { SCB->VTOR = VECTOR_ADDRESS & SCB_VTOR_TBLOFF_Msk; __DSB(); __ISB(); } #else #if defined(CONFIG_SW_VECTOR_RELAY) Z_GENERIC_SECTION(.vt_pointer_section) void *_vector_table_pointer; #endif #define VECTOR_ADDRESS 0 void __weak relocate_vector_table(void) { #if defined(CONFIG_XIP) && (CONFIG_FLASH_BASE_ADDRESS != 0) || \ !defined(CONFIG_XIP) && (CONFIG_SRAM_BASE_ADDRESS != 0) size_t vector_size = (size_t)_vector_end - (size_t)_vector_start; (void)memcpy(VECTOR_ADDRESS, _vector_start, vector_size); #elif defined(CONFIG_SW_VECTOR_RELAY) _vector_table_pointer = _vector_start; #endif } #if defined(__GNUC__) #pragma GCC diagnostic pop #endif #endif /* CONFIG_CPU_CORTEX_M_HAS_VTOR */ #ifdef CONFIG_FLOAT static inline void enable_floating_point(void) { /* * Upon reset, the Co-Processor Access Control Register is 0x00000000. * Enable CP10 and CP11 co-processors to enable floating point. */ SCB->CPACR |= CPACR_CP10_FULL_ACCESS | CPACR_CP11_FULL_ACCESS; /* * Upon reset, the FPU Context Control Register is 0xC0000000 * (both Automatic and Lazy state preservation is enabled). * Disable lazy state preservation so the volatile FP registers are * always saved on exception. */ FPU->FPCCR = FPU_FPCCR_ASPEN_Msk; /* FPU_FPCCR_LSPEN = 0 */ /* * Although automatic state preservation is enabled, the processor * does not automatically save the volatile FP registers until they * have first been touched. Perform a dummy move operation so that * the stack frames are created as expected before any thread * context switching can occur. It has to be surrounded by instruction * synchronization barriers to ensure that the whole sequence is * serialized. */ __asm__ volatile( "isb;\n\t" "vmov s0, s0;\n\t" "isb;\n\t" ); } #else static inline void enable_floating_point(void) { } #endif extern FUNC_NORETURN void z_cstart(void); /** * * @brief Prepare to and run C code * * This routine prepares for the execution of and runs C code. * * @return N/A */ extern void _IntLibInit(void); #ifdef CONFIG_BOOT_TIME_MEASUREMENT extern u64_t __start_time_stamp; #endif void _PrepC(void) { #ifdef CONFIG_INIT_STACKS init_stacks(); #endif /* * Set PSP and use it to boot without using MSP, so that it * gets set to _interrupt_stack during initialization. */ set_and_switch_to_psp(); relocate_vector_table(); enable_floating_point(); z_bss_zero(); z_data_copy(); #ifdef CONFIG_BOOT_TIME_MEASUREMENT __start_time_stamp = 0U; #endif _IntLibInit(); z_cstart(); CODE_UNREACHABLE; } |