1/* 2 * Copyright (c) 2006-2018, RT-Thread Development Team 3 * 4 * SPDX-License-Identifier: Apache-2.0 5 * 6 * Change Logs: 7 * Date Author Notes 8 * 2015-04-06 zchong the first version 9 */ 10 11 MODULE ?cstartup 12 13 ; -------------------- 14; Mode, correspords to bits 0-5 in CPSR 15 16MODE_MSK DEFINE 0x1F ; Bit mask for mode bits in CPSR 17I_Bit DEFINE 0x80 ; when I bit is set, IRQ is disabled 18F_Bit DEFINE 0x40 ; when F bit is set, FIQ is disabled 19 20USR_MODE DEFINE 0x10 ; User mode 21FIQ_MODE DEFINE 0x11 ; Fast Interrupt Request mode 22IRQ_MODE DEFINE 0x12 ; Interrupt Request mode 23SVC_MODE DEFINE 0x13 ; Supervisor mode 24ABT_MODE DEFINE 0x17 ; Abort mode 25UND_MODE DEFINE 0x1B ; Undefined Instruction mode 26SYS_MODE DEFINE 0x1F ; System mode 27 28 29 ;; Forward declaration of sections. 30 SECTION IRQ_STACK:DATA:NOROOT(3) 31 SECTION FIQ_STACK:DATA:NOROOT(3) 32 SECTION SVC_STACK:DATA:NOROOT(3) 33 SECTION ABT_STACK:DATA:NOROOT(3) 34 SECTION UND_STACK:DATA:NOROOT(3) 35 SECTION CSTACK:DATA:NOROOT(3) 36 SECTION .text:CODE 37 38 39 SECTION .intvec:CODE:NOROOT(5) 40 41 PUBLIC __vector 42 PUBLIC __iar_program_start 43 44 45__iar_init$$done: ; The vector table is not needed 46 ; until after copy initialization is done 47 48__vector: ; Make this a DATA label, so that stack usage 49 ; analysis doesn't consider it an uncalled fun 50 ARM 51 52 ; All default exception handlers (except reset) are 53 ; defined as weak symbol definitions. 54 ; If a handler is defined by the application it will take precedence. 55 LDR PC,Reset_Addr ; Reset 56 LDR PC,Undefined_Addr ; Undefined instructions 57 LDR PC,SWI_Addr ; Software interrupt (SWI/SVC) 58 LDR PC,Prefetch_Addr ; Prefetch abort 59 LDR PC,Abort_Addr ; Data abort 60 DCD 0 ; RESERVED 61 LDR PC,IRQ_Addr ; IRQ 62 LDR PC,FIQ_Addr ; FIQ 63 64 DATA 65 66Reset_Addr: DCD __iar_program_start 67Undefined_Addr: DCD Undefined_Handler 68SWI_Addr: DCD SWI_Handler 69Prefetch_Addr: DCD Prefetch_Handler 70Abort_Addr: DCD Abort_Handler 71IRQ_Addr: DCD IRQ_Handler 72FIQ_Addr: DCD FIQ_Handler 73 74 75; -------------------------------------------------- 76; ?cstartup -- low-level system initialization code. 77; 78; After a reset execution starts here, the mode is ARM, supervisor 79; with interrupts disabled. 80; 81 82 SECTION .text:CODE:NOROOT(2) 83 84 EXTERN rt_hw_trap_udef 85 EXTERN rt_hw_trap_swi 86 EXTERN rt_hw_trap_pabt 87 EXTERN rt_hw_trap_dabt 88 EXTERN rt_hw_trap_fiq 89 EXTERN rt_hw_trap_irq 90 EXTERN rt_interrupt_enter 91 EXTERN rt_interrupt_leave 92 EXTERN rt_thread_switch_interrupt_flag 93 EXTERN rt_interrupt_from_thread 94 EXTERN rt_interrupt_to_thread 95 EXTERN rt_current_thread 96 EXTERN vmm_thread 97 EXTERN vmm_virq_check 98 99 EXTERN __cmain 100 REQUIRE __vector 101 EXTWEAK __iar_init_core 102 EXTWEAK __iar_init_vfp 103 104 105 ARM 106 107__iar_program_start: 108?cstartup: 109 110; 111; Add initialization needed before setup of stackpointers here. 112; 113 114; 115; Initialize the stack pointers. 116; The pattern below can be used for any of the exception stacks: 117; FIQ, IRQ, SVC, ABT, UND, SYS. 118; The USR mode uses the same stack as SYS. 119; The stack segments must be defined in the linker command file, 120; and be declared above. 121; 122 123 MRS r0, cpsr ; Original PSR value 124 125 ;; Set up the interrupt stack pointer. 126 BIC r0, r0, #MODE_MSK ; Clear the mode bits 127 ORR r0, r0, #IRQ_MODE ; Set IRQ mode bits 128 MSR cpsr_c, r0 ; Change the mode 129 LDR sp, =SFE(IRQ_STACK) ; End of IRQ_STACK 130 BIC sp,sp,#0x7 ; Make sure SP is 8 aligned 131 132 ;; Set up the fast interrupt stack pointer. 133 BIC r0, r0, #MODE_MSK ; Clear the mode bits 134 ORR r0, r0, #FIQ_MODE ; Set FIR mode bits 135 MSR cpsr_c, r0 ; Change the mode 136 LDR sp, =SFE(FIQ_STACK) ; End of FIQ_STACK 137 BIC sp,sp,#0x7 ; Make sure SP is 8 aligned 138 139 BIC r0,r0,#MODE_MSK ; Clear the mode bits 140 ORR r0,r0,#ABT_MODE ; Set Abort mode bits 141 MSR cpsr_c,r0 ; Change the mode 142 LDR sp,=SFE(ABT_STACK) ; End of ABT_STACK 143 BIC sp,sp,#0x7 ; Make sure SP is 8 aligned 144 145 BIC r0,r0,#MODE_MSK ; Clear the mode bits 146 ORR r0,r0,#UND_MODE ; Set Undefined mode bits 147 MSR cpsr_c,r0 ; Change the mode 148 LDR sp,=SFE(UND_STACK) ; End of UND_STACK 149 BIC sp,sp,#0x7 ; Make sure SP is 8 aligned 150 151 ;; Set up the normal stack pointer. 152 BIC r0 ,r0, #MODE_MSK ; Clear the mode bits 153 ORR r0 ,r0, #SVC_MODE ; Set System mode bits 154 MSR cpsr_c, r0 ; Change the mode 155 LDR sp, =SFE(SVC_STACK) ; End of SVC_STACK 156 BIC sp,sp,#0x7 ; Make sure SP is 8 aligned 157 158 ;; Turn on core features assumed to be enabled. 159 BL __iar_init_core 160 161 ;; Initialize VFP (if needed). 162 BL __iar_init_vfp 163 164 165 ;; Continue to __cmain for C-level initialization. 166 B __cmain 167 168 169Undefined_Handler: 170 SUB sp, sp, #72 171 STMIA sp, {r0 - r12} ;/* Calling r0-r12 */ 172 ADD r8, sp, #60 173 174 MRS r1, cpsr 175 MRS r2, spsr 176 ORR r2,r2, #I_Bit | F_Bit 177 MSR cpsr_c, r2 178 MOV r0, r0 179 STMDB r8, {sp, lr} ;/* Calling SP, LR */ 180 MSR cpsr_c, r1 ;/* return to Undefined Instruction mode */ 181 182 STR lr, [r8, #0] ;/* Save calling PC */ 183 MRS r6, spsr 184 STR r6, [r8, #4] ;/* Save CPSR */ 185 STR r0, [r8, #8] ;/* Save OLD_R0 */ 186 MOV r0, sp 187 188 BL rt_hw_trap_udef 189 190 LDMIA sp, {r0 - r12} ;/* Calling r0 - r2 */ 191 MOV r0, r0 192 LDR lr, [sp, #60] ;/* Get PC */ 193 ADD sp, sp, #72 194 MOVS pc, lr ;/* return & move spsr_svc into cpsr */ 195 196SWI_Handler: 197 BL rt_hw_trap_swi 198 199Prefetch_Handler: 200 BL rt_hw_trap_pabt 201 202Abort_Handler: 203 SUB sp, sp, #72 204 STMIA sp, {r0 - r12} ;/* Calling r0-r12 */ 205 ADD r8, sp, #60 206 STMDB r8, {sp, lr} ;/* Calling SP, LR */ 207 STR lr, [r8, #0] ;/* Save calling PC */ 208 MRS r6, spsr 209 STR r6, [r8, #4] ;/* Save CPSR */ 210 STR r0, [r8, #8] ;/* Save OLD_R0 */ 211 MOV r0, sp 212 213 BL rt_hw_trap_dabt 214 215 LDMIA sp, {r0 - r12} ;/* Calling r0 - r2 */ 216 MOV r0, r0 217 LDR lr, [sp, #60] ;/* Get PC */ 218 ADD sp, sp, #72 219 MOVS pc, lr ;/* return & move spsr_svc into cpsr */ 220 221FIQ_Handler: 222 STMFD sp!,{r0-r7,lr} 223 BL rt_hw_trap_fiq 224 LDMFD sp!,{r0-r7,lr} 225 SUBS pc,lr,#4 226 227IRQ_Handler: 228 STMFD sp!, {r0-r12,lr} 229 230 BL rt_interrupt_enter 231 BL rt_hw_trap_irq 232 BL rt_interrupt_leave 233 234 ; if rt_thread_switch_interrupt_flag set, jump to 235 ; rt_hw_context_switch_interrupt_do and don't return 236 LDR r0, =rt_thread_switch_interrupt_flag 237 LDR r1, [r0] 238 CMP r1, #1 239 BEQ rt_hw_context_switch_interrupt_do 240 241 LDMFD sp!, {r0-r12,lr} 242 SUBS pc, lr, #4 243 244rt_hw_context_switch_interrupt_do: 245 MOV r1, #0 ; clear flag 246 STR r1, [r0] 247 248 LDMFD sp!, {r0-r12,lr}; reload saved registers 249 STMFD sp, {r0-r2} ; save r0-r2 250 251 MRS r0, spsr ; get cpsr of interrupt thread 252 253 SUB r1, sp, #4*3 254 SUB r2, lr, #4 ; save old task's pc to r2 255 256 ; switch to SVC mode with no interrupt 257 MSR cpsr_c, #I_Bit | F_Bit | SVC_MODE 258 259 STMFD sp!, {r2} ; push old task's pc 260 STMFD sp!, {r3-r12,lr}; push old task's lr,r12-r4 261 LDMFD r1, {r1-r3} ; restore r0-r2 of the interrupt thread 262 STMFD sp!, {r1-r3} ; push old task's r0-r2 263 STMFD sp!, {r0} ; push old task's cpsr 264 265 LDR r4, =rt_interrupt_from_thread 266 LDR r5, [r4] 267 STR sp, [r5] ; store sp in preempted tasks's TCB 268 269 LDR r6, =rt_interrupt_to_thread 270 LDR r6, [r6] 271 LDR sp, [r6] ; get new task's stack pointer 272 273 LDMFD sp!, {r4} ; pop new task's cpsr to spsr 274 MSR spsr_cxsf, r4 275 276 LDMFD sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr 277 278 END 279