xref: /nrf52832-nimble/rt-thread/libcpu/arm/lpc24xx/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 * 2008-12-11     XuXinming    first version
9 * 2011-03-17     Bernard      update to 0.4.x
10 */
11
12#define WDMOD          (0xE0000000 + 0x00)
13#define VICIntEnClr    (0xFFFFF000 + 0x014)
14#define VICVectAddr    (0xFFFFF000 + 0xF00)
15#define VICIntSelect   (0xFFFFF000 + 0x00C)
16#define PLLCFG         (0xE01FC000 + 0x084)
17#define PLLCON         (0xE01FC000 + 0x080)
18#define PLLFEED        (0xE01FC000 + 0x08C)
19#define PLLSTAT        (0xE01FC000 + 0x088)
20#define CCLKCFG        (0xE01FC000 + 0x104)
21#define MEMMAP         (0xE01FC000 + 0x040)
22#define SCS            (0xE01FC000 + 0x1A0)
23#define CLKSRCSEL      (0xE01FC000 + 0x10C)
24#define MAMCR          (0xE01FC000 + 0x000)
25#define MAMTIM         (0xE01FC000 + 0x004)
26
27/* stack memory */
28.section .bss.noinit
29.equ    IRQ_STACK_SIZE, 0x00000200
30.equ    FIQ_STACK_SIZE, 0x00000100
31.equ    UDF_STACK_SIZE, 0x00000004
32.equ    ABT_STACK_SIZE, 0x00000004
33.equ    SVC_STACK_SIZE, 0x00000200
34
35.space  IRQ_STACK_SIZE
36IRQ_STACK:
37
38.space  FIQ_STACK_SIZE
39FIQ_STACK:
40
41.space  UDF_STACK_SIZE
42UDF_STACK:
43
44.space  ABT_STACK_SIZE
45ABT_STACK:
46
47.space  SVC_STACK_SIZE
48SVC_STACK:
49
50.section .init, "ax"
51.code 32
52.globl _start
53_start:
54        b reset
55        ldr     pc, _vector_undef
56        ldr     pc, _vector_swi
57        ldr     pc, _vector_pabt
58        ldr     pc, _vector_dabt
59        ldr     pc, _vector_resv
60        ldr     pc, _vector_irq
61        ldr     pc, _vector_fiq
62
63_vector_undef:  .word vector_undef
64_vector_swi:    .word vector_swi
65_vector_pabt:   .word vector_pabt
66_vector_dabt:   .word vector_dabt
67_vector_resv:   .word vector_resv
68_vector_irq:    .word vector_irq
69_vector_fiq:    .word vector_fiq
70
71.balignl        16,0xdeadbeef
72
73/*
74 * rtthread kernel start and end
75 * which are defined in linker script
76 */
77.globl _rtthread_start
78_rtthread_start:
79        .word _start
80
81.globl _rtthread_end
82_rtthread_end:
83        .word  _end
84
85/*
86 * rtthread bss start and end which are defined in linker script
87 */
88.globl _bss_start
89_bss_start:
90        .word __bss_start
91
92.globl _bss_end
93_bss_end:
94        .word __bss_end
95
96.text
97.code 32
98
99/* the system entry */
100reset:
101        /* enter svc mode */
102        msr cpsr_c, #SVCMODE|NOINT
103
104        /*watch dog disable */
105        ldr r0,=WDMOD
106        ldr r1,=0x0
107        str r1,[r0]
108
109        /* all interrupt disable */
110        ldr r0,=VICIntEnClr
111        ldr r1,=0xffffffff
112        str r1,[r0]
113
114        ldr     r1, =VICVectAddr
115        ldr     r0, =0x00
116        str     r0, [r1]
117
118        ldr     r1, =VICIntSelect
119        ldr     r0, =0x00
120        str     r0, [r1]
121
122        /* setup stack */
123        bl              stack_setup
124
125        /* copy .data to SRAM */
126        ldr     r1, =_sidata            /* .data start in image */
127        ldr     r2, =_edata             /* .data end in image   */
128        ldr     r3, =_sdata             /* sram data start      */
129data_loop:
130        ldr     r0, [r1, #0]
131        str     r0, [r3]
132
133        add     r1, r1, #4
134        add     r3, r3, #4
135
136        cmp     r3, r2                   /* check if data to clear */
137        blo     data_loop                /* loop until done        */
138
139        /* clear .bss */
140        mov     r0,#0                   /* get a zero */
141        ldr     r1,=__bss_start         /* bss start  */
142        ldr     r2,=__bss_end           /* bss end    */
143
144bss_loop:
145        cmp     r1,r2                   /* check if data to clear */
146        strlo   r0,[r1],#4              /* clear 4 bytes          */
147        blo     bss_loop                /* loop until done        */
148
149        /* call C++ constructors of global objects */
150        ldr     r0, =__ctors_start__
151        ldr     r1, =__ctors_end__
152
153ctor_loop:
154        cmp     r0, r1
155        beq     ctor_end
156        ldr     r2, [r0], #4
157        stmfd   sp!, {r0-r1}
158        mov     lr, pc
159        bx      r2
160        ldmfd   sp!, {r0-r1}
161        b       ctor_loop
162ctor_end:
163
164        /* start RT-Thread Kernel               */
165        ldr     pc, _rtthread_startup
166
167_rtthread_startup:
168        .word rtthread_startup
169
170        .equ USERMODE,  0x10
171        .equ FIQMODE,   0x11
172        .equ IRQMODE,   0x12
173        .equ SVCMODE,   0x13
174        .equ ABORTMODE, 0x17
175        .equ UNDEFMODE, 0x1b
176        .equ MODEMASK,  0x1f
177        .equ NOINT,             0xc0
178
179/* exception handlers */
180vector_undef:   bl rt_hw_trap_udef
181vector_swi:     bl rt_hw_trap_swi
182vector_pabt:    bl rt_hw_trap_pabt
183vector_dabt:    bl rt_hw_trap_dabt
184vector_resv:    bl rt_hw_trap_resv
185
186.globl rt_interrupt_enter
187.globl rt_interrupt_leave
188.globl rt_thread_switch_interrupt_flag
189.globl rt_interrupt_from_thread
190.globl rt_interrupt_to_thread
191vector_irq:
192        stmfd   sp!, {r0-r12,lr}
193        bl      rt_interrupt_enter
194        bl      rt_hw_trap_irq
195        bl      rt_interrupt_leave
196
197        /* if rt_thread_switch_interrupt_flag set,
198         * jump to _interrupt_thread_switch and don't return
199         */
200        ldr     r0, =rt_thread_switch_interrupt_flag
201        ldr     r1, [r0]
202        cmp     r1, #1
203        beq     _interrupt_thread_switch
204
205        ldmfd   sp!, {r0-r12,lr}
206        subs    pc, lr, #4
207
208        .align  5
209vector_fiq:
210        stmfd   sp!,{r0-r7,lr}
211        bl      rt_hw_trap_fiq
212        ldmfd   sp!,{r0-r7,lr}
213        subs    pc,lr,#4
214
215_interrupt_thread_switch:
216        mov     r1, #0          /* clear rt_thread_switch_interrupt_flag */
217        str     r1, [r0]
218
219        ldmfd   sp!, {r0-r12,lr} /* reload saved registers */
220        stmfd   sp!, {r0-r3}    /* save r0-r3 */
221        mov     r1, sp
222        add     sp, sp, #16     /*  restore sp */
223        sub     r2, lr, #4      /* save old task's pc to r2 */
224
225        mrs     r3, spsr        /* disable interrupt */
226        orr     r0, r3, #NOINT
227        msr     spsr_c, r0
228
229        ldr     r0,  =.+8       /* switch to interrupted task's stack */
230        movs    pc, r0
231
232        stmfd   sp!, {r2}       /* push old task's pc */
233        stmfd   sp!, {r4-r12,lr} /* push old task's lr,r12-r4 */
234        mov     r4, r1          /* Special optimised code below */
235        mov     r5, r3
236        ldmfd   r4!, {r0-r3}
237        stmfd   sp!, {r0-r3}    /* push old task's r3-r0 */
238        stmfd   sp!, {r5}       /* push old task's psr */
239        mrs     r4, spsr
240        stmfd   sp!, {r4}       /* push old task's spsr */
241
242        ldr     r4, =rt_interrupt_from_thread
243        ldr     r5, [r4]
244        str     sp, [r5]        /* store sp in preempted tasks's TCB */
245
246        ldr     r6, =rt_interrupt_to_thread
247        ldr     r6, [r6]
248        ldr     sp, [r6]        /* get new task's stack pointer */
249
250        ldmfd   sp!, {r4}       /* pop new task's spsr */
251        msr     SPSR_cxsf, r4
252        ldmfd   sp!, {r4}       /* pop new task's psr */
253        msr     CPSR_cxsf, r4
254
255        ldmfd sp!, {r0-r12,lr,pc} /* pop new task's r0-r12,lr & pc */
256
257stack_setup:
258        mrs     r0, cpsr
259        bic     r0, r0, #MODEMASK
260        orr     r1, r0, #UNDEFMODE|NOINT
261        msr     cpsr_cxsf, r1                   /* undef mode */
262        ldr     sp, =UDF_STACK
263
264        orr     r1,r0,#ABORTMODE|NOINT
265        msr     cpsr_cxsf,r1                    /* abort mode */
266        ldr     sp, =ABT_STACK
267
268        orr     r1,r0,#IRQMODE|NOINT
269        msr     cpsr_cxsf,r1                    /* IRQ mode */
270        ldr     sp, =IRQ_STACK
271
272        orr     r1,r0,#FIQMODE|NOINT
273        msr     cpsr_cxsf,r1                    /* FIQ mode */
274        ldr     sp, =FIQ_STACK
275
276        bic     r0,r0,#MODEMASK
277        orr     r1,r0,#SVCMODE|NOINT
278        msr     cpsr_cxsf,r1                    /* SVC mode */
279        ldr     sp, =SVC_STACK
280
281        /* USER mode is not initialized. */
282        mov     pc,lr                           /* The LR register may be not valid for the mode changes.*/
283