summaryrefslogtreecommitdiff
path: root/firmware/target/arm/at91sam/lyre_proto1/crt0.S
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/arm/at91sam/lyre_proto1/crt0.S')
-rw-r--r--firmware/target/arm/at91sam/lyre_proto1/crt0.S274
1 files changed, 274 insertions, 0 deletions
diff --git a/firmware/target/arm/at91sam/lyre_proto1/crt0.S b/firmware/target/arm/at91sam/lyre_proto1/crt0.S
new file mode 100644
index 0000000000..0146a8409c
--- /dev/null
+++ b/firmware/target/arm/at91sam/lyre_proto1/crt0.S
@@ -0,0 +1,274 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 *
9 *
10 * Copyright (C) 2009 by Jorge Pinto
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "at91sam9260.h"
23
24#define DRAMORIG AT91C_EBI_SDRAM_32BIT
25#define DRAMSIZE (MEMORYSIZE * 0x100000)
26#define IRAM0ORIG AT91C_IRAM_1
27#define IRAM0SIZE AT91C_IRAM_1_SIZE
28#define TOP_OF_MEMORY (IRAM0ORIG + IRAM0SIZE)
29#define ABT_STACK_SIZE 8*3*4
30#define IRQ_STACK_SIZE 8*3*4
31
32#define ARM_MODE_ABT 0x17
33#define ARM_MODE_FIQ 0x11
34#define ARM_MODE_IRQ 0x12
35#define ARM_MODE_SVC 0x13
36
37#define I_BIT 0x80
38#define F_BIT 0x40
39
40
41/* Application startup entry point */
42.globl reset_handler
43
44.align 4
45
46.section .vectors
47.arm
48
49
50/* Exception vectors (should be a branch to be detected as a valid code
51 * by the rom) */
52_exception_vectors:
53reset_vector:
54 ldr pc, =reset_handler
55undef_vector:
56 b undef_vector /* Undefined Instruction */
57swi_vector:
58 b swi_vector /* Software Interrupt */
59pabt_vector:
60 ldr pc, =pabt_handler /* Prefetch Abort */
61dabt_vector:
62 ldr pc, =dabt_handler /* Data Abort */
63rsvd_vector:
64 b rsvd_vector /* reserved */
65irq_vector:
66 b irq_handler /* IRQ : read the AIC */
67fiq_vector:
68/*-----------------------------------------------------------------------------
69 *- Function : fiq_handler
70 *- Treatments : FIQ (Fast Interrupt) Interrupt Handler.
71 *- Called Functions :
72 *---------------------------------------------------------------------------*/
73fiq_handler:
74pabt_handler:
75dabt_handler:
76 b fiq_handler
77
78/*-----------------------------------------------------------------------------
79 *- Function : irq_handler
80 *- Treatments : IRQ Controller Interrupt Handler.
81 *- Called Functions : AIC_IVR[interrupt]
82 *---------------------------------------------------------------------------*/
83irq_handler:
84/*- Manage Exception Entry */
85/*- Adjust and save LR_irq in IRQ stack - (LR - Link Register) */
86 sub lr, lr, #4
87 stmfd sp!, {lr}
88/*- Save r0 and SPSR (Saved Program Status Register) in IRQ stack */
89 mrs r14, SPSR
90 stmfd sp!, {r0,r14}
91
92/*- Write in the IVR (Interrupt Vector Register) to support Protect Mode */
93/*- No effect in Normal Mode */
94/*- De-assert the NIRQ and clear the source in Protect Mode */
95 ldr r14, =AT91C_BASE_AIC
96 ldr r0 , [r14, #AIC_IVR]
97 str r14, [r14, #AIC_IVR]
98
99/*- Enable Interrupt and Switch in Supervisor Mode */
100 msr CPSR_c, #ARM_MODE_SVC
101
102/*- Save scratch/used registers and LR in User Stack */
103 stmfd sp!, {r1-r3, r12, r14}
104
105/*- Branch to the routine pointed by the AIC_IVR */
106 mov r14, pc
107 bx r0
108
109/*- Restore scratch/used registers and LR from User Stack */
110 ldmia sp!, {r1-r3, r12, r14}
111
112/*- Disable Interrupt and switch back in IRQ mode */
113 msr CPSR_c, #ARM_MODE_IRQ | I_BIT
114
115/*- Mark the End of Interrupt on the AIC */
116 ldr r14, =AT91C_BASE_AIC
117 str r14, [r14, #AIC_EOICR]
118
119/*- Restore SPSR_irq and r0 from IRQ stack */
120 ldmia sp!, {r0,r14}
121 msr SPSR_cxsf, r14
122
123/*- Restore adjusted LR_irq from IRQ stack directly in the PC */
124 ldmia sp!, {pc}^
125
126/*-----------------------------------------------------------------------------
127 *- Function : reset_handler
128 *- Treatments : Reset Interrupt Handler.
129 *- Called Functions : lowlevel_init
130 * main
131 *---------------------------------------------------------------------------*/
132.section .text
133reset_handler:
134/*-----------------------------------------------------------------------------
135 *- Low level Init is performed in a C function: lowlevel_init
136 *- Init Stack Pointer to a valid memory area before calling lowlevel_init
137 *
138 * Put Stack Pointer on end of IRAM 1 and branches to lowlevel_init function.
139 *---------------------------------------------------------------------------*/
140/*- Temporary stack in internal RAM for Low Level Init execution */
141_low_level_init:
142 ldr r2, =_litteral_pool_lowlevel_init /* Load r2 with the address of
143 * _litteral_pool_lowlevel_init
144 */
145 ldmia r2, {r0, r1} /* r0 = lowlevel_init and r1 = TOP_OF_MEMORY */
146 mov sp, r1 /* sp (Stack Pointer) = TOP_OF_MEMORY (end of IRAM 1) */
147 mov lr, pc /* lr (Link register) = pc (Program Counter) */
148 bx r0 /* Branch on C function (interworking) -- branch to
149 * lowlevel_init
150 */
151
152/*-----------------------------------------------------------------------------
153 *- Setup the stack for each mode
154 *
155 * Executes this code after returning from lowlevel_init fucntion.
156 * Configures Abort Mode Stack + Interrupt Mode Stack + Supervisor Mode Stack,
157 * reserves 3 blocks, one for each mode and they start at end of IRAM 1.
158 *---------------------------------------------------------------------------*/
159_stack_init:
160 ldr r2, =_litteral_pool_stack_init
161 ldmia r2, {r0, r1, r2} /* r0 = TOP_OF_MEMORY (end of IRAM 1);
162 * r1 = ABT_STACK_SIZE;
163 * r2 = IRQ_STACK_SIZE
164 */
165
166 /*- Set up Abort Mode and set ABT Mode Stack */
167 msr CPSR_c, #ARM_MODE_ABT | I_BIT | F_BIT /* Enter in Mode Abort
168 * and disable IRQ (Interrupt) and FIQ (Fast Interrupt)
169 */
170
171 mov sp, r0 /* sp (ABT Mode Stack Pointer) = TOP_OF_MEMORY
172 * (end of IRAM 1)
173 */
174
175 /* put r0 with value of the new address for next Stack */
176 sub r0, r0, r1 /* r0 = r0 - r1 --> r0 = (end of IRAM 1) -
177 * (ABT_STACK_SIZE)
178 */
179
180 /*- Set up Interrupt Mode and set IRQ Mode Stack */
181 msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT /* Enter in Mode Interrupt
182 * and disable IRQ (Interrupt) and FIQ (Fast Interrupt)
183 */
184
185 mov sp, r0 /* sp (Interrupt Mode Stack Pointer) =
186 * TOP_OF_MEMORY (end of IRAM 1) - (ABT_STACK_SIZE)
187 */
188
189 sub r0, r0, r2 /* Put on r0 the new address for next
190 * Stack (Supervisor Mode)
191 */
192
193/*- Enable interrupt & Set up Supervisor Mode and set Supervisor Mode Stack */
194 msr CPSR_c, #ARM_MODE_SVC | F_BIT
195 mov sp, r0
196
197/*-----------------------------------------------------------------------------
198 *- Segments initialization
199 *---------------------------------------------------------------------------*/
200/* Copy the vectors section code from the LMA address to the LVA address */
201_init_vectors:
202 ldr r1, =_litteral_pool_vectors /* Load r1 with the address of
203 * _litteral_pool_vectors
204 */
205 ldmia r1, {r2, r3, r4} /* r2 = DRAMORIG; r3 = _start_vectors_section;
206 * r4 = _end_vectors_section;
207 */
2081:
209 cmp r3, r4 /* Compare r3 with r4 (r3 - r4) */
210 ldrcc r5, [r2], #4 /* if (_start_vectors_section < _end_vectors_section)
211 * { r5 = [r2]; r2 = r2 + 4; }
212 */
213 strcc r5, [r3], #4 /* if (_start_vectors_section < _end_vectors_section)
214 * { [r3] = r5; r3 = r3 + 4; }
215 */
216 bcc 1b /* loop while (_start_vectors_section < _end_vectors_section) */
217
218/* Clear the bss segment */
219_init_bss:
220 ldr r2, =_litteral_pool_bss
221 ldmia r2, {r3, r4} /* r3 = _start_bss_section; r4 = _end_bss_section */
222 mov r2, #0 /* r2 = 0 */
2231:
224 cmp r3, r4 /* Compare --> (_start_bss_section - _end_bss_section) */
225 strcc r2, [r3], #4 /* if (_start_bss_section < _end_bss_section) {
226 * [r3] = 0; r3 = r3 + 4; }
227 */
228 bcc 1b /* loop while _start_bss_section < _end_bss_section */
229
230/* Set up some stack and munge it with 0xdeadbeef */
231 ldr sp, =stackend
232 mov r3, sp
233 ldr r2, =stackbegin
234 ldr r4, =0xdeadbeef
235
236stackmunge:
237 cmp r3, r2
238 strhi r4, [r2], #4
239 bhi stackmunge
240
241/*-----------------------------------------------------------------------------
242 *- Branch to the main
243 *---------------------------------------------------------------------------*/
244_branch_main:
245 ldr r0, =main
246 mov lr, pc
247 bx r0
248
249/*-----------------------------------------------------------------------------
250 *- Litteral pools
251 *---------------------------------------------------------------------------*/
252_litteral_pool_lowlevel_init:
253 .word lowlevel_init
254 .word TOP_OF_MEMORY /* Default SVC stack after power up */
255
256_litteral_pool_stack_init:
257 .word TOP_OF_MEMORY /* Top of the stack */
258 .word ABT_STACK_SIZE /* ABT stack size */
259 .word IRQ_STACK_SIZE /* IRQ stack size */
260
261_litteral_pool_bss:
262 .word _start_bss_section
263 .word _end_bss_section
264
265_litteral_pool_vectors:
266#if defined(BOOTLOADER)
267 .word (DRAMORIG + DRAMSIZE - 0x100000) /* LMA address of vectors are at
268 * end of DRAM minus 1MByte
269 */
270#else
271 .word DRAMORIG /* LMA address of vectors are at DRAMORIG */
272#endif
273 .word _start_vectors_section
274 .word _end_vectors_section