xref: /nrf52832-nimble/rt-thread/libcpu/arm/am335x/start_iar.s (revision 104654410c56c573564690304ae786df310c91fc)
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