xref: /nrf52832-nimble/rt-thread/libcpu/arm/arm926/start_iar.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    MODULE ?cstartup
50    SECTION .noinit:DATA:NOROOT(3)
51    DATA
52
53    ALIGNRAM 3
54    DS8 UND_STK_SIZE
55    PUBLIC UND_STACK_START
56UND_STACK_START:
57
58    ALIGNRAM 3
59    DS8 ABT_STK_SIZE
60    PUBLIC ABT_STACK_START
61ABT_STACK_START:
62
63    ALIGNRAM 3
64    DS8 FIQ_STK_SIZE
65    PUBLIC FIQ_STACK_START
66FIQ_STACK_START:
67
68    ALIGNRAM 3
69    DS8 IRQ_STK_SIZE
70    PUBLIC IRQ_STACK_START
71IRQ_STACK_START:
72
73    ALIGNRAM 3
74    DS8 SYS_STK_SIZE
75    PUBLIC SYS_STACK_START
76SYS_STACK_START:
77
78    ALIGNRAM 3
79    DS8 SVC_STK_SIZE
80    PUBLIC SVC_STACK_START
81SVC_STACK_START:
82
83;--------------Jump vector table------------------------------------------------
84    SECTION .intvec:CODE:ROOT(2)
85    ARM
86    PUBLIC Entry_Point
87Entry_Point:
88__iar_init$$done:               ; The interrupt vector is not needed
89                                ; until after copy initialization is done
90    LDR     PC, vector_reset
91    LDR     PC, vector_undef
92    LDR     PC, vector_swi
93    LDR     PC, vector_pabt
94    LDR     PC, vector_dabt
95    LDR     PC, vector_resv
96    LDR     PC, vector_irq
97    LDR     PC, vector_fiq
98
99vector_reset:
100    DC32 Reset_Handler
101vector_undef:
102    DC32 Undef_Handler
103vector_swi:
104    DC32 SWI_Handler
105vector_pabt:
106    DC32 PAbt_Handler
107vector_dabt:
108    DC32 DAbt_Handler
109vector_resv:
110    DC32 Resv_Handler
111vector_irq:
112    DC32 IRQ_Handler
113vector_fiq:
114    DC32 FIQ_Handler
115
116;----------------- Reset Handler -----------------------------------------------
117    EXTERN rt_low_level_init
118    EXTERN ?main
119    PUBLIC __iar_program_start
120__iar_program_start:
121Reset_Handler:
122    ; Set the cpu to SVC32 mode
123    MRS     R0, CPSR
124    BIC     R0, R0, #MODEMASK
125    ORR     R0, R0, #MODE_SVC|NOINT
126    MSR     CPSR_cxsf, R0
127
128    ; Set CO-Processor
129    ; little-enddisbale I/D Cache MMU, vector table is 0x00000000
130    MRC     P15, 0, R0, C1, C0, 0   ; Read CP15
131    LDR     R1, =0x00003085         ; set clear bits
132    BIC     R0, R0, R1
133    MCR     P15, 0, R0, C1, C0, 0   ; Write CP15
134
135    ; Call low level init function,
136    ; disable and clear all IRQs, Init MMU, Init interrupt controller, etc.
137    LDR     SP, =SVC_STACK_START
138    LDR     R0, =rt_low_level_init
139    BLX     R0
140
141Setup_Stack:
142    ; Setup Stack for each mode
143    MRS     R0, CPSR
144    BIC     R0, R0, #MODEMASK
145
146    ORR     R1, R0, #MODE_UND|NOINT
147    MSR     CPSR_cxsf, R1            ; Undef mode
148    LDR     SP, =UND_STACK_START
149
150    ORR     R1,R0,#MODE_ABT|NOINT
151    MSR     CPSR_cxsf,R1             ; Abort mode
152    LDR     SP, =ABT_STACK_START
153
154    ORR     R1,R0,#MODE_IRQ|NOINT
155    MSR     CPSR_cxsf,R1             ; IRQ mode
156    LDR     SP, =IRQ_STACK_START
157
158    ORR     R1,R0,#MODE_FIQ|NOINT
159    MSR     CPSR_cxsf,R1             ; FIQ mode
160    LDR     SP, =FIQ_STACK_START
161
162    ORR     R1,R0,#MODE_SYS|NOINT
163    MSR     CPSR_cxsf,R1             ; SYS/User mode
164    LDR     SP, =SYS_STACK_START
165
166    ORR     R1,R0,#MODE_SVC|NOINT
167    MSR     CPSR_cxsf,R1             ; SVC mode
168    LDR     SP, =SVC_STACK_START
169
170    ; Enter the C code
171    LDR     R0, =?main
172    BLX     R0
173
174;----------------- Exception Handler -------------------------------------------
175    IMPORT rt_hw_trap_udef
176    IMPORT rt_hw_trap_swi
177    IMPORT rt_hw_trap_pabt
178    IMPORT rt_hw_trap_dabt
179    IMPORT rt_hw_trap_resv
180    IMPORT rt_hw_trap_irq
181    IMPORT rt_hw_trap_fiq
182
183    IMPORT rt_interrupt_enter
184    IMPORT rt_interrupt_leave
185    IMPORT rt_thread_switch_interrupt_flag
186    IMPORT rt_interrupt_from_thread
187    IMPORT rt_interrupt_to_thread
188
189    SECTION .text:CODE:ROOT(2)
190    ARM
191Undef_Handler:
192    SUB     SP, SP, #S_FRAME_SIZE
193    STMIA   SP, {R0 - R12}          ; Calling R0-R12
194    ADD     R8, SP, #S_PC
195    STMDB   R8, {SP, LR}            ; Calling SP, LR
196    STR     LR, [R8, #0]            ; Save calling PC
197    MRS     R6, SPSR
198    STR     R6, [R8, #4]            ; Save CPSR
199    STR     R0, [R8, #8]            ; Save SPSR
200    MOV     R0, SP
201    BL      rt_hw_trap_udef
202
203SWI_Handler:
204    BL      rt_hw_trap_swi
205
206PAbt_Handler:
207    BL      rt_hw_trap_pabt
208
209DAbt_Handler:
210    SUB     SP, SP, #S_FRAME_SIZE
211    STMIA   SP, {R0 - R12}          ; Calling R0-R12
212    ADD     R8, SP, #S_PC
213    STMDB   R8, {SP, LR}            ; Calling SP, LR
214    STR     LR, [R8, #0]            ; Save calling PC
215    MRS     R6, SPSR
216    STR     R6, [R8, #4]            ; Save CPSR
217    STR     R0, [R8, #8]            ; Save SPSR
218    MOV     R0, SP
219    BL      rt_hw_trap_dabt
220
221Resv_Handler:
222    BL      rt_hw_trap_resv
223
224IRQ_Handler:
225    STMFD   SP!, {R0-R12,LR}
226    BL      rt_interrupt_enter
227    BL      rt_hw_trap_irq
228    BL      rt_interrupt_leave
229
230    ; If rt_thread_switch_interrupt_flag set,
231    ; jump to rt_hw_context_switch_interrupt_do and don't return
232    LDR     R0, =rt_thread_switch_interrupt_flag
233    LDR     R1, [R0]
234    CMP     R1, #1
235    BEQ     rt_hw_context_switch_interrupt_do
236
237    LDMFD   SP!, {R0-R12,LR}
238    SUBS    PC, LR, #4
239
240FIQ_Handler:
241    STMFD   SP!, {R0-R7,LR}
242    BL      rt_hw_trap_fiq
243    LDMFD   SP!, {R0-R7,LR}
244    SUBS    PC, LR, #4
245
246;------ void rt_hw_context_switch_interrupt_do(rt_base_t flag) -----------------
247rt_hw_context_switch_interrupt_do:
248    MOV     R1,  #0                 ; Clear flag
249    STR     R1,  [R0]               ; Save to flag variable
250
251    LDMFD   SP!, {R0-R12,LR}        ; Reload saved registers
252    STMFD   SP, {R0-R2}             ; Save R0-R2
253    SUB     R1,  SP, #4*3           ; Save old task's SP to R1
254    SUB     R2,  LR, #4             ; Save old task's PC to R2
255
256    MRS     R0,  SPSR               ; Get CPSR of interrupt thread
257
258    MSR     CPSR_c, #MODE_SVC|NOINT ; Switch to SVC mode and no interrupt
259
260    STMFD   SP!, {R2}               ; Push old task's PC
261    STMFD   SP!, {R3-R12,LR}        ; Push old task's LR,R12-R3
262    LDMFD   R1, {R1-R3}
263    STMFD   SP!, {R1-R3}            ; Push old task's R2-R0
264    STMFD   SP!, {R0}               ; Push old task's CPSR
265
266    LDR     R4,  =rt_interrupt_from_thread
267    LDR     R5,  [R4]               ; R5 = stack ptr in old tasks's TCB
268    STR     SP,  [R5]               ; Store SP in preempted tasks's TCB
269
270    LDR     R6,  =rt_interrupt_to_thread
271    LDR     R6,  [R6]               ; R6 = stack ptr in new tasks's TCB
272    LDR     SP,  [R6]               ; Get new task's stack pointer
273
274    LDMFD   SP!, {R4}               ; Pop new task's SPSR
275    MSR     SPSR_cxsf, R4
276
277    LDMFD   SP!, {R0-R12,LR,PC}^    ; pop new task's R0-R12,LR & PC SPSR to CPSR
278    END
279