summaryrefslogtreecommitdiff
path: root/libcpu/arm/am335x/start_iar.s
blob: beb3113b702cd84e40064ce00bf1aee409236bf4 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
/*
 * Copyright (c) 2006-2022, RT-Thread Development Team
 *
 * SPDX-License-Identifier: Apache-2.0
 *
 * Change Logs:
 * Date           Author       Notes
 * 2015-04-06     zchong      the first version
 */

        MODULE  ?cstartup

        ; --------------------
; Mode, correspords to bits 0-5 in CPSR

MODE_MSK DEFINE 0x1F            ; Bit mask for mode bits in CPSR
I_Bit    DEFINE 0x80            ; when I bit is set, IRQ is disabled
F_Bit    DEFINE 0x40            ; when F bit is set, FIQ is disabled

USR_MODE DEFINE 0x10            ; User mode
FIQ_MODE DEFINE 0x11            ; Fast Interrupt Request mode
IRQ_MODE DEFINE 0x12            ; Interrupt Request mode
SVC_MODE DEFINE 0x13            ; Supervisor mode
ABT_MODE DEFINE 0x17            ; Abort mode
UND_MODE DEFINE 0x1B            ; Undefined Instruction mode
SYS_MODE DEFINE 0x1F            ; System mode


        ;; Forward declaration of sections.
        SECTION IRQ_STACK:DATA:NOROOT(3)
        SECTION FIQ_STACK:DATA:NOROOT(3)
        SECTION SVC_STACK:DATA:NOROOT(3)
        SECTION ABT_STACK:DATA:NOROOT(3)
        SECTION UND_STACK:DATA:NOROOT(3)
        SECTION CSTACK:DATA:NOROOT(3)
        SECTION .text:CODE


        SECTION .intvec:CODE:NOROOT(5)

        PUBLIC  __vector
        PUBLIC  __iar_program_start


__iar_init$$done:               ; The vector table is not needed
                                ; until after copy initialization is done

__vector:                       ; Make this a DATA label, so that stack usage
                                ; analysis doesn't consider it an uncalled fun
        ARM

        ; All default exception handlers (except reset) are
        ; defined as weak symbol definitions.
        ; If a handler is defined by the application it will take precedence.
        LDR     PC,Reset_Addr           ; Reset
        LDR     PC,Undefined_Addr       ; Undefined instructions
        LDR     PC,SWI_Addr             ; Software interrupt (SWI/SVC)
        LDR     PC,Prefetch_Addr        ; Prefetch abort
        LDR     PC,Abort_Addr           ; Data abort
        DCD     0                       ; RESERVED
        LDR     PC,IRQ_Addr             ; IRQ
        LDR     PC,FIQ_Addr             ; FIQ

        DATA

Reset_Addr:     DCD   __iar_program_start
Undefined_Addr: DCD   Undefined_Handler
SWI_Addr:       DCD   SWI_Handler
Prefetch_Addr:  DCD   Prefetch_Handler
Abort_Addr:     DCD   Abort_Handler
IRQ_Addr:       DCD   IRQ_Handler
FIQ_Addr:       DCD   FIQ_Handler


; --------------------------------------------------
; ?cstartup -- low-level system initialization code.
;
; After a reset execution starts here, the mode is ARM, supervisor
; with interrupts disabled.
;

        SECTION .text:CODE:NOROOT(2)

        EXTERN  rt_hw_trap_udef
        EXTERN  rt_hw_trap_swi
        EXTERN  rt_hw_trap_pabt
        EXTERN  rt_hw_trap_dabt
        EXTERN  rt_hw_trap_fiq
        EXTERN  rt_hw_trap_irq
        EXTERN  rt_interrupt_enter
        EXTERN  rt_interrupt_leave
        EXTERN  rt_thread_switch_interrupt_flag
        EXTERN  rt_interrupt_from_thread
        EXTERN  rt_interrupt_to_thread
        EXTERN  rt_current_thread
        EXTERN  vmm_thread
        EXTERN  vmm_virq_check

        EXTERN  __cmain
        REQUIRE __vector
        EXTWEAK __iar_init_core
        EXTWEAK __iar_init_vfp


        ARM

__iar_program_start:
?cstartup:

;
; Add initialization needed before setup of stackpointers here.
;

;
; Initialize the stack pointers.
; The pattern below can be used for any of the exception stacks:
; FIQ, IRQ, SVC, ABT, UND, SYS.
; The USR mode uses the same stack as SYS.
; The stack segments must be defined in the linker command file,
; and be declared above.
;

        MRS     r0, cpsr                ; Original PSR value

        ;; Set up the interrupt stack pointer.
        BIC     r0, r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0, r0, #IRQ_MODE       ; Set IRQ mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(IRQ_STACK)     ; End of IRQ_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        ;; Set up the fast interrupt stack pointer.
        BIC     r0, r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0, r0, #FIQ_MODE       ; Set FIR mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(FIQ_STACK)     ; End of FIQ_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        BIC     r0,r0,#MODE_MSK         ; Clear the mode bits
        ORR     r0,r0,#ABT_MODE         ; Set Abort mode bits
        MSR     cpsr_c,r0               ; Change the mode
        LDR     sp,=SFE(ABT_STACK)      ; End of ABT_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        BIC     r0,r0,#MODE_MSK         ; Clear the mode bits
        ORR     r0,r0,#UND_MODE         ; Set Undefined mode bits
        MSR     cpsr_c,r0               ; Change the mode
        LDR     sp,=SFE(UND_STACK)      ; End of UND_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        ;; Set up the normal stack pointer.
        BIC     r0 ,r0, #MODE_MSK       ; Clear the mode bits
        ORR     r0 ,r0, #SVC_MODE       ; Set System mode bits
        MSR     cpsr_c, r0              ; Change the mode
        LDR     sp, =SFE(SVC_STACK)     ; End of SVC_STACK
        BIC     sp,sp,#0x7              ; Make sure SP is 8 aligned

        ;; Turn on core features assumed to be enabled.
        BL      __iar_init_core

        ;; Initialize VFP (if needed).
        BL      __iar_init_vfp


        ;; Continue to __cmain for C-level initialization.
        B       __cmain


Undefined_Handler:
        SUB     sp, sp, #72
        STMIA   sp, {r0 - r12}          ;/* Calling r0-r12                  */
        ADD     r8, sp, #60

        MRS     r1, cpsr
        MRS     r2, spsr
        ORR     r2,r2, #I_Bit | F_Bit
        MSR     cpsr_c, r2
        MOV     r0, r0
        STMDB   r8, {sp, lr}            ;/* Calling SP, LR                  */
        MSR     cpsr_c, r1              ;/* return to Undefined Instruction mode  */

        STR     lr, [r8, #0]            ;/* Save calling PC                 */
        MRS     r6, spsr
        STR     r6, [r8, #4]            ;/* Save CPSR                       */
        STR     r0, [r8, #8]            ;/* Save OLD_R0                     */
        MOV     r0, sp

        BL      rt_hw_trap_udef

        LDMIA    sp, {r0 - r12}         ;/* Calling r0 - r2  */
        MOV      r0, r0
        LDR      lr, [sp, #60]          ;/* Get PC   */
        ADD      sp, sp, #72
        MOVS     pc, lr                 ;/* return & move spsr_svc into cpsr */

SWI_Handler:
        BL      rt_hw_trap_swi

Prefetch_Handler:
        BL      rt_hw_trap_pabt

Abort_Handler:
        SUB     sp, sp, #72
        STMIA   sp, {r0 - r12}          ;/* Calling r0-r12                  */
        ADD     r8, sp, #60
        STMDB   r8, {sp, lr}            ;/* Calling SP, LR                  */
        STR     lr, [r8, #0]            ;/* Save calling PC                 */
        MRS     r6, spsr
        STR     r6, [r8, #4]            ;/* Save CPSR                       */
        STR     r0, [r8, #8]            ;/* Save OLD_R0                     */
        MOV     r0, sp

        BL      rt_hw_trap_dabt

        LDMIA    sp, {r0 - r12}         ;/* Calling r0 - r2  */
        MOV      r0, r0
        LDR      lr, [sp, #60]          ;/* Get PC   */
        ADD      sp, sp, #72
        MOVS     pc, lr                 ;/* return & move spsr_svc into cpsr */

FIQ_Handler:
        STMFD   sp!,{r0-r7,lr}
        BL      rt_hw_trap_fiq
        LDMFD   sp!,{r0-r7,lr}
        SUBS    pc,lr,#4

IRQ_Handler:
        STMFD   sp!, {r0-r12,lr}

        BL      rt_interrupt_enter
        BL      rt_hw_trap_irq
        BL      rt_interrupt_leave

        ; if rt_thread_switch_interrupt_flag set, jump to
        ; rt_hw_context_switch_interrupt_do and don't return
        LDR     r0, =rt_thread_switch_interrupt_flag
        LDR     r1, [r0]
        CMP     r1, #1
        BEQ     rt_hw_context_switch_interrupt_do

        LDMFD   sp!, {r0-r12,lr}
        SUBS    pc, lr, #4

rt_hw_context_switch_interrupt_do:
        MOV     r1,  #0         ; clear flag
        STR     r1,  [r0]

        LDMFD   sp!, {r0-r12,lr}; reload saved registers
        STMFD   sp,  {r0-r2}    ; save r0-r2

        MRS     r0,  spsr       ; get cpsr of interrupt thread

        SUB     r1,  sp, #4*3
        SUB     r2,  lr, #4     ; save old task's pc to r2

        ; switch to SVC mode with no interrupt
        MSR     cpsr_c, #I_Bit | F_Bit | SVC_MODE

        STMFD   sp!, {r2}       ; push old task's pc
        STMFD   sp!, {r3-r12,lr}; push old task's lr,r12-r4
        LDMFD   r1,  {r1-r3}    ; restore r0-r2 of the interrupt thread
        STMFD   sp!, {r1-r3}    ; push old task's r0-r2
        STMFD   sp!, {r0}       ; push old task's cpsr

        LDR     r4,  =rt_interrupt_from_thread
        LDR     r5,  [r4]
        STR     sp,  [r5]       ; store sp in preempted tasks's TCB

        LDR     r6,  =rt_interrupt_to_thread
        LDR     r6,  [r6]
        LDR     sp,  [r6]       ; get new task's stack pointer

        LDMFD   sp!, {r4}       ; pop new task's cpsr to spsr
        MSR     spsr_cxsf, r4

        LDMFD   sp!, {r0-r12,lr,pc}^ ; pop new task's r0-r12,lr & pc, copy spsr to cpsr

     END