1/*
2 * Copyright (c) 2006-2021, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author       Notes
8 * 2010-11-13     weety      first version
9 */
10
11#define CONFIG_STACKSIZE    512
12#define S_FRAME_SIZE        68
13
14#define S_PC                64
15#define S_LR                60
16#define S_SP                56
17#define S_IP                52
18#define S_FP                48
19#define S_R10               44
20#define S_R9                40
21#define S_R8                36
22#define S_R7                32
23#define S_R6                28
24#define S_R5                24
25#define S_R4                20
26#define S_R3                16
27#define S_R2                12
28#define S_R1                8
29#define S_R0                4
30#define S_CPSR              0
31
32.equ    I_BIT,              0x80    @ when I bit is set, IRQ is disabled
33.equ    F_BIT,              0x40    @ when F bit is set, FIQ is disabled
34
35.equ    USERMODE,           0x10
36.equ    FIQMODE,            0x11
37.equ    IRQMODE,            0x12
38.equ    SVCMODE,            0x13
39.equ    ABORTMODE,          0x17
40.equ    UNDEFMODE,          0x1b
41.equ    MODEMASK,           0x1f
42.equ    NOINT,              0xc0
43
44.equ    RAM_BASE,           0x00000000  /*Start address of RAM      */
45.equ    ROM_BASE,           0x80000000  /*Start address of Flash    */
46
47
48.equ    EINT_ENABLE0,           0x01c48018
49.equ    EINT_ENABLE1,           0x01c4801c
50
51/*
52 *************************************************************************
53 *
54 * Jump vector table
55 *
56 *************************************************************************
57 */
58
59.section .init, "ax"
60.code 32
61
62.globl _start
63_start:
64    b       reset
65    ldr     pc, _vector_undef
66    ldr     pc, _vector_swi
67    ldr     pc, _vector_pabt
68    ldr     pc, _vector_dabt
69    ldr     pc, _vector_resv
70    ldr     pc, _vector_irq
71    ldr     pc, _vector_fiq
72
73_vector_undef:  .word vector_undef
74_vector_swi:    .word vector_swi
75_vector_pabt:   .word vector_pabt
76_vector_dabt:   .word vector_dabt
77_vector_resv:   .word vector_resv
78_vector_irq:    .word vector_irq
79_vector_fiq:    .word vector_fiq
80
81.balignl    16,0xdeadbeef
82
83/*
84 *************************************************************************
85 *
86 * Startup Code (reset vector)
87 * relocate armboot to ram
88 * setup stack
89 * jump to second stage
90 *
91 *************************************************************************
92 */
93
94_TEXT_BASE:
95    .word    TEXT_BASE
96
97/*
98 * rtthread kernel start and end
99 * which are defined in linker script
100 */
101.globl _rtthread_start
102_rtthread_start:
103    .word _start
104
105.globl _rtthread_end
106_rtthread_end:
107    .word  _end
108
109/*
110 * rtthread bss start and end which are defined in linker script
111 */
112.globl _bss_start
113_bss_start:
114    .word __bss_start
115
116.globl _bss_end
117_bss_end:
118    .word __bss_end
119
120/* IRQ stack memory (calculated at run-time)     */
121.globl IRQ_STACK_START
122IRQ_STACK_START:
123    .word _irq_stack_start + 1024
124
125.globl FIQ_STACK_START
126FIQ_STACK_START:
127    .word _fiq_stack_start + 1024
128
129.globl UNDEFINED_STACK_START
130UNDEFINED_STACK_START:
131    .word _undefined_stack_start + CONFIG_STACKSIZE
132
133.globl ABORT_STACK_START
134ABORT_STACK_START:
135    .word _abort_stack_start + CONFIG_STACKSIZE
136
137.globl _STACK_START
138_STACK_START:
139    .word _svc_stack_start + 1024
140
141/* ----------------------------------entry------------------------------*/
142reset:
143
144    /* set the cpu to SVC32 mode    */
145    mrs     r0,cpsr
146    bic     r0,r0,#MODEMASK
147    orr     r0,r0,#SVCMODE
148    msr     cpsr,r0
149
150    /* mask all IRQs by clearing all bits in the INTMRs               */
151    mov r1, $0
152    ldr r0, =EINT_ENABLE0
153    str r1, [r0]
154    ldr r0, =EINT_ENABLE1
155    str r1, [r0]
156#if 0
157    /* set interrupt vector        */
158    ldr     r0, _TEXT_BASE
159    mov r1, #0x00
160    add r2, r0, #0x40         /* size, 32bytes                   */
161
162copy_loop:
163    ldmia   r0!, {r3-r10}           /* copy from source address [r0]    */
164    stmia   r1!, {r3-r10}           /* copy to   target address [r1]    */
165    cmp     r0, r2                  /* until source end addreee [r2]    */
166    ble     copy_loop
167#endif
168
169    /* setup stack */
170    bl      stack_setup
171
172    /* clear .bss */
173    mov     r0,#0                   /* get a zero                       */
174    ldr     r1,=__bss_start         /* bss start                        */
175    ldr     r2,=__bss_end           /* bss end                          */
176
177bss_loop:
178    cmp     r1,r2                   /* check if data to clear           */
179    strlo   r0,[r1],#4              /* clear 4 bytes                    */
180    blo     bss_loop                /* loop until done                  */
181
182    /* call C++ constructors of global objects                          */
183    ldr     r0, =__ctors_start__
184    ldr     r1, =__ctors_end__
185
186ctor_loop:
187    cmp     r0, r1
188    beq     ctor_end
189    ldr     r2, [r0], #4
190    stmfd   sp!, {r0-r1}
191    mov     lr, pc
192    bx      r2
193    ldmfd   sp!, {r0-r1}
194    b       ctor_loop
195
196ctor_end:
197
198    /* start RT-Thread Kernel        */
199    ldr     pc, _rtthread_startup
200
201_rtthread_startup:
202    .word rtthread_startup
203#if defined (__FLASH_BUILD__)
204_load_address:
205    .word ROM_BASE + _TEXT_BASE
206#else
207_load_address:
208    .word RAM_BASE + _TEXT_BASE
209#endif
210
211
212/*
213 *************************************************************************
214 *
215 * Interrupt handling
216 *
217 *************************************************************************
218 */
219
220.macro push_exp_reg
221    sub     sp, sp, #S_FRAME_SIZE   @/* Sizeof(struct rt_hw_stack)  */
222    stmib   sp, {r0 - r12}          @/* Calling r0-r12                  */
223    mov     r0, sp
224    mrs     r6, spsr                @/* Save CPSR                       */
225    str     lr, [r0, #S_PC]         @/* Push PC                         */
226    str     r6, [r0, #S_CPSR]       @/* Push CPSR                       */
227    @ switch to SVC mode with no interrupt
228    msr     cpsr_c, #I_BIT|F_BIT|SVCMODE
229    str     sp, [r0, #S_SP]         @/* Save calling SP                 */
230    str     lr, [r0, #S_LR]         @/* Save calling PC                 */
231.endm
232/* exception handlers    */
233    .align  5
234vector_undef:
235    push_exp_reg
236    bl     rt_hw_trap_udef
237
238    .align  5
239vector_swi:
240    push_exp_reg
241    bl     rt_hw_trap_swi
242
243    .align  5
244vector_pabt:
245    push_exp_reg
246    bl     rt_hw_trap_pabt
247
248    .align  5
249vector_dabt:
250    push_exp_reg
251    bl     rt_hw_trap_dabt
252
253    .align  5
254vector_resv:
255    push_exp_reg
256    bl     rt_hw_trap_resv
257
258.globl     rt_interrupt_enter
259.globl     rt_interrupt_leave
260.globl     rt_thread_switch_interrupt_flag
261.globl     rt_interrupt_from_thread
262.globl     rt_interrupt_to_thread
263vector_irq:
264    stmfd   sp!, {r0-r12,lr}
265
266    bl      rt_interrupt_enter
267    bl      rt_hw_trap_irq
268    bl      rt_interrupt_leave
269
270
271    @ if rt_thread_switch_interrupt_flag set, jump to
272    @ rt_hw_context_switch_interrupt_do and don't return
273    ldr     r0, =rt_thread_switch_interrupt_flag
274    ldr     r1, [r0]
275    cmp     r1, #1
276    beq     rt_hw_context_switch_interrupt_do
277
278    ldmfd   sp!, {r0-r12,lr}
279    subs    pc, lr, #4
280
281    .align  5
282vector_fiq:
283    stmfd   sp!,{r0-r7,lr}
284    bl      rt_hw_trap_fiq
285    ldmfd   sp!,{r0-r7,lr}
286    subs    pc,lr,#4
287
288rt_hw_context_switch_interrupt_do:
289    mov     r1,  #0         @ clear flag
290    str     r1,  [r0]
291
292    ldmfd   sp!, {r0-r12,lr}@ reload saved registers
293    stmfd   sp,  {r0-r2}    @ save r0-r2
294
295    mrs     r0,  spsr       @ get cpsr of interrupt thread
296
297    sub     r1,  sp, #4*3
298    sub     r2,  lr, #4     @ save old task's pc to r2
299
300    @ switch to SVC mode with no interrupt
301    msr     cpsr_c, #I_BIT|F_BIT|SVCMODE
302
303    stmfd   sp!, {r2}       @ push old task's pc
304    stmfd   sp!, {r3-r12,lr}@ push old task's lr,r12-r4
305    ldmfd   r1,  {r1-r3}    @ restore r0-r2 of the interrupt thread
306    stmfd   sp!, {r1-r3}    @ push old task's r0-r2
307    stmfd   sp!, {r0}       @ push old task's cpsr
308
309    ldr     r4,  =rt_interrupt_from_thread
310    ldr     r5,  [r4]
311    str     sp,  [r5]       @ store sp in preempted tasks's TCB
312
313    ldr     r6,  =rt_interrupt_to_thread
314    ldr     r6,  [r6]
315    ldr     sp,  [r6]       @ get new task's stack pointer
316
317    ldmfd   sp!, {r4}       @ pop new task's cpsr to spsr
318    msr     spsr_cxsf, r4
319
320    ldmfd   sp!, {r0-r12,lr,pc}^ @ pop new task's r0-r12,lr & pc, copy spsr to cpsr
321
322
323stack_setup:
324    mrs     r0, cpsr
325    bic     r0, r0, #MODEMASK
326    orr     r1, r0, #UNDEFMODE|NOINT
327    msr     cpsr_cxsf, r1           /* undef mode          */
328    ldr     sp, UNDEFINED_STACK_START
329
330    orr     r1,r0,#ABORTMODE|NOINT
331    msr     cpsr_cxsf,r1            /* abort mode          */
332    ldr     sp, ABORT_STACK_START
333
334    orr     r1,r0,#IRQMODE|NOINT
335    msr     cpsr_cxsf,r1            /* IRQ mode            */
336    ldr     sp, IRQ_STACK_START
337
338    orr     r1,r0,#FIQMODE|NOINT
339    msr     cpsr_cxsf,r1            /* FIQ mode            */
340    ldr     sp, FIQ_STACK_START
341
342    bic     r0,r0,#MODEMASK
343    orr     r1,r0,#SVCMODE|NOINT
344    msr     cpsr_cxsf,r1            /* SVC mode            */
345
346    ldr     sp, _STACK_START
347
348    /* USER mode is not initialized. */
349    bx      lr    /* The LR register may be not valid for the mode changes.*/
350
351/*/*}*/
352
353
354