xref: /nrf52832-nimble/rt-thread/libcpu/arm/arm926/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; * 2011-01-13     weety      first version
9*10465441SEvalZero; * 2015-04-15     ArdaFu     Split from AT91SAM9260 BSP
10*10465441SEvalZero; * 2015-04-21     ArdaFu     Remove remap code. Using mmu to map vector table
11*10465441SEvalZero; * 2015-06-04     aozima     Align stack address to 8 byte.
12*10465441SEvalZero; */
13*10465441SEvalZero
14*10465441SEvalZero#include "rt_low_level_init.h"
15*10465441SEvalZero
16*10465441SEvalZero#define S_FRAME_SIZE    (18*4)   ;72
17*10465441SEvalZero
18*10465441SEvalZero;#define S_SPSR          (17*4)   ;SPSR
19*10465441SEvalZero;#define S_CPSR          (16*4)   ;CPSR
20*10465441SEvalZero#define S_PC            (15*4)   ;R15
21*10465441SEvalZero;#define S_LR            (14*4)   ;R14
22*10465441SEvalZero;#define S_SP            (13*4)   ;R13
23*10465441SEvalZero
24*10465441SEvalZero;#define S_IP            (12*4)   ;R12
25*10465441SEvalZero;#define S_FP            (11*4)   ;R11
26*10465441SEvalZero;#define S_R10           (10*4)
27*10465441SEvalZero;#define S_R9            (9*4)
28*10465441SEvalZero;#define S_R8            (8*4)
29*10465441SEvalZero;#define S_R7            (7*4)
30*10465441SEvalZero;#define S_R6            (6*4)
31*10465441SEvalZero;#define S_R5            (5*4)
32*10465441SEvalZero;#define S_R4            (4*4)
33*10465441SEvalZero;#define S_R3            (3*4)
34*10465441SEvalZero;#define S_R2            (2*4)
35*10465441SEvalZero;#define S_R1            (1*4)
36*10465441SEvalZero;#define S_R0            (0*4)
37*10465441SEvalZero
38*10465441SEvalZero#define MODE_SYS        0x1F
39*10465441SEvalZero#define MODE_FIQ        0x11
40*10465441SEvalZero#define MODE_IRQ        0x12
41*10465441SEvalZero#define MODE_SVC        0x13
42*10465441SEvalZero#define MODE_ABT        0x17
43*10465441SEvalZero#define MODE_UND        0x1B
44*10465441SEvalZero#define MODEMASK        0x1F
45*10465441SEvalZero
46*10465441SEvalZero#define NOINT           0xC0
47*10465441SEvalZero
48*10465441SEvalZero;----------------------- Stack and Heap Definitions ----------------------------
49*10465441SEvalZero    MODULE ?cstartup
50*10465441SEvalZero    SECTION .noinit:DATA:NOROOT(3)
51*10465441SEvalZero    DATA
52*10465441SEvalZero
53*10465441SEvalZero    ALIGNRAM 3
54*10465441SEvalZero    DS8 UND_STK_SIZE
55*10465441SEvalZero    PUBLIC UND_STACK_START
56*10465441SEvalZeroUND_STACK_START:
57*10465441SEvalZero
58*10465441SEvalZero    ALIGNRAM 3
59*10465441SEvalZero    DS8 ABT_STK_SIZE
60*10465441SEvalZero    PUBLIC ABT_STACK_START
61*10465441SEvalZeroABT_STACK_START:
62*10465441SEvalZero
63*10465441SEvalZero    ALIGNRAM 3
64*10465441SEvalZero    DS8 FIQ_STK_SIZE
65*10465441SEvalZero    PUBLIC FIQ_STACK_START
66*10465441SEvalZeroFIQ_STACK_START:
67*10465441SEvalZero
68*10465441SEvalZero    ALIGNRAM 3
69*10465441SEvalZero    DS8 IRQ_STK_SIZE
70*10465441SEvalZero    PUBLIC IRQ_STACK_START
71*10465441SEvalZeroIRQ_STACK_START:
72*10465441SEvalZero
73*10465441SEvalZero    ALIGNRAM 3
74*10465441SEvalZero    DS8 SYS_STK_SIZE
75*10465441SEvalZero    PUBLIC SYS_STACK_START
76*10465441SEvalZeroSYS_STACK_START:
77*10465441SEvalZero
78*10465441SEvalZero    ALIGNRAM 3
79*10465441SEvalZero    DS8 SVC_STK_SIZE
80*10465441SEvalZero    PUBLIC SVC_STACK_START
81*10465441SEvalZeroSVC_STACK_START:
82*10465441SEvalZero
83*10465441SEvalZero;--------------Jump vector table------------------------------------------------
84*10465441SEvalZero    SECTION .intvec:CODE:ROOT(2)
85*10465441SEvalZero    ARM
86*10465441SEvalZero    PUBLIC Entry_Point
87*10465441SEvalZeroEntry_Point:
88*10465441SEvalZero__iar_init$$done:               ; The interrupt vector is not needed
89*10465441SEvalZero                                ; until after copy initialization is done
90*10465441SEvalZero    LDR     PC, vector_reset
91*10465441SEvalZero    LDR     PC, vector_undef
92*10465441SEvalZero    LDR     PC, vector_swi
93*10465441SEvalZero    LDR     PC, vector_pabt
94*10465441SEvalZero    LDR     PC, vector_dabt
95*10465441SEvalZero    LDR     PC, vector_resv
96*10465441SEvalZero    LDR     PC, vector_irq
97*10465441SEvalZero    LDR     PC, vector_fiq
98*10465441SEvalZero
99*10465441SEvalZerovector_reset:
100*10465441SEvalZero    DC32 Reset_Handler
101*10465441SEvalZerovector_undef:
102*10465441SEvalZero    DC32 Undef_Handler
103*10465441SEvalZerovector_swi:
104*10465441SEvalZero    DC32 SWI_Handler
105*10465441SEvalZerovector_pabt:
106*10465441SEvalZero    DC32 PAbt_Handler
107*10465441SEvalZerovector_dabt:
108*10465441SEvalZero    DC32 DAbt_Handler
109*10465441SEvalZerovector_resv:
110*10465441SEvalZero    DC32 Resv_Handler
111*10465441SEvalZerovector_irq:
112*10465441SEvalZero    DC32 IRQ_Handler
113*10465441SEvalZerovector_fiq:
114*10465441SEvalZero    DC32 FIQ_Handler
115*10465441SEvalZero
116*10465441SEvalZero;----------------- Reset Handler -----------------------------------------------
117*10465441SEvalZero    EXTERN rt_low_level_init
118*10465441SEvalZero    EXTERN ?main
119*10465441SEvalZero    PUBLIC __iar_program_start
120*10465441SEvalZero__iar_program_start:
121*10465441SEvalZeroReset_Handler:
122*10465441SEvalZero    ; Set the cpu to SVC32 mode
123*10465441SEvalZero    MRS     R0, CPSR
124*10465441SEvalZero    BIC     R0, R0, #MODEMASK
125*10465441SEvalZero    ORR     R0, R0, #MODE_SVC|NOINT
126*10465441SEvalZero    MSR     CPSR_cxsf, R0
127*10465441SEvalZero
128*10465441SEvalZero    ; Set CO-Processor
129*10465441SEvalZero    ; little-enddisbale I/D Cache MMU, vector table is 0x00000000
130*10465441SEvalZero    MRC     P15, 0, R0, C1, C0, 0   ; Read CP15
131*10465441SEvalZero    LDR     R1, =0x00003085         ; set clear bits
132*10465441SEvalZero    BIC     R0, R0, R1
133*10465441SEvalZero    MCR     P15, 0, R0, C1, C0, 0   ; Write CP15
134*10465441SEvalZero
135*10465441SEvalZero    ; Call low level init function,
136*10465441SEvalZero    ; disable and clear all IRQs, Init MMU, Init interrupt controller, etc.
137*10465441SEvalZero    LDR     SP, =SVC_STACK_START
138*10465441SEvalZero    LDR     R0, =rt_low_level_init
139*10465441SEvalZero    BLX     R0
140*10465441SEvalZero
141*10465441SEvalZeroSetup_Stack:
142*10465441SEvalZero    ; Setup Stack for each mode
143*10465441SEvalZero    MRS     R0, CPSR
144*10465441SEvalZero    BIC     R0, R0, #MODEMASK
145*10465441SEvalZero
146*10465441SEvalZero    ORR     R1, R0, #MODE_UND|NOINT
147*10465441SEvalZero    MSR     CPSR_cxsf, R1            ; Undef mode
148*10465441SEvalZero    LDR     SP, =UND_STACK_START
149*10465441SEvalZero
150*10465441SEvalZero    ORR     R1,R0,#MODE_ABT|NOINT
151*10465441SEvalZero    MSR     CPSR_cxsf,R1             ; Abort mode
152*10465441SEvalZero    LDR     SP, =ABT_STACK_START
153*10465441SEvalZero
154*10465441SEvalZero    ORR     R1,R0,#MODE_IRQ|NOINT
155*10465441SEvalZero    MSR     CPSR_cxsf,R1             ; IRQ mode
156*10465441SEvalZero    LDR     SP, =IRQ_STACK_START
157*10465441SEvalZero
158*10465441SEvalZero    ORR     R1,R0,#MODE_FIQ|NOINT
159*10465441SEvalZero    MSR     CPSR_cxsf,R1             ; FIQ mode
160*10465441SEvalZero    LDR     SP, =FIQ_STACK_START
161*10465441SEvalZero
162*10465441SEvalZero    ORR     R1,R0,#MODE_SYS|NOINT
163*10465441SEvalZero    MSR     CPSR_cxsf,R1             ; SYS/User mode
164*10465441SEvalZero    LDR     SP, =SYS_STACK_START
165*10465441SEvalZero
166*10465441SEvalZero    ORR     R1,R0,#MODE_SVC|NOINT
167*10465441SEvalZero    MSR     CPSR_cxsf,R1             ; SVC mode
168*10465441SEvalZero    LDR     SP, =SVC_STACK_START
169*10465441SEvalZero
170*10465441SEvalZero    ; Enter the C code
171*10465441SEvalZero    LDR     R0, =?main
172*10465441SEvalZero    BLX     R0
173*10465441SEvalZero
174*10465441SEvalZero;----------------- Exception Handler -------------------------------------------
175*10465441SEvalZero    IMPORT rt_hw_trap_udef
176*10465441SEvalZero    IMPORT rt_hw_trap_swi
177*10465441SEvalZero    IMPORT rt_hw_trap_pabt
178*10465441SEvalZero    IMPORT rt_hw_trap_dabt
179*10465441SEvalZero    IMPORT rt_hw_trap_resv
180*10465441SEvalZero    IMPORT rt_hw_trap_irq
181*10465441SEvalZero    IMPORT rt_hw_trap_fiq
182*10465441SEvalZero
183*10465441SEvalZero    IMPORT rt_interrupt_enter
184*10465441SEvalZero    IMPORT rt_interrupt_leave
185*10465441SEvalZero    IMPORT rt_thread_switch_interrupt_flag
186*10465441SEvalZero    IMPORT rt_interrupt_from_thread
187*10465441SEvalZero    IMPORT rt_interrupt_to_thread
188*10465441SEvalZero
189*10465441SEvalZero    SECTION .text:CODE:ROOT(2)
190*10465441SEvalZero    ARM
191*10465441SEvalZeroUndef_Handler:
192*10465441SEvalZero    SUB     SP, SP, #S_FRAME_SIZE
193*10465441SEvalZero    STMIA   SP, {R0 - R12}          ; Calling R0-R12
194*10465441SEvalZero    ADD     R8, SP, #S_PC
195*10465441SEvalZero    STMDB   R8, {SP, LR}            ; Calling SP, LR
196*10465441SEvalZero    STR     LR, [R8, #0]            ; Save calling PC
197*10465441SEvalZero    MRS     R6, SPSR
198*10465441SEvalZero    STR     R6, [R8, #4]            ; Save CPSR
199*10465441SEvalZero    STR     R0, [R8, #8]            ; Save SPSR
200*10465441SEvalZero    MOV     R0, SP
201*10465441SEvalZero    BL      rt_hw_trap_udef
202*10465441SEvalZero
203*10465441SEvalZeroSWI_Handler:
204*10465441SEvalZero    BL      rt_hw_trap_swi
205*10465441SEvalZero
206*10465441SEvalZeroPAbt_Handler:
207*10465441SEvalZero    BL      rt_hw_trap_pabt
208*10465441SEvalZero
209*10465441SEvalZeroDAbt_Handler:
210*10465441SEvalZero    SUB     SP, SP, #S_FRAME_SIZE
211*10465441SEvalZero    STMIA   SP, {R0 - R12}          ; Calling R0-R12
212*10465441SEvalZero    ADD     R8, SP, #S_PC
213*10465441SEvalZero    STMDB   R8, {SP, LR}            ; Calling SP, LR
214*10465441SEvalZero    STR     LR, [R8, #0]            ; Save calling PC
215*10465441SEvalZero    MRS     R6, SPSR
216*10465441SEvalZero    STR     R6, [R8, #4]            ; Save CPSR
217*10465441SEvalZero    STR     R0, [R8, #8]            ; Save SPSR
218*10465441SEvalZero    MOV     R0, SP
219*10465441SEvalZero    BL      rt_hw_trap_dabt
220*10465441SEvalZero
221*10465441SEvalZeroResv_Handler:
222*10465441SEvalZero    BL      rt_hw_trap_resv
223*10465441SEvalZero
224*10465441SEvalZeroIRQ_Handler:
225*10465441SEvalZero    STMFD   SP!, {R0-R12,LR}
226*10465441SEvalZero    BL      rt_interrupt_enter
227*10465441SEvalZero    BL      rt_hw_trap_irq
228*10465441SEvalZero    BL      rt_interrupt_leave
229*10465441SEvalZero
230*10465441SEvalZero    ; If rt_thread_switch_interrupt_flag set,
231*10465441SEvalZero    ; jump to rt_hw_context_switch_interrupt_do and don't return
232*10465441SEvalZero    LDR     R0, =rt_thread_switch_interrupt_flag
233*10465441SEvalZero    LDR     R1, [R0]
234*10465441SEvalZero    CMP     R1, #1
235*10465441SEvalZero    BEQ     rt_hw_context_switch_interrupt_do
236*10465441SEvalZero
237*10465441SEvalZero    LDMFD   SP!, {R0-R12,LR}
238*10465441SEvalZero    SUBS    PC, LR, #4
239*10465441SEvalZero
240*10465441SEvalZeroFIQ_Handler:
241*10465441SEvalZero    STMFD   SP!, {R0-R7,LR}
242*10465441SEvalZero    BL      rt_hw_trap_fiq
243*10465441SEvalZero    LDMFD   SP!, {R0-R7,LR}
244*10465441SEvalZero    SUBS    PC, LR, #4
245*10465441SEvalZero
246*10465441SEvalZero;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
247*10465441SEvalZerort_hw_context_switch_interrupt_do:
248*10465441SEvalZero    MOV     R1,  #0                 ; Clear flag
249*10465441SEvalZero    STR     R1,  [R0]               ; Save to flag variable
250*10465441SEvalZero
251*10465441SEvalZero    LDMFD   SP!, {R0-R12,LR}        ; Reload saved registers
252*10465441SEvalZero    STMFD   SP, {R0-R2}             ; Save R0-R2
253*10465441SEvalZero    SUB     R1,  SP, #4*3           ; Save old task's SP to R1
254*10465441SEvalZero    SUB     R2,  LR, #4             ; Save old task's PC to R2
255*10465441SEvalZero
256*10465441SEvalZero    MRS     R0,  SPSR               ; Get CPSR of interrupt thread
257*10465441SEvalZero
258*10465441SEvalZero    MSR     CPSR_c, #MODE_SVC|NOINT ; Switch to SVC mode and no interrupt
259*10465441SEvalZero
260*10465441SEvalZero    STMFD   SP!, {R2}               ; Push old task's PC
261*10465441SEvalZero    STMFD   SP!, {R3-R12,LR}        ; Push old task's LR,R12-R3
262*10465441SEvalZero    LDMFD   R1, {R1-R3}
263*10465441SEvalZero    STMFD   SP!, {R1-R3}            ; Push old task's R2-R0
264*10465441SEvalZero    STMFD   SP!, {R0}               ; Push old task's CPSR
265*10465441SEvalZero
266*10465441SEvalZero    LDR     R4,  =rt_interrupt_from_thread
267*10465441SEvalZero    LDR     R5,  [R4]               ; R5 = stack ptr in old tasks's TCB
268*10465441SEvalZero    STR     SP,  [R5]               ; Store SP in preempted tasks's TCB
269*10465441SEvalZero
270*10465441SEvalZero    LDR     R6,  =rt_interrupt_to_thread
271*10465441SEvalZero    LDR     R6,  [R6]               ; R6 = stack ptr in new tasks's TCB
272*10465441SEvalZero    LDR     SP,  [R6]               ; Get new task's stack pointer
273*10465441SEvalZero
274*10465441SEvalZero    LDMFD   SP!, {R4}               ; Pop new task's SPSR
275*10465441SEvalZero    MSR     SPSR_cxsf, R4
276*10465441SEvalZero
277*10465441SEvalZero    LDMFD   SP!, {R0-R12,LR,PC}^    ; pop new task's R0-R12,LR & PC SPSR to CPSR
278*10465441SEvalZero    END
279