xref: /nrf52832-nimble/rt-thread/libcpu/arm/arm926/start_gcc.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    .section .nobss, "w"
50*10465441SEvalZero
51*10465441SEvalZero    .space UND_STK_SIZE
52*10465441SEvalZero    .align 3
53*10465441SEvalZero    .global UND_STACK_START
54*10465441SEvalZeroUND_STACK_START:
55*10465441SEvalZero
56*10465441SEvalZero    .space ABT_STK_SIZE
57*10465441SEvalZero    .align 3
58*10465441SEvalZero    .global ABT_STACK_START
59*10465441SEvalZeroABT_STACK_START:
60*10465441SEvalZero
61*10465441SEvalZero    .space FIQ_STK_SIZE
62*10465441SEvalZero    .align 3
63*10465441SEvalZero    .global FIQ_STACK_START
64*10465441SEvalZeroFIQ_STACK_START:
65*10465441SEvalZero
66*10465441SEvalZero    .space IRQ_STK_SIZE
67*10465441SEvalZero    .align 3
68*10465441SEvalZero    .global IRQ_STACK_START
69*10465441SEvalZeroIRQ_STACK_START:
70*10465441SEvalZero
71*10465441SEvalZero    .skip SYS_STK_SIZE
72*10465441SEvalZero    .align 3
73*10465441SEvalZero    .global SYS_STACK_START
74*10465441SEvalZeroSYS_STACK_START:
75*10465441SEvalZero
76*10465441SEvalZero    .space SVC_STK_SIZE
77*10465441SEvalZero    .align 3
78*10465441SEvalZero    .global SVC_STACK_START
79*10465441SEvalZeroSVC_STACK_START:
80*10465441SEvalZero
81*10465441SEvalZero@;--------------Jump vector table-----------------------------------------------
82*10465441SEvalZero    .section .init, "ax"
83*10465441SEvalZero    .arm
84*10465441SEvalZero
85*10465441SEvalZero    .global start
86*10465441SEvalZerostart:
87*10465441SEvalZero    LDR     PC, vector_reset
88*10465441SEvalZero    LDR     PC, vector_undef
89*10465441SEvalZero    LDR     PC, vector_swi
90*10465441SEvalZero    LDR     PC, vector_pabt
91*10465441SEvalZero    LDR     PC, vector_dabt
92*10465441SEvalZero    LDR     PC, vector_resv
93*10465441SEvalZero    LDR     PC, vector_irq
94*10465441SEvalZero    LDR     PC, vector_fiq
95*10465441SEvalZero
96*10465441SEvalZerovector_reset:
97*10465441SEvalZero    .word  Reset_Handler
98*10465441SEvalZerovector_undef:
99*10465441SEvalZero    .word  Undef_Handler
100*10465441SEvalZerovector_swi:
101*10465441SEvalZero    .word  SWI_Handler
102*10465441SEvalZerovector_pabt:
103*10465441SEvalZero    .word  PAbt_Handler
104*10465441SEvalZerovector_dabt:
105*10465441SEvalZero    .word  DAbt_Handler
106*10465441SEvalZerovector_resv:
107*10465441SEvalZero    .word  Resv_Handler
108*10465441SEvalZerovector_irq:
109*10465441SEvalZero    .word  IRQ_Handler
110*10465441SEvalZerovector_fiq:
111*10465441SEvalZero    .word  FIQ_Handler
112*10465441SEvalZero
113*10465441SEvalZero    .balignl     16,0xdeadbeef
114*10465441SEvalZero
115*10465441SEvalZero@;----------------- Reset Handler ---------------------------------------------
116*10465441SEvalZero    .global rt_low_level_init
117*10465441SEvalZero    .global main
118*10465441SEvalZero    .global Reset_Handler
119*10465441SEvalZeroReset_Handler:
120*10465441SEvalZero    @; Set the cpu to SVC32 mode
121*10465441SEvalZero    MRS     R0, CPSR
122*10465441SEvalZero    BIC     R0, R0, #MODEMASK
123*10465441SEvalZero    ORR     R0, R0, #MODE_SVC|NOINT
124*10465441SEvalZero    MSR     CPSR_cxsf, R0
125*10465441SEvalZero
126*10465441SEvalZero    @; Set CO-Processor
127*10465441SEvalZero    @; little-end锛宒isbale I/D Cache MMU, vector table is 0x00000000
128*10465441SEvalZero    MRC     P15, 0, R0, C1, C0, 0   @; Read CP15
129*10465441SEvalZero    LDR     R1, =0x00003085         @; set clear bits
130*10465441SEvalZero    BIC     R0, R0, R1
131*10465441SEvalZero    MCR     P15, 0, R0, C1, C0, 0   @; Write CP15
132*10465441SEvalZero
133*10465441SEvalZero    @; Call low level init function,
134*10465441SEvalZero    @; disable and clear all IRQs, Init MMU, Init interrupt controller, etc.
135*10465441SEvalZero    LDR     SP, =SVC_STACK_START
136*10465441SEvalZero    LDR     R0, =rt_low_level_init
137*10465441SEvalZero    BLX     R0
138*10465441SEvalZero
139*10465441SEvalZeroSetup_Stack:
140*10465441SEvalZero    @; Setup Stack for each mode
141*10465441SEvalZero    MRS     R0, CPSR
142*10465441SEvalZero    BIC     R0, R0, #MODEMASK
143*10465441SEvalZero
144*10465441SEvalZero    ORR     R1, R0, #MODE_UND|NOINT
145*10465441SEvalZero    MSR     CPSR_cxsf, R1            @; Undef mode
146*10465441SEvalZero    LDR     SP, =UND_STACK_START
147*10465441SEvalZero
148*10465441SEvalZero    ORR     R1, R0, #MODE_ABT|NOINT
149*10465441SEvalZero    MSR     CPSR_cxsf, R1            @; Abort mode
150*10465441SEvalZero    LDR     SP, =ABT_STACK_START
151*10465441SEvalZero
152*10465441SEvalZero    ORR     R1, R0, #MODE_IRQ|NOINT
153*10465441SEvalZero    MSR     CPSR_cxsf, R1            @; IRQ mode
154*10465441SEvalZero    LDR     SP, =IRQ_STACK_START
155*10465441SEvalZero
156*10465441SEvalZero    ORR     R1, R0, #MODE_FIQ|NOINT
157*10465441SEvalZero    MSR     CPSR_cxsf, R1            @; FIQ mode
158*10465441SEvalZero    LDR     SP, =FIQ_STACK_START
159*10465441SEvalZero
160*10465441SEvalZero    ORR     R1, R0, #MODE_SYS|NOINT
161*10465441SEvalZero    MSR     CPSR_cxsf,R1             @; SYS/User mode
162*10465441SEvalZero    LDR     SP, =SYS_STACK_START
163*10465441SEvalZero
164*10465441SEvalZero    ORR     R1, R0, #MODE_SVC|NOINT
165*10465441SEvalZero    MSR     CPSR_cxsf, R1            @; SVC mode
166*10465441SEvalZero    LDR     SP, =SVC_STACK_START
167*10465441SEvalZero
168*10465441SEvalZero    @; clear .bss
169*10465441SEvalZero    MOV     R0, #0                   @; get a zero
170*10465441SEvalZero    LDR     R1, =__bss_start__       @; bss start
171*10465441SEvalZero    LDR     R2, =__bss_end__         @; bss end
172*10465441SEvalZero
173*10465441SEvalZerobss_clear_loop:
174*10465441SEvalZero    CMP     R1, R2                   @; check if data to clear
175*10465441SEvalZero    STRLO   R0, [R1], #4             @; clear 4 bytes
176*10465441SEvalZero    BLO     bss_clear_loop           @; loop until done
177*10465441SEvalZero
178*10465441SEvalZero    @; call C++ constructors of global objects
179*10465441SEvalZero    LDR     R0, =__ctors_start__
180*10465441SEvalZero    LDR     R1, =__ctors_end__
181*10465441SEvalZero
182*10465441SEvalZeroctor_loop:
183*10465441SEvalZero    CMP     R0, R1
184*10465441SEvalZero    BEQ     ctor_end
185*10465441SEvalZero    LDR     R2, [R0], #4
186*10465441SEvalZero    STMFD   SP!, {R0-R1}
187*10465441SEvalZero    MOV     LR, PC
188*10465441SEvalZero    BX      R2
189*10465441SEvalZero    LDMFD   SP!, {R0-R1}
190*10465441SEvalZero    B       ctor_loop
191*10465441SEvalZeroctor_end:
192*10465441SEvalZero
193*10465441SEvalZero    @; Enter the C code
194*10465441SEvalZero    LDR     R0, =rtthread_startup
195*10465441SEvalZero    BLX     R0
196*10465441SEvalZero
197*10465441SEvalZero@;----------------- Exception Handler -----------------------------------------
198*10465441SEvalZero    .global rt_hw_trap_udef
199*10465441SEvalZero    .global rt_hw_trap_swi
200*10465441SEvalZero    .global rt_hw_trap_pabt
201*10465441SEvalZero    .global rt_hw_trap_dabt
202*10465441SEvalZero    .global rt_hw_trap_resv
203*10465441SEvalZero    .global rt_hw_trap_irq
204*10465441SEvalZero    .global rt_hw_trap_fiq
205*10465441SEvalZero
206*10465441SEvalZero    .global rt_interrupt_enter
207*10465441SEvalZero    .global rt_interrupt_leave
208*10465441SEvalZero    .global rt_thread_switch_interrupt_flag
209*10465441SEvalZero    .global rt_interrupt_from_thread
210*10465441SEvalZero    .global rt_interrupt_to_thread
211*10465441SEvalZero
212*10465441SEvalZero    .align  5
213*10465441SEvalZeroUndef_Handler:
214*10465441SEvalZero    SUB     SP, SP, #S_FRAME_SIZE
215*10465441SEvalZero    STMIA   SP, {R0 - R12}          @; Calling R0-R12
216*10465441SEvalZero    ADD     R8, SP, #S_PC
217*10465441SEvalZero    STMDB   R8, {SP, LR}            @; Calling SP, LR
218*10465441SEvalZero    STR     LR, [R8, #0]            @; Save calling PC
219*10465441SEvalZero    MRS     R6, SPSR
220*10465441SEvalZero    STR     R6, [R8, #4]            @; Save CPSR
221*10465441SEvalZero    STR     R0, [R8, #8]            @; Save SPSR
222*10465441SEvalZero    MOV     R0, SP
223*10465441SEvalZero    BL      rt_hw_trap_udef
224*10465441SEvalZero
225*10465441SEvalZero    .align  5
226*10465441SEvalZeroSWI_Handler:
227*10465441SEvalZero    BL      rt_hw_trap_swi
228*10465441SEvalZero
229*10465441SEvalZero    .align  5
230*10465441SEvalZeroPAbt_Handler:
231*10465441SEvalZero    BL      rt_hw_trap_pabt
232*10465441SEvalZero
233*10465441SEvalZero    .align  5
234*10465441SEvalZeroDAbt_Handler:
235*10465441SEvalZero    SUB     SP, SP, #S_FRAME_SIZE
236*10465441SEvalZero    STMIA   SP, {R0 - R12}          @; Calling R0-R12
237*10465441SEvalZero    ADD     R8, SP, #S_PC
238*10465441SEvalZero    STMDB   R8, {SP, LR}            @; Calling SP, LR
239*10465441SEvalZero    STR     LR, [R8, #0]            @; Save calling PC
240*10465441SEvalZero    MRS     R6, SPSR
241*10465441SEvalZero    STR     R6, [R8, #4]            @; Save CPSR
242*10465441SEvalZero    STR     R0, [R8, #8]            @; Save SPSR
243*10465441SEvalZero    MOV     R0, SP
244*10465441SEvalZero    BL      rt_hw_trap_dabt
245*10465441SEvalZero
246*10465441SEvalZero    .align  5
247*10465441SEvalZeroResv_Handler:
248*10465441SEvalZero    BL      rt_hw_trap_resv
249*10465441SEvalZero
250*10465441SEvalZero    .align  5
251*10465441SEvalZeroFIQ_Handler:
252*10465441SEvalZero    STMFD   SP!, {R0-R7,LR}
253*10465441SEvalZero    BL      rt_hw_trap_fiq
254*10465441SEvalZero    LDMFD   SP!, {R0-R7,LR}
255*10465441SEvalZero    SUBS    PC, LR, #4
256*10465441SEvalZero
257*10465441SEvalZero    .align  5
258*10465441SEvalZeroIRQ_Handler:
259*10465441SEvalZero    STMFD   SP!, {R0-R12,LR}
260*10465441SEvalZero    BL      rt_interrupt_enter
261*10465441SEvalZero    BL      rt_hw_trap_irq
262*10465441SEvalZero    BL      rt_interrupt_leave
263*10465441SEvalZero
264*10465441SEvalZero    @; If rt_thread_switch_interrupt_flag set,
265*10465441SEvalZero    @; jump to rt_hw_context_switch_interrupt_do and don't return
266*10465441SEvalZero    LDR     R0, =rt_thread_switch_interrupt_flag
267*10465441SEvalZero    LDR     R1, [R0]
268*10465441SEvalZero    CMP     R1, #1
269*10465441SEvalZero    BEQ     rt_hw_context_switch_interrupt_do
270*10465441SEvalZero
271*10465441SEvalZero    LDMFD   SP!, {R0-R12,LR}
272*10465441SEvalZero    SUBS    PC, LR, #4
273*10465441SEvalZero
274*10465441SEvalZero@;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
275*10465441SEvalZerort_hw_context_switch_interrupt_do:
276*10465441SEvalZero    MOV     R1,  #0                 @; Clear flag
277*10465441SEvalZero    STR     R1,  [R0]               @; Save to flag variable
278*10465441SEvalZero
279*10465441SEvalZero    LDMFD   SP!, {R0-R12,LR}        @; Reload saved registers
280*10465441SEvalZero    STMFD   SP, {R0-R2}             @; Save R0-R2
281*10465441SEvalZero    SUB     R1,  SP, #4*3           @; Save old task's SP to R1
282*10465441SEvalZero    SUB     R2,  LR, #4             @; Save old task's PC to R2
283*10465441SEvalZero
284*10465441SEvalZero    MRS     R0,  SPSR               @; Get CPSR of interrupt thread
285*10465441SEvalZero
286*10465441SEvalZero    MSR     CPSR_c, #MODE_SVC|NOINT @; Switch to SVC mode and no interrupt
287*10465441SEvalZero
288*10465441SEvalZero    STMFD   SP!, {R2}               @; Push old task's PC
289*10465441SEvalZero    STMFD   SP!, {R3-R12,LR}        @; Push old task's LR,R12-R3
290*10465441SEvalZero    LDMFD   R1, {R1-R3}
291*10465441SEvalZero    STMFD   SP!, {R1-R3}            @; Push old task's R2-R0
292*10465441SEvalZero    STMFD   SP!, {R0}               @; Push old task's CPSR
293*10465441SEvalZero
294*10465441SEvalZero    LDR     R4,  =rt_interrupt_from_thread
295*10465441SEvalZero    LDR     R5,  [R4]               @; R5 = stack ptr in old tasks's TCB
296*10465441SEvalZero    STR     SP,  [R5]               @; Store SP in preempted tasks's TCB
297*10465441SEvalZero
298*10465441SEvalZero    LDR     R6,  =rt_interrupt_to_thread
299*10465441SEvalZero    LDR     R6,  [R6]               @; R6 = stack ptr in new tasks's TCB
300*10465441SEvalZero    LDR     SP,  [R6]               @; Get new task's stack pointer
301*10465441SEvalZero
302*10465441SEvalZero    LDMFD   SP!, {R4}               @; Pop new task's SPSR
303*10465441SEvalZero    MSR     SPSR_cxsf, R4
304*10465441SEvalZero
305*10465441SEvalZero    LDMFD   SP!, {R0-R12,LR,PC}^    @; pop new task's R0-R12,LR & PC SPSR 2 CPSR
306