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