1/*
2 * Copyright (c) 2006-2022, RT-Thread Development Team
3 *
4 * SPDX-License-Identifier: Apache-2.0
5 *
6 * Change Logs:
7 * Date           Author       Notes
8 * 2006-08-31     Bernard      first version
9 */
10
11    /* Internal Memory Base Addresses */
12    .equ    FLASH_BASE,     0x00100000
13    .equ    RAM_BASE,       0x00200000
14
15    /* Stack Configuration */
16    .equ    TOP_STACK,      0x00204000
17    .equ    UND_STACK_SIZE, 0x00000100
18    .equ    SVC_STACK_SIZE, 0x00000400
19    .equ    ABT_STACK_SIZE, 0x00000100
20    .equ    FIQ_STACK_SIZE, 0x00000100
21    .equ    IRQ_STACK_SIZE, 0x00000100
22    .equ    USR_STACK_SIZE, 0x00000004
23
24    /* ARM architecture definitions */
25    .equ    MODE_USR, 0x10
26    .equ    MODE_FIQ, 0x11
27    .equ    MODE_IRQ, 0x12
28    .equ    MODE_SVC, 0x13
29    .equ    MODE_ABT, 0x17
30    .equ    MODE_UND, 0x1B
31    .equ    MODE_SYS, 0x1F
32
33    .equ    I_BIT, 0x80    /* when this bit is set, IRQ is disabled */
34    .equ    F_BIT, 0x40    /* when this bit is set, FIQ is disabled */
35
36.section .init, "ax"
37.code 32
38.align 0
39.globl _start
40_start:
41    b   reset
42    ldr pc, _vector_undef
43    ldr pc, _vector_swi
44    ldr pc, _vector_pabt
45    ldr pc, _vector_dabt
46    nop                         /* reserved vector */
47    ldr pc, _vector_irq
48    ldr pc, _vector_fiq
49
50_vector_undef:  .word vector_undef
51_vector_swi:    .word vector_swi
52_vector_pabt:   .word vector_pabt
53_vector_dabt:   .word vector_dabt
54_vector_resv:   .word vector_resv
55_vector_irq:    .word vector_irq
56_vector_fiq:    .word vector_fiq
57
58/*
59 * rtthread bss start and end
60 * which are defined in linker script
61 */
62.globl _bss_start
63_bss_start: .word __bss_start
64.globl _bss_end
65_bss_end:   .word __bss_end
66
67/* the system entry */
68reset:
69    /* disable watchdog */
70    ldr r0, =0xFFFFFD40
71    ldr r1, =0x00008000
72    str r1, [r0, #0x04]
73
74    /* enable the main oscillator */
75    ldr r0, =0xFFFFFC00
76    ldr r1, =0x00000601
77    str r1, [r0, #0x20]
78
79    /* wait for main oscillator to stabilize */
80moscs_loop:
81    ldr r2, [r0, #0x68]
82    ands r2, r2, #1
83    beq moscs_loop
84
85    /* set up the PLL */
86    ldr r1, =0x00191C05
87    str r1, [r0, #0x2C]
88
89    /* wait for PLL to lock */
90pll_loop:
91    ldr r2, [r0, #0x68]
92    ands r2, r2, #0x04
93    beq pll_loop
94
95    /* select clock */
96    ldr r1, =0x00000007
97    str r1, [r0, #0x30]
98
99    /* setup stack for each mode */
100    ldr r0, =TOP_STACK
101
102    /* set stack */
103    /* undefined instruction mode */
104    msr cpsr_c, #MODE_UND|I_BIT|F_BIT
105    mov sp, r0
106    sub r0, r0, #UND_STACK_SIZE
107
108    /* abort mode */
109    msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
110    mov sp, r0
111    sub r0, r0, #ABT_STACK_SIZE
112
113    /* FIQ mode */
114    msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
115    mov sp, r0
116    sub r0, r0, #FIQ_STACK_SIZE
117
118    /* IRQ mode */
119    msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
120    mov sp, r0
121    sub r0, r0, #IRQ_STACK_SIZE
122
123    /* supervisor mode */
124    msr cpsr_c, #MODE_SVC
125    mov sp, r0
126
127#ifdef __FLASH_BUILD__
128    /* Relocate .data section (Copy from ROM to RAM) */
129    ldr     r1, =_etext
130    ldr     r2, =_data
131    ldr     r3, =_edata
132data_loop:
133    cmp     r2, r3
134    ldrlo   r0, [r1], #4
135    strlo   r0, [r2], #4
136    blo     data_loop
137#else
138    /* remap SRAM to 0x0000 */
139    ldr r0, =0xFFFFFF00
140    mov r1, #0x01
141    str r1, [r0]
142#endif
143
144    /* mask all IRQs */
145    ldr r1, =0xFFFFF124
146    ldr r0, =0XFFFFFFFF
147    str r0, [r1]
148
149    /* start RT-Thread Kernel */
150    ldr pc, _rtthread_startup
151
152_rtthread_startup: .word rtthread_startup
153
154/* exception handlers */
155vector_undef: b vector_undef
156vector_swi  : b vector_swi
157vector_pabt : b vector_pabt
158vector_dabt : b vector_dabt
159vector_resv : b vector_resv
160
161.globl rt_interrupt_enter
162.globl rt_interrupt_leave
163.globl rt_thread_switch_interrupt_flag
164.globl rt_interrupt_from_thread
165.globl rt_interrupt_to_thread
166vector_irq:
167    stmfd   sp!, {r0-r12,lr}
168    bl  rt_interrupt_enter
169    bl  rt_hw_trap_irq
170    bl  rt_interrupt_leave
171
172    /*
173     * if rt_thread_switch_interrupt_flag set, jump to
174     * rt_hw_context_switch_interrupt_do and don't return
175     */
176    ldr r0, =rt_thread_switch_interrupt_flag
177    ldr r1, [r0]
178    cmp r1, #1
179    beq rt_hw_context_switch_interrupt_do
180
181    ldmfd   sp!, {r0-r12,lr}
182    subs    pc, lr, #4
183
184vector_fiq:
185    stmfd   sp!,{r0-r7,lr}
186    bl  rt_hw_trap_fiq
187    ldmfd   sp!,{r0-r7,lr}
188    subs    pc,lr,#4
189
190/*
191 * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
192 */
193rt_hw_context_switch_interrupt_do:
194    mov     r1,  #0             /* clear flag */
195    str     r1,  [r0]
196
197    ldmfd   sp!, {r0-r12,lr}    /* reload saved registers */
198    stmfd   sp!, {r0-r3}        /* save r0-r3 */
199    mov     r1,  sp
200    add     sp,  sp, #16        /* restore sp */
201    sub     r2,  lr, #4         /* save old task's pc to r2 */
202
203    mrs     r3,  spsr           /* disable interrupt */
204    orr     r0,  r3, #I_BIT|F_BIT
205    msr     spsr_c, r0
206
207    ldr     r0,  =.+8           /* switch to interrupted task's stack */
208    movs    pc,  r0
209
210    stmfd   sp!, {r2}           /* push old task's pc */
211    stmfd   sp!, {r4-r12,lr}    /* push old task's lr,r12-r4 */
212    mov     r4,  r1             /* Special optimised code below */
213    mov     r5,  r3
214    ldmfd   r4!, {r0-r3}
215    stmfd   sp!, {r0-r3}        /* push old task's r3-r0 */
216    stmfd   sp!, {r5}           /* push old task's psr */
217    mrs     r4,  spsr
218    stmfd   sp!, {r4}           /* push old task's spsr */
219
220    ldr     r4,  =rt_interrupt_from_thread
221    ldr     r5,  [r4]
222    str     sp,  [r5]           /* store sp in preempted tasks's TCB */
223
224    ldr     r6,  =rt_interrupt_to_thread
225    ldr     r6,  [r6]
226    ldr     sp,  [r6]           /* get new task's stack pointer */
227
228    ldmfd   sp!, {r4}           /* pop new task's spsr */
229    msr     SPSR_cxsf, r4
230    ldmfd   sp!, {r4}           /* pop new task's psr */
231    msr     CPSR_cxsf, r4
232
233    ldmfd   sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
234