xref: /nrf52832-nimble/rt-thread/libcpu/arm/AT91SAM7X/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 * 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#ifdef __FLASH_BUILD__
100	/* copy exception vectors into internal sram */
101    /*
102	mov r8, #RAM_BASE
103	ldr r9, =_start
104	ldmia r9!, {r0-r7}
105	stmia r8!, {r0-r7}
106	ldmia r9!, {r0-r6}
107	stmia r8!, {r0-r6}
108    */
109#endif
110
111	/* setup stack for each mode */
112	ldr r0, =TOP_STACK
113
114	/* set stack */
115	/* undefined instruction mode */
116	msr cpsr_c, #MODE_UND|I_BIT|F_BIT
117	mov sp, r0
118	sub r0, r0, #UND_STACK_SIZE
119
120	/* abort mode */
121	msr cpsr_c, #MODE_ABT|I_BIT|F_BIT
122	mov sp, r0
123	sub r0, r0, #ABT_STACK_SIZE
124
125	/* FIQ mode */
126	msr cpsr_c, #MODE_FIQ|I_BIT|F_BIT
127	mov sp, r0
128	sub r0, r0, #FIQ_STACK_SIZE
129
130	/* IRQ mode */
131	msr cpsr_c, #MODE_IRQ|I_BIT|F_BIT
132	mov sp, r0
133	sub r0, r0, #IRQ_STACK_SIZE
134
135	/* supervisor mode */
136	msr cpsr_c, #MODE_SVC|I_BIT|F_BIT
137	mov sp, r0
138
139	/* remap SRAM to 0x0000 */
140	/*
141	ldr r0, =0xFFFFFF00
142	mov r1, #0x01
143	str r1, [r0]
144	*/
145
146	/* mask all IRQs */
147	ldr	r1, =0xFFFFF124
148	ldr	r0, =0XFFFFFFFF
149	str	r0, [r1]
150
151    /* copy .data to SRAM */
152    ldr     r1, =_sidata            /* .data start in image */
153    ldr     r2, =_edata             /* .data end in image   */
154    ldr     r3, =_sdata             /* sram data start      */
155data_loop:
156    ldr     r0, [r1, #0]
157    str     r0, [r3]
158
159    add     r1, r1, #4
160    add     r3, r3, #4
161
162    cmp     r3, r2                   /* check if data to clear */
163    blo     data_loop                /* loop until done        */
164
165    /* clear .bss */
166    mov     r0,#0                   /* get a zero */
167    ldr     r1,=__bss_start         /* bss start  */
168    ldr     r2,=__bss_end           /* bss end    */
169
170bss_loop:
171    cmp     r1,r2                   /* check if data to clear */
172    strlo   r0,[r1],#4              /* clear 4 bytes          */
173    blo     bss_loop                /* loop until done        */
174
175    /* call C++ constructors of global objects */
176    ldr     r0, =__ctors_start__
177    ldr     r1, =__ctors_end__
178
179ctor_loop:
180    cmp     r0, r1
181    beq     ctor_end
182    ldr     r2, [r0], #4
183    stmfd   sp!, {r0-r1}
184    mov     lr, pc
185    bx      r2
186    ldmfd   sp!, {r0-r1}
187    b       ctor_loop
188ctor_end:
189
190
191	/* start RT-Thread Kernel */
192	ldr	pc, _rtthread_startup
193
194_rtthread_startup: .word rtthread_startup
195
196/* exception handlers */
197vector_undef: b	vector_undef
198vector_swi  : b vector_swi
199vector_pabt : b vector_pabt
200vector_dabt : b vector_dabt
201vector_resv : b vector_resv
202
203.globl rt_interrupt_enter
204.globl rt_interrupt_leave
205.globl rt_thread_switch_interrupt_flag
206.globl rt_interrupt_from_thread
207.globl rt_interrupt_to_thread
208vector_irq:
209	stmfd	sp!, {r0-r12,lr}
210	bl	rt_interrupt_enter
211	bl	rt_hw_trap_irq
212	bl	rt_interrupt_leave
213
214	/*
215	 * if rt_thread_switch_interrupt_flag set, jump to
216	 * rt_hw_context_switch_interrupt_do and don't return
217	 */
218	ldr	r0, =rt_thread_switch_interrupt_flag
219	ldr	r1, [r0]
220	cmp	r1, #1
221	beq	rt_hw_context_switch_interrupt_do
222
223	ldmfd	sp!, {r0-r12,lr}
224	subs	pc, lr, #4
225
226vector_fiq:
227	stmfd	sp!,{r0-r7,lr}
228	bl 	rt_hw_trap_fiq
229	ldmfd	sp!,{r0-r7,lr}
230	subs	pc,lr,#4
231
232/*
233 * void rt_hw_context_switch_interrupt_do(rt_base_t flag)
234 */
235rt_hw_context_switch_interrupt_do:
236	mov	r1,  #0				@ clear flag
237	str	r1,  [r0]
238
239	ldmfd	sp!, {r0-r12,lr}@ reload saved registers
240	stmfd	sp!, {r0-r3}	@ save r0-r3
241	mov	r1,  sp
242	add	sp,  sp, #16		@ restore sp
243	sub	r2,  lr, #4			@ save old task's pc to r2
244
245	mrs	r3,  spsr			@ disable interrupt
246	orr	r0,  r3, #I_BIT|F_BIT
247	msr	spsr_c, r0
248
249	ldr	r0,  =.+8			@ switch to interrupted task's stack
250	movs	pc,  r0
251
252	stmfd	sp!, {r2}		@ push old task's pc
253	stmfd	sp!, {r4-r12,lr}@ push old task's lr,r12-r4
254	mov	r4,  r1				@ Special optimised code below
255	mov	r5,  r3
256	ldmfd	r4!, {r0-r3}
257	stmfd	sp!, {r0-r3}	@ push old task's r3-r0
258	stmfd	sp!, {r5}		@ push old task's psr
259	mrs	r4,  spsr
260	stmfd	sp!, {r4}		@ push old task's spsr
261
262	ldr	r4,  =rt_interrupt_from_thread
263	ldr	r5,  [r4]
264	str	sp,  [r5]			@ store sp in preempted tasks's TCB
265
266	ldr	r6,  =rt_interrupt_to_thread
267	ldr	r6,  [r6]
268	ldr	sp,  [r6]			@ get new task's stack pointer
269
270	ldmfd	sp!, {r4}		@ pop new task's spsr
271	msr	SPSR_cxsf, r4
272	ldmfd	sp!, {r4}		@ pop new task's psr
273	msr	CPSR_cxsf, r4
274
275	ldmfd	sp!, {r0-r12,lr,pc}	@ pop new task's r0-r12,lr & pc
276