Branch data Line data Source code
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 Full C support initialization 10 : : * 11 : : * 12 : : * Initialization of full C support: zero the .bss, copy the .data if XIP, 13 : : * call z_cstart(). 14 : : * 15 : : * Stack is available in this module, but not the global data/bss until their 16 : : * initialization is performed. 17 : : */ 18 : : 19 : : #include <kernel.h> 20 : : #include <kernel_internal.h> 21 : : #include <linker/linker-defs.h> 22 : : 23 : : #if defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A) 24 : : #include <aarch32/cortex_a_r/stack.h> 25 : : #endif 26 : : 27 : : #if defined(__GNUC__) 28 : : /* 29 : : * GCC can detect if memcpy is passed a NULL argument, however one of 30 : : * the cases of relocate_vector_table() it is valid to pass NULL, so we 31 : : * suppress the warning for this case. We need to do this before 32 : : * string.h is included to get the declaration of memcpy. 33 : : */ 34 : : #pragma GCC diagnostic push 35 : : #pragma GCC diagnostic ignored "-Wnonnull" 36 : : #endif 37 : : 38 : : #include <string.h> 39 : : 40 : : #if defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) 41 : : Z_GENERIC_SECTION(.vt_pointer_section) __attribute__((used)) 42 : : void *_vector_table_pointer; 43 : : #endif 44 : : 45 : : #ifdef CONFIG_CPU_CORTEX_M_HAS_VTOR 46 : : 47 : : #define VECTOR_ADDRESS ((uintptr_t)_vector_start) 48 : : 49 : 0 : static inline void relocate_vector_table(void) 50 : : { 51 : 0 : SCB->VTOR = VECTOR_ADDRESS & SCB_VTOR_TBLOFF_Msk; 52 : : __DSB(); 53 : : __ISB(); 54 : 0 : } 55 : : 56 : : #elif defined(CONFIG_AARCH32_ARMV8_R) 57 : : 58 : : #define VECTOR_ADDRESS ((uintptr_t)_vector_start) 59 : : 60 : : static inline void relocate_vector_table(void) 61 : : { 62 : : write_vbar(VECTOR_ADDRESS & VBAR_MASK); 63 : : __ISB(); 64 : : } 65 : : 66 : : #else 67 : : #define VECTOR_ADDRESS 0 68 : : 69 : : void __weak relocate_vector_table(void) 70 : : { 71 : : #if defined(CONFIG_XIP) && (CONFIG_FLASH_BASE_ADDRESS != 0) || \ 72 : : !defined(CONFIG_XIP) && (CONFIG_SRAM_BASE_ADDRESS != 0) 73 : : size_t vector_size = (size_t)_vector_end - (size_t)_vector_start; 74 : : (void)memcpy(VECTOR_ADDRESS, _vector_start, vector_size); 75 : : #elif defined(CONFIG_SW_VECTOR_RELAY) || defined(CONFIG_SW_VECTOR_RELAY_CLIENT) 76 : : _vector_table_pointer = _vector_start; 77 : : #endif 78 : : } 79 : : 80 : : #if defined(__GNUC__) 81 : : #pragma GCC diagnostic pop 82 : : #endif 83 : : 84 : : #endif /* CONFIG_CPU_CORTEX_M_HAS_VTOR */ 85 : : 86 : : #if defined(CONFIG_CPU_HAS_FPU) 87 : 0 : static inline void z_arm_floating_point_init(void) 88 : : { 89 : : /* 90 : : * Upon reset, the Co-Processor Access Control Register is, normally, 91 : : * 0x00000000. However, it might be left un-cleared by firmware running 92 : : * before Zephyr boot. 93 : : */ 94 : 0 : SCB->CPACR &= (~(CPACR_CP10_Msk | CPACR_CP11_Msk)); 95 : : 96 : : #if defined(CONFIG_FPU) 97 : : /* 98 : : * Enable CP10 and CP11 Co-Processors to enable access to floating 99 : : * point registers. 100 : : */ 101 : : #if defined(CONFIG_USERSPACE) 102 : : /* Full access */ 103 : : SCB->CPACR |= CPACR_CP10_FULL_ACCESS | CPACR_CP11_FULL_ACCESS; 104 : : #else 105 : : /* Privileged access only */ 106 : : SCB->CPACR |= CPACR_CP10_PRIV_ACCESS | CPACR_CP11_PRIV_ACCESS; 107 : : #endif /* CONFIG_USERSPACE */ 108 : : /* 109 : : * Upon reset, the FPU Context Control Register is 0xC0000000 110 : : * (both Automatic and Lazy state preservation is enabled). 111 : : */ 112 : : #if defined(CONFIG_MULTITHREADING) && !defined(CONFIG_FPU_SHARING) 113 : : /* Unshared FP registers (multithreading) mode. We disable the 114 : : * automatic stacking of FP registers (automatic setting of 115 : : * FPCA bit in the CONTROL register), upon exception entries, 116 : : * as the FP registers are to be used by a single context (and 117 : : * the use of FP registers in ISRs is not supported). This 118 : : * configuration improves interrupt latency and decreases the 119 : : * stack memory requirement for the (single) thread that makes 120 : : * use of the FP co-processor. 121 : : */ 122 : : FPU->FPCCR &= (~(FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk)); 123 : : #else 124 : : /* 125 : : * FP register sharing (multithreading) mode or single-threading mode. 126 : : * 127 : : * Enable both automatic and lazy state preservation of the FP context. 128 : : * The FPCA bit of the CONTROL register will be automatically set, if 129 : : * the thread uses the floating point registers. Because of lazy state 130 : : * preservation the volatile FP registers will not be stacked upon 131 : : * exception entry, however, the required area in the stack frame will 132 : : * be reserved for them. This configuration improves interrupt latency. 133 : : * The registers will eventually be stacked when the thread is swapped 134 : : * out during context-switch or if an ISR attempts to execute floating 135 : : * point instructions. 136 : : */ 137 : : FPU->FPCCR = FPU_FPCCR_ASPEN_Msk | FPU_FPCCR_LSPEN_Msk; 138 : : #endif /* CONFIG_FPU_SHARING */ 139 : : 140 : : /* Make the side-effects of modifying the FPCCR be realized 141 : : * immediately. 142 : : */ 143 : : __DSB(); 144 : : __ISB(); 145 : : 146 : : /* Initialize the Floating Point Status and Control Register. */ 147 : : #if defined(CONFIG_ARMV8_1_M_MAINLINE) 148 : : /* 149 : : * For ARMv8.1-M with FPU, the FPSCR[18:16] LTPSIZE field must be set 150 : : * to 0b100 for "Tail predication not applied" as it's reset value 151 : : */ 152 : : __set_FPSCR(4 << FPU_FPDSCR_LTPSIZE_Pos); 153 : : #else 154 : : __set_FPSCR(0); 155 : : #endif 156 : : 157 : : /* 158 : : * Note: 159 : : * The use of the FP register bank is enabled, however the FP context 160 : : * will be activated (FPCA bit on the CONTROL register) in the presence 161 : : * of floating point instructions. 162 : : */ 163 : : 164 : : #endif /* CONFIG_FPU */ 165 : : 166 : : /* 167 : : * Upon reset, the CONTROL.FPCA bit is, normally, cleared. However, 168 : : * it might be left un-cleared by firmware running before Zephyr boot. 169 : : * We must clear this bit to prevent errors in exception unstacking. 170 : : * 171 : : * Note: 172 : : * In Sharing FP Registers mode CONTROL.FPCA is cleared before switching 173 : : * to main, so it may be skipped here (saving few boot cycles). 174 : : * 175 : : * If CONFIG_INIT_ARCH_HW_AT_BOOT is set, CONTROL is cleared at reset. 176 : : */ 177 : : #if (!defined(CONFIG_FPU) || !defined(CONFIG_FPU_SHARING)) && \ 178 : : (!defined(CONFIG_INIT_ARCH_HW_AT_BOOT)) 179 : : 180 : : __set_CONTROL(__get_CONTROL() & (~(CONTROL_FPCA_Msk))); 181 : : #endif 182 : 0 : } 183 : : #endif /* CONFIG_CPU_HAS_FPU */ 184 : : 185 : : extern FUNC_NORETURN void z_cstart(void); 186 : : 187 : : /** 188 : : * 189 : : * @brief Prepare to and run C code 190 : : * 191 : : * This routine prepares for the execution of and runs C code. 192 : : * 193 : : */ 194 : 0 : void z_arm_prep_c(void) 195 : : { 196 : 0 : relocate_vector_table(); 197 : : #if defined(CONFIG_CPU_HAS_FPU) 198 : 0 : z_arm_floating_point_init(); 199 : : #endif 200 : 0 : z_bss_zero(); 201 : 1 : z_data_copy(); 202 : : #if ((defined(CONFIG_ARMV7_R) || defined(CONFIG_ARMV7_A)) && defined(CONFIG_INIT_STACKS)) 203 : : z_arm_init_stacks(); 204 : : #endif 205 : 1 : z_arm_interrupt_init(); 206 : 1 : z_cstart(); 207 : : CODE_UNREACHABLE; 208 : : }