xref: /nrf52832-nimble/rt-thread/libcpu/arm/AT91SAM7X/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 * 2006-08-31     Bernard      first version
9*10465441SEvalZero */
10*10465441SEvalZero
11*10465441SEvalZero	/* Internal Memory Base Addresses */
12*10465441SEvalZero	.equ    FLASH_BASE,     0x00100000
13*10465441SEvalZero	.equ    RAM_BASE,       0x00200000
14*10465441SEvalZero
15*10465441SEvalZero	/* Stack Configuration */
16*10465441SEvalZero	.equ    TOP_STACK,      0x00204000
17*10465441SEvalZero	.equ    UND_STACK_SIZE, 0x00000100
18*10465441SEvalZero	.equ    SVC_STACK_SIZE, 0x00000400
19*10465441SEvalZero	.equ    ABT_STACK_SIZE, 0x00000100
20*10465441SEvalZero	.equ    FIQ_STACK_SIZE, 0x00000100
21*10465441SEvalZero	.equ    IRQ_STACK_SIZE, 0x00000100
22*10465441SEvalZero	.equ    USR_STACK_SIZE, 0x00000004
23*10465441SEvalZero
24*10465441SEvalZero	/* ARM architecture definitions */
25*10465441SEvalZero	.equ	MODE_USR, 0x10
26*10465441SEvalZero	.equ	MODE_FIQ, 0x11
27*10465441SEvalZero	.equ	MODE_IRQ, 0x12
28*10465441SEvalZero	.equ	MODE_SVC, 0x13
29*10465441SEvalZero	.equ	MODE_ABT, 0x17
30*10465441SEvalZero	.equ	MODE_UND, 0x1B
31*10465441SEvalZero	.equ	MODE_SYS, 0x1F
32*10465441SEvalZero
33*10465441SEvalZero	.equ    I_BIT, 0x80    /* when this bit is set, IRQ is disabled */
34*10465441SEvalZero	.equ    F_BIT, 0x40    /* when this bit is set, FIQ is disabled */
35*10465441SEvalZero
36*10465441SEvalZero.section .init, "ax"
37*10465441SEvalZero.code 32
38*10465441SEvalZero.align 0
39*10465441SEvalZero.globl _start
40*10465441SEvalZero_start:
41*10465441SEvalZero	b	reset
42*10465441SEvalZero	ldr	pc, _vector_undef
43*10465441SEvalZero	ldr	pc, _vector_swi
44*10465441SEvalZero	ldr	pc, _vector_pabt
45*10465441SEvalZero	ldr	pc, _vector_dabt
46*10465441SEvalZero	nop							/* reserved vector */
47*10465441SEvalZero	ldr	pc, _vector_irq
48*10465441SEvalZero	ldr	pc, _vector_fiq
49*10465441SEvalZero
50*10465441SEvalZero_vector_undef:	.word vector_undef
51*10465441SEvalZero_vector_swi:	.word vector_swi
52*10465441SEvalZero_vector_pabt:	.word vector_pabt
53*10465441SEvalZero_vector_dabt:	.word vector_dabt
54*10465441SEvalZero_vector_resv:	.word vector_resv
55*10465441SEvalZero_vector_irq:	.word vector_irq
56*10465441SEvalZero_vector_fiq:	.word vector_fiq
57*10465441SEvalZero
58*10465441SEvalZero/*
59*10465441SEvalZero * rtthread bss start and end
60*10465441SEvalZero * which are defined in linker script
61*10465441SEvalZero */
62*10465441SEvalZero.globl _bss_start
63*10465441SEvalZero_bss_start:	.word __bss_start
64*10465441SEvalZero.globl _bss_end
65*10465441SEvalZero_bss_end:	.word __bss_end
66*10465441SEvalZero
67*10465441SEvalZero/* the system entry */
68*10465441SEvalZeroreset:
69*10465441SEvalZero	/* disable watchdog */
70*10465441SEvalZero	ldr r0, =0xFFFFFD40
71*10465441SEvalZero	ldr r1, =0x00008000
72*10465441SEvalZero	str r1, [r0, #0x04]
73*10465441SEvalZero
74*10465441SEvalZero	/* enable the main oscillator */
75*10465441SEvalZero	ldr r0, =0xFFFFFC00
76*10465441SEvalZero	ldr r1, =0x00000601
77*10465441SEvalZero	str r1, [r0, #0x20]
78*10465441SEvalZero
79*10465441SEvalZero	/* wait for main oscillator to stabilize */
80*10465441SEvalZeromoscs_loop:
81*10465441SEvalZero	ldr r2, [r0, #0x68]
82*10465441SEvalZero	ands r2, r2, #1
83*10465441SEvalZero	beq moscs_loop
84*10465441SEvalZero
85*10465441SEvalZero	/* set up the PLL */
86*10465441SEvalZero	ldr r1, =0x00191C05
87*10465441SEvalZero	str r1, [r0, #0x2C]
88*10465441SEvalZero
89*10465441SEvalZero	/* wait for PLL to lock */
90*10465441SEvalZeropll_loop:
91*10465441SEvalZero	ldr r2, [r0, #0x68]
92*10465441SEvalZero	ands r2, r2, #0x04
93*10465441SEvalZero	beq pll_loop
94*10465441SEvalZero
95*10465441SEvalZero	/* select clock */
96*10465441SEvalZero	ldr r1, =0x00000007
97*10465441SEvalZero	str r1, [r0, #0x30]
98*10465441SEvalZero
99*10465441SEvalZero#ifdef __FLASH_BUILD__
100*10465441SEvalZero	/* copy exception vectors into internal sram */
101*10465441SEvalZero    /*
102*10465441SEvalZero	mov r8, #RAM_BASE
103*10465441SEvalZero	ldr r9, =_start
104*10465441SEvalZero	ldmia r9!, {r0-r7}
105*10465441SEvalZero	stmia r8!, {r0-r7}
106*10465441SEvalZero	ldmia r9!, {r0-r6}
107*10465441SEvalZero	stmia r8!, {r0-r6}
108*10465441SEvalZero    */
109*10465441SEvalZero#endif
110*10465441SEvalZero
111*10465441SEvalZero	/* setup stack for each mode */
112*10465441SEvalZero	ldr r0, =TOP_STACK
113*10465441SEvalZero
114*10465441SEvalZero	/* set stack */
115*10465441SEvalZero	/* undefined instruction mode */
116*10465441SEvalZero	msr cpsr_c, #MODE_UND|I_BIT|F_BIT
117*10465441SEvalZero	mov sp, r0
118*10465441SEvalZero	sub r0, r0, #UND_STACK_SIZE
119*10465441SEvalZero
120*10465441SEvalZero	/* abort mode */
121*10465441SEvalZero	msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
122*10465441SEvalZero	mov sp, r0
123*10465441SEvalZero	sub r0, r0, #ABT_STACK_SIZE
124*10465441SEvalZero
125*10465441SEvalZero	/* FIQ mode */
126*10465441SEvalZero	msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
127*10465441SEvalZero	mov sp, r0
128*10465441SEvalZero	sub r0, r0, #FIQ_STACK_SIZE
129*10465441SEvalZero
130*10465441SEvalZero	/* IRQ mode */
131*10465441SEvalZero	msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
132*10465441SEvalZero	mov sp, r0
133*10465441SEvalZero	sub r0, r0, #IRQ_STACK_SIZE
134*10465441SEvalZero
135*10465441SEvalZero	/* supervisor mode */
136*10465441SEvalZero	msr cpsr_c, #MODE_SVC|I_BIT|F_BIT
137*10465441SEvalZero	mov sp, r0
138*10465441SEvalZero
139*10465441SEvalZero	/* remap SRAM to 0x0000 */
140*10465441SEvalZero	/*
141*10465441SEvalZero	ldr r0, =0xFFFFFF00
142*10465441SEvalZero	mov r1, #0x01
143*10465441SEvalZero	str r1, [r0]
144*10465441SEvalZero	*/
145*10465441SEvalZero
146*10465441SEvalZero	/* mask all IRQs */
147*10465441SEvalZero	ldr	r1, =0xFFFFF124
148*10465441SEvalZero	ldr	r0, =0XFFFFFFFF
149*10465441SEvalZero	str	r0, [r1]
150*10465441SEvalZero
151*10465441SEvalZero    /* copy .data to SRAM */
152*10465441SEvalZero    ldr     r1, =_sidata            /* .data start in image */
153*10465441SEvalZero    ldr     r2, =_edata             /* .data end in image   */
154*10465441SEvalZero    ldr     r3, =_sdata             /* sram data start      */
155*10465441SEvalZerodata_loop:
156*10465441SEvalZero    ldr     r0, [r1, #0]
157*10465441SEvalZero    str     r0, [r3]
158*10465441SEvalZero
159*10465441SEvalZero    add     r1, r1, #4
160*10465441SEvalZero    add     r3, r3, #4
161*10465441SEvalZero
162*10465441SEvalZero    cmp     r3, r2                   /* check if data to clear */
163*10465441SEvalZero    blo     data_loop                /* loop until done        */
164*10465441SEvalZero
165*10465441SEvalZero    /* clear .bss */
166*10465441SEvalZero    mov     r0,#0                   /* get a zero */
167*10465441SEvalZero    ldr     r1,=__bss_start         /* bss start  */
168*10465441SEvalZero    ldr     r2,=__bss_end           /* bss end    */
169*10465441SEvalZero
170*10465441SEvalZerobss_loop:
171*10465441SEvalZero    cmp     r1,r2                   /* check if data to clear */
172*10465441SEvalZero    strlo   r0,[r1],#4              /* clear 4 bytes          */
173*10465441SEvalZero    blo     bss_loop                /* loop until done        */
174*10465441SEvalZero
175*10465441SEvalZero    /* call C++ constructors of global objects */
176*10465441SEvalZero    ldr     r0, =__ctors_start__
177*10465441SEvalZero    ldr     r1, =__ctors_end__
178*10465441SEvalZero
179*10465441SEvalZeroctor_loop:
180*10465441SEvalZero    cmp     r0, r1
181*10465441SEvalZero    beq     ctor_end
182*10465441SEvalZero    ldr     r2, [r0], #4
183*10465441SEvalZero    stmfd   sp!, {r0-r1}
184*10465441SEvalZero    mov     lr, pc
185*10465441SEvalZero    bx      r2
186*10465441SEvalZero    ldmfd   sp!, {r0-r1}
187*10465441SEvalZero    b       ctor_loop
188*10465441SEvalZeroctor_end:
189*10465441SEvalZero
190*10465441SEvalZero
191*10465441SEvalZero	/* start RT-Thread Kernel */
192*10465441SEvalZero	ldr	pc, _rtthread_startup
193*10465441SEvalZero
194*10465441SEvalZero_rtthread_startup: .word rtthread_startup
195*10465441SEvalZero
196*10465441SEvalZero/* exception handlers */
197*10465441SEvalZerovector_undef: b	vector_undef
198*10465441SEvalZerovector_swi  : b vector_swi
199*10465441SEvalZerovector_pabt : b vector_pabt
200*10465441SEvalZerovector_dabt : b vector_dabt
201*10465441SEvalZerovector_resv : b vector_resv
202*10465441SEvalZero
203*10465441SEvalZero.globl rt_interrupt_enter
204*10465441SEvalZero.globl rt_interrupt_leave
205*10465441SEvalZero.globl rt_thread_switch_interrupt_flag
206*10465441SEvalZero.globl rt_interrupt_from_thread
207*10465441SEvalZero.globl rt_interrupt_to_thread
208*10465441SEvalZerovector_irq:
209*10465441SEvalZero	stmfd	sp!, {r0-r12,lr}
210*10465441SEvalZero	bl	rt_interrupt_enter
211*10465441SEvalZero	bl	rt_hw_trap_irq
212*10465441SEvalZero	bl	rt_interrupt_leave
213*10465441SEvalZero
214*10465441SEvalZero	/*
215*10465441SEvalZero	 * if rt_thread_switch_interrupt_flag set, jump to
216*10465441SEvalZero	 * rt_hw_context_switch_interrupt_do and don't return
217*10465441SEvalZero	 */
218*10465441SEvalZero	ldr	r0, =rt_thread_switch_interrupt_flag
219*10465441SEvalZero	ldr	r1, [r0]
220*10465441SEvalZero	cmp	r1, #1
221*10465441SEvalZero	beq	rt_hw_context_switch_interrupt_do
222*10465441SEvalZero
223*10465441SEvalZero	ldmfd	sp!, {r0-r12,lr}
224*10465441SEvalZero	subs	pc, lr, #4
225*10465441SEvalZero
226*10465441SEvalZerovector_fiq:
227*10465441SEvalZero	stmfd	sp!,{r0-r7,lr}
228*10465441SEvalZero	bl 	rt_hw_trap_fiq
229*10465441SEvalZero	ldmfd	sp!,{r0-r7,lr}
230*10465441SEvalZero	subs	pc,lr,#4
231*10465441SEvalZero
232*10465441SEvalZero/*
233*10465441SEvalZero * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
234*10465441SEvalZero */
235*10465441SEvalZerort_hw_context_switch_interrupt_do:
236*10465441SEvalZero	mov	r1,  #0				@ clear flag
237*10465441SEvalZero	str	r1,  [r0]
238*10465441SEvalZero
239*10465441SEvalZero	ldmfd	sp!, {r0-r12,lr}@ reload saved registers
240*10465441SEvalZero	stmfd	sp!, {r0-r3}	@ save r0-r3
241*10465441SEvalZero	mov	r1,  sp
242*10465441SEvalZero	add	sp,  sp, #16		@ restore sp
243*10465441SEvalZero	sub	r2,  lr, #4			@ save old task's pc to r2
244*10465441SEvalZero
245*10465441SEvalZero	mrs	r3,  spsr			@ disable interrupt
246*10465441SEvalZero	orr	r0,  r3, #I_BIT|F_BIT
247*10465441SEvalZero	msr	spsr_c, r0
248*10465441SEvalZero
249*10465441SEvalZero	ldr	r0,  =.+8			@ switch to interrupted task's stack
250*10465441SEvalZero	movs	pc,  r0
251*10465441SEvalZero
252*10465441SEvalZero	stmfd	sp!, {r2}		@ push old task's pc
253*10465441SEvalZero	stmfd	sp!, {r4-r12,lr}@ push old task's lr,r12-r4
254*10465441SEvalZero	mov	r4,  r1				@ Special optimised code below
255*10465441SEvalZero	mov	r5,  r3
256*10465441SEvalZero	ldmfd	r4!, {r0-r3}
257*10465441SEvalZero	stmfd	sp!, {r0-r3}	@ push old task's r3-r0
258*10465441SEvalZero	stmfd	sp!, {r5}		@ push old task's psr
259*10465441SEvalZero	mrs	r4,  spsr
260*10465441SEvalZero	stmfd	sp!, {r4}		@ push old task's spsr
261*10465441SEvalZero
262*10465441SEvalZero	ldr	r4,  =rt_interrupt_from_thread
263*10465441SEvalZero	ldr	r5,  [r4]
264*10465441SEvalZero	str	sp,  [r5]			@ store sp in preempted tasks's TCB
265*10465441SEvalZero
266*10465441SEvalZero	ldr	r6,  =rt_interrupt_to_thread
267*10465441SEvalZero	ldr	r6,  [r6]
268*10465441SEvalZero	ldr	sp,  [r6]			@ get new task's stack pointer
269*10465441SEvalZero
270*10465441SEvalZero	ldmfd	sp!, {r4}		@ pop new task's spsr
271*10465441SEvalZero	msr	SPSR_cxsf, r4
272*10465441SEvalZero	ldmfd	sp!, {r4}		@ pop new task's psr
273*10465441SEvalZero	msr	CPSR_cxsf, r4
274*10465441SEvalZero
275*10465441SEvalZero	ldmfd	sp!, {r0-r12,lr,pc}	@ pop new task's r0-r12,lr & pc
276