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