diff options
Diffstat (limited to 'firmware/target/arm/at91sam/lyre_proto1/crt0.S')
-rw-r--r-- | firmware/target/arm/at91sam/lyre_proto1/crt0.S | 274 |
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: | ||
53 | reset_vector: | ||
54 | ldr pc, =reset_handler | ||
55 | undef_vector: | ||
56 | b undef_vector /* Undefined Instruction */ | ||
57 | swi_vector: | ||
58 | b swi_vector /* Software Interrupt */ | ||
59 | pabt_vector: | ||
60 | ldr pc, =pabt_handler /* Prefetch Abort */ | ||
61 | dabt_vector: | ||
62 | ldr pc, =dabt_handler /* Data Abort */ | ||
63 | rsvd_vector: | ||
64 | b rsvd_vector /* reserved */ | ||
65 | irq_vector: | ||
66 | b irq_handler /* IRQ : read the AIC */ | ||
67 | fiq_vector: | ||
68 | /*----------------------------------------------------------------------------- | ||
69 | *- Function : fiq_handler | ||
70 | *- Treatments : FIQ (Fast Interrupt) Interrupt Handler. | ||
71 | *- Called Functions : | ||
72 | *---------------------------------------------------------------------------*/ | ||
73 | fiq_handler: | ||
74 | pabt_handler: | ||
75 | dabt_handler: | ||
76 | b fiq_handler | ||
77 | |||
78 | /*----------------------------------------------------------------------------- | ||
79 | *- Function : irq_handler | ||
80 | *- Treatments : IRQ Controller Interrupt Handler. | ||
81 | *- Called Functions : AIC_IVR[interrupt] | ||
82 | *---------------------------------------------------------------------------*/ | ||
83 | irq_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 | ||
133 | reset_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 | */ | ||
208 | 1: | ||
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 */ | ||
223 | 1: | ||
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 | |||
236 | stackmunge: | ||
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 | ||