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