diff options
Diffstat (limited to 'firmware/target/arm/tms320dm320/crt0.S')
-rw-r--r-- | firmware/target/arm/tms320dm320/crt0.S | 409 |
1 files changed, 293 insertions, 116 deletions
diff --git a/firmware/target/arm/tms320dm320/crt0.S b/firmware/target/arm/tms320dm320/crt0.S index 440897d67f..69bc8b1622 100644 --- a/firmware/target/arm/tms320dm320/crt0.S +++ b/firmware/target/arm/tms320dm320/crt0.S | |||
@@ -7,12 +7,7 @@ | |||
7 | * \/ \/ \/ \/ \/ | 7 | * \/ \/ \/ \/ \/ |
8 | * $Id$ | 8 | * $Id$ |
9 | * | 9 | * |
10 | * Copyright (C) 2002 by Linus Nielsen Feltzing | 10 | * Copyright (C) 2010 by Karl Kurbjun |
11 | * | ||
12 | * Arm bootloader and startup code based on startup.s from the iPodLinux loader | ||
13 | * | ||
14 | * Copyright (c) 2003, Daniel Palffy (dpalffy (at) rainstorm.org) | ||
15 | * Copyright (c) 2005, Bernard Leach <leachbj@bouncycastle.org> | ||
16 | * | 11 | * |
17 | * This program is free software; you can redistribute it and/or | 12 | * This program is free software; you can redistribute it and/or |
18 | * modify it under the terms of the GNU General Public License | 13 | * modify it under the terms of the GNU General Public License |
@@ -26,25 +21,83 @@ | |||
26 | #include "config.h" | 21 | #include "config.h" |
27 | #include "cpu.h" | 22 | #include "cpu.h" |
28 | 23 | ||
29 | .section .init.text,"ax",%progbits | 24 | #define CACHE_NONE 0 |
25 | #define CACHE_ALL 0x0C | ||
26 | #define BUFFERED 0x04 | ||
30 | 27 | ||
31 | .global start | 28 | #define LONG_VECTORS 1 |
32 | start: | ||
33 | msr cpsr, #0xd3 /* enter supervisor mode, disable IRQ/FIQ */ | ||
34 | 29 | ||
35 | #ifndef CREATIVE_ZVx | 30 | /****************************************************************************** |
36 | /* Copy exception handler code to address 0 */ | 31 | * vectors: * |
37 | ldr r2, =_vectorsstart | 32 | * This is the ARM vector table * |
38 | ldr r3, =_vectorsend | 33 | * Long call exception handlers are used for simplicity between flash * |
39 | ldr r4, =_vectorscopy | 34 | * bootloader and SDRAM main-application. These need to be copied to address * |
40 | 1: | 35 | * 0x0 at start. * |
41 | cmp r3, r2 | 36 | ******************************************************************************/ |
42 | ldrhi r5, [r4], #4 | 37 | .section .vectors,"ax" |
43 | strhi r5, [r2], #4 | 38 | .code 32 |
44 | bhi 1b | 39 | |
40 | .global _vectors | ||
41 | @entry: | ||
42 | _vectors: | ||
43 | |||
44 | #if defined(SHORT_VECTORS) /* Use relative branch vectors (64 MB limit) */ | ||
45 | b _start /* Reset Vector */ | ||
46 | b _undefined_instruction /* Undefined instruction */ | ||
47 | b _software_interrupt /* Software Vector */ | ||
48 | b _prefetch_abort /* Prefetch Abort */ | ||
49 | b _data_abort /* Data Abort */ | ||
50 | b _dead_loop /* Reserved/Unused */ | ||
51 | b irq_handler /* IRQ vector */ | ||
52 | b fiq_handler /* FIQ vector */ | ||
53 | #else | ||
54 | #if defined(LONG_VECTORS) | ||
55 | /* Load the PC with the word values stored below */ | ||
56 | ldr pc, [pc, #0x18] /* Reset */ | ||
57 | ldr pc, [pc, #0x18] /* Undefined instruction */ | ||
58 | ldr pc, [pc, #0x18] /* Software interrupt */ | ||
59 | ldr pc, [pc, #0x18] /* Prefetch Abort */ | ||
60 | ldr pc, [pc, #0x18] /* Data Abort */ | ||
61 | ldr pc, [pc, #0x18] /* Reserved/Unused */ | ||
62 | ldr pc, [pc, #0x18] /* IRQ */ | ||
63 | ldr pc, [pc, #0x18] /* FIQ */ | ||
64 | |||
65 | /* Addresses of the handlers */ | ||
66 | .word _start | ||
67 | .word _undefined_instruction | ||
68 | .word _software_interrupt | ||
69 | .word _prefetch_abort | ||
70 | .word _data_abort | ||
71 | .word _dead_loop | ||
72 | .word irq_handler | ||
73 | .word fiq_handler | ||
74 | #else | ||
75 | #error Vector type undefined | ||
76 | #endif | ||
45 | #endif | 77 | #endif |
46 | 78 | ||
47 | /* Disable data and instruction cache, high vectors (at 0xffff0000 instead of 0x00000000) */ | 79 | /****************************************************************************** |
80 | * _start: * | ||
81 | * This is the main entry point to the program * | ||
82 | ******************************************************************************/ | ||
83 | .section .init, "ax" | ||
84 | .code 32 | ||
85 | .align 0x04 | ||
86 | .global _start | ||
87 | _start: | ||
88 | /* Go into supervisor state with IRQ's disabled. | ||
89 | * This register is described in section "A2.5 Program status registers" | ||
90 | * of the "ARM Architecture Reference Manual". | ||
91 | */ | ||
92 | msr cpsr, #0xd3 | ||
93 | |||
94 | /* Disable all the fancy stuff */ | ||
95 | mov r0, #0 | ||
96 | mcr p15, 0, r0, c1, c0, 0 | ||
97 | |||
98 | /* Disable data and instruction cache, high vectors (at 0xffff0000 instead | ||
99 | * of 0x00000000) | ||
100 | */ | ||
48 | mrc p15, 0, r0, c1, c0, 0 | 101 | mrc p15, 0, r0, c1, c0, 0 |
49 | /* clear bits 13, 9:8 (--VI --RS) */ | 102 | /* clear bits 13, 9:8 (--VI --RS) */ |
50 | bic r0, r0, #0x00003300 | 103 | bic r0, r0, #0x00003300 |
@@ -54,112 +107,236 @@ start: | |||
54 | orr r0, r0, #0x00000002 | 107 | orr r0, r0, #0x00000002 |
55 | mcr p15, 0, r0, c1, c0, 0 | 108 | mcr p15, 0, r0, c1, c0, 0 |
56 | 109 | ||
57 | #if !defined(STUB) | 110 | /* Add a few cycles of delay before continuing due to system requirements */ |
58 | /* Zero out IBSS */ | 111 | mov r0, #0x20 |
59 | ldr r2, =_iedata | 112 | bl _delay_cycles |
60 | ldr r3, =_iend | 113 | |
61 | mov r4, #0 | 114 | #if defined(BOOTLOADER) |
62 | 1: | 115 | bl _init_board |
63 | cmp r3, r2 | 116 | #endif |
64 | strhi r4, [r2], #4 | 117 | |
65 | bhi 1b | 118 | /* Copy exception handler code to address 0 */ |
66 | 119 | ldr r0, =_vectorscopy | |
67 | #ifndef CREATIVE_ZVx | 120 | ldr r1, =_vectorsstart |
68 | /* Copy the IRAM */ | 121 | ldr r2, =_vectorsend |
69 | ldr r2, =_iramcopy | 122 | bl _copy_section |
70 | ldr r3, =_iramstart | 123 | |
71 | ldr r4, =_iramend | 124 | /* Add some delay time to make sure JTAG can be accessed cleanly */ |
72 | 1: | 125 | mov r0, #0x100000 |
73 | cmp r4, r3 | 126 | bl _delay_cycles |
74 | ldrhi r5, [r2], #4 | 127 | |
75 | strhi r5, [r3], #4 | 128 | #if defined(BOOTLOADER) |
76 | bhi 1b | 129 | /* Copy the DRAM */ |
130 | ldr r0, =_dramcopy | ||
131 | ldr r1, =_dramstart | ||
132 | ldr r2, =_dramend | ||
133 | bl _copy_section | ||
77 | #endif | 134 | #endif |
78 | #endif /* !STUB */ | 135 | |
79 | 136 | /* Zero out the IBSS */ | |
80 | 137 | mov r0, #0 | |
81 | /* Initialise bss section to zero */ | 138 | ldr r1, =_ibss_start |
82 | ldr r2, =_edata | 139 | ldr r2, =_ibss_end |
83 | ldr r3, =_end | 140 | bl _init_section |
84 | mov r4, #0 | 141 | |
85 | bsszero: | 142 | /* Copy the IRAM */ |
86 | cmp r3, r2 | 143 | ldr r0, =_iramcopy |
87 | strhi r4, [r2], #4 | 144 | ldr r1, =_iramstart |
88 | bhi bsszero | 145 | ldr r2, =_iramend |
89 | 146 | bl _copy_section | |
90 | /* Set up some stack and munge it with 0xdeadbeef */ | 147 | |
91 | ldr sp, =stackend | 148 | /* Zero out the BSS */ |
92 | mov r3, sp | 149 | mov r0, #0 |
93 | ldr r2, =stackbegin | 150 | ldr r1, =_bss_start |
94 | ldr r4, =0xdeadbeef | 151 | ldr r2, =_bss_end |
95 | stackmunge: | 152 | bl _init_section |
96 | cmp r3, r2 | 153 | |
97 | strhi r4, [r2], #4 | 154 | /* Initialize fiq stack */ |
98 | bhi stackmunge | 155 | ldr r0, =0xDEADBEEF |
99 | 156 | ldr r1, =_fiq_stack_end /* Stack counts backwards, so end is first*/ | |
100 | /* Set up stack for IRQ mode */ | 157 | ldr r2, =_fiq_stack_start |
101 | msr cpsr_c, #0xd2 /* IRQ disabled, FIQ enabled */ | 158 | bl _init_section |
102 | ldr sp, =irq_stack | 159 | |
103 | /* Set up stack for FIQ mode */ | 160 | msr cpsr_c, #0xd1 /* Go into fiq state */ |
104 | msr cpsr_c, #0xd1 /* IRQ/FIQ disabled */ | 161 | ldr sp, =_fiq_stack_start /* set the fiq stack pointer */ |
105 | ldr sp, =fiq_stack | 162 | |
106 | 163 | /* Initialize irq stack */ | |
107 | /* Let abort and undefined modes use IRQ stack */ | 164 | ldr r0, =0xDEADBEEF /* Can be taken out; left for clarity */ |
108 | msr cpsr_c, #0xd7 /* IRQ/FIQ disabled */ | 165 | ldr r1, =_irq_stack_end /* Stack counts backwards, so end is first*/ |
109 | ldr sp, =irq_stack | 166 | ldr r2, =_irq_stack_start |
110 | msr cpsr_c, #0xdb /* IRQ/FIQ disabled */ | 167 | bl _init_section |
111 | ldr sp, =irq_stack | 168 | |
112 | 169 | msr cpsr_c, #0xd2 /* Go into irq state */ | |
113 | /* Switch to supervisor mode (no IRQ) */ | 170 | ldr sp, =_irq_stack_start /* set the irq stack pointer */ |
114 | msr cpsr_c, #0xd3 | 171 | |
115 | ldr sp, =stackend | 172 | /* This should not be needed, but set the stack location for abort and |
116 | 173 | * undefined to at least a known stack location (IRQ) | |
117 | start_loc: | 174 | */ |
118 | bl main | 175 | msr cpsr_c, #0xd7 /* Go into abort state */ |
119 | /* main() should never return */ | 176 | ldr sp, =_irq_stack_start /* set the stack pointer */ |
120 | 177 | ||
121 | /* Exception handlers. Will be copied to address 0 after memory remapping */ | 178 | msr cpsr_c, #0xdb /* Go into undefined state */ |
122 | .section .vectors,"aw" | 179 | ldr sp, =_irq_stack_start /* set the stack pointer */ |
123 | b start | 180 | |
124 | b undef_instr_handler | 181 | /* Initialize program stack */ |
125 | b software_int_handler | 182 | msr cpsr_c, #0xd3 /* Go into supervisor state */ |
126 | b prefetch_abort_handler | 183 | ldr r0, =0xDEADBEEF /* Can be taken out; left for clarity */ |
127 | b data_abort_handler | 184 | ldr r1, =_pro_stack_end /* Stack counts backwards, so end is first*/ |
128 | b reserved_handler | 185 | ldr r2, =_pro_stack_start |
129 | b irq_handler | 186 | bl _init_section |
130 | b fiq_handler | 187 | |
131 | 188 | ldr sp, =_pro_stack_start /* set the supervisor stack pointer */ | |
132 | .text | 189 | |
133 | 190 | /* MMU initialization */ | |
134 | /* All illegal exceptions call into UIE with exception address as first | 191 | bl ttb_init |
135 | parameter. This is calculated differently depending on which exception | 192 | |
136 | we're in. Second parameter is exception number, used for a string lookup | 193 | /* Make sure everything is mapped on itself */ |
137 | in UIE. | 194 | ldr r0, =0x0 |
195 | ldr r1, =0x0 | ||
196 | ldr r2, =0x1000 | ||
197 | mov r3, #CACHE_NONE | ||
198 | bl map_section | ||
199 | |||
200 | /* Enable caching for FLASH */ | ||
201 | ldr r0, =_flash_start | ||
202 | ldr r1, =_flash_start | ||
203 | ldr r2, =_flash_sizem | ||
204 | mov r3, #CACHE_ALL | ||
205 | bl map_section | ||
206 | |||
207 | /* Enable caching for RAM */ | ||
208 | ldr r0, =_sdram_start | ||
209 | ldr r1, =_sdram_start | ||
210 | ldr r2, =_sdram_sizem | ||
211 | mov r3, #CACHE_ALL | ||
212 | bl map_section | ||
213 | |||
214 | bl enable_mmu | ||
215 | |||
216 | /* Initial setup is complete, go into main */ | ||
217 | ldr pc, =main | ||
218 | |||
219 | /* If main returns go into an infinite loop */ | ||
220 | b _dead_loop | ||
221 | |||
222 | /* Constants go here (from _start - .ltorg): */ | ||
223 | .ltorg | ||
224 | |||
225 | /****************************************************************************** | ||
226 | * _init_section: * | ||
227 | * This function initializes a section with the 32-bit value specified. * | ||
228 | ******************************************************************************/ | ||
229 | .section .init, "ax" | ||
230 | .code 32 | ||
231 | .align 0x04 | ||
232 | .global _init_section | ||
233 | .type _init_section, %function | ||
234 | /* r0 = init value | ||
235 | * r1 = start location | ||
236 | * r2 = end location | ||
237 | */ | ||
238 | |||
239 | /* This function will not run if end is less than or equal to start */ | ||
240 | _init_section: | ||
241 | cmp r2, r1 | ||
242 | strhi r0, [r1], #4 /* store and increment start location */ | ||
243 | bhi _init_section | ||
244 | bx lr | ||
245 | .ltorg | ||
246 | .size _init_section, .-_init_section | ||
247 | |||
248 | /****************************************************************************** | ||
249 | * _copy_section: * | ||
250 | * This function copies a section to a new location * | ||
251 | ******************************************************************************/ | ||
252 | .section .init, "ax" | ||
253 | .code 32 | ||
254 | .align 0x04 | ||
255 | .global _copy_section | ||
256 | .type _copy_section, %function | ||
257 | /* r0 = source address | ||
258 | * r1 = destination start address | ||
259 | * r2 = destination end address | ||
260 | * | ||
261 | * r3 is a scratch register | ||
138 | */ | 262 | */ |
139 | undef_instr_handler: | 263 | |
264 | _copy_section: | ||
265 | cmp r2, r1 | ||
266 | ldrhi r3, [r0], #4 | ||
267 | strhi r3, [r1], #4 | ||
268 | bhi _copy_section | ||
269 | bx lr | ||
270 | .ltorg | ||
271 | .size _copy_section, .-_copy_section | ||
272 | |||
273 | /****************************************************************************** | ||
274 | * _delay_cycles: * | ||
275 | * This function delays for the specified number of cycles * | ||
276 | ******************************************************************************/ | ||
277 | .section .init, "ax" | ||
278 | .code 32 | ||
279 | .align 0x04 | ||
280 | .global _delay_cycles | ||
281 | .type _delay_cycles, %function | ||
282 | /* r0 = number of cycles to delay */ | ||
283 | |||
284 | /* If r0 is zero it will be the maximum length delay */ | ||
285 | _delay_cycles: | ||
286 | subs r0, r0, #1 | ||
287 | bne _delay_cycles | ||
288 | bx lr | ||
289 | .ltorg | ||
290 | .size _delay_cycles, .-_delay_cycles | ||
291 | |||
292 | /****************************************************************************** | ||
293 | * Unused exception vectors. These call the UIE function. * | ||
294 | * Arguements are: * | ||
295 | * r0: PC of exception * | ||
296 | * r1: Exception number. * | ||
297 | * Exception numbers are as defined: * | ||
298 | * 0: Undefined Instruction * | ||
299 | * 1: Prefetch Abort * | ||
300 | * 2: Data Abort * | ||
301 | * The exceptions return operations are documented in section A2.6 of the * | ||
302 | * ARM Architecture Reference Manual. * | ||
303 | ******************************************************************************/ | ||
304 | |||
305 | /* A2.6.3: Undefined Instruction Exception - LR=PC of next instruction */ | ||
306 | _undefined_instruction: | ||
140 | sub r0, lr, #4 | 307 | sub r0, lr, #4 |
141 | mov r1, #0 | 308 | mov r1, #0 |
142 | b UIE | 309 | bl UIE |
143 | 310 | ||
144 | /* We run supervisor mode most of the time, and should never see a software | 311 | /* A2.6.4: Software Interrupt exception - These should not happen in Rockbox, |
145 | exception being thrown. Perhaps make it illegal and call UIE? | 312 | * but for now leave this as a placeholder and continue with the program. |
313 | * LR=PC of next instruction. | ||
146 | */ | 314 | */ |
147 | software_int_handler: | 315 | _software_interrupt: |
148 | reserved_handler: | 316 | mov pc, lr |
149 | movs pc, lr | ||
150 | 317 | ||
151 | prefetch_abort_handler: | 318 | /* A2.6.5 Prefetch Abort - This is also the BKPT instruction since this is a |
319 | * v5 target. Pass it on to UIE since it is not currently used. | ||
320 | */ | ||
321 | _prefetch_abort: | ||
152 | sub r0, lr, #4 | 322 | sub r0, lr, #4 |
153 | mov r1, #1 | 323 | mov r1, #1 |
154 | b UIE | 324 | bl UIE |
155 | 325 | ||
156 | data_abort_handler: | 326 | /* A2.6.6 Data Abort - There was a memory abort, can return after fixing cause |
327 | * with the LR address. | ||
328 | */ | ||
329 | _data_abort: | ||
157 | sub r0, lr, #8 | 330 | sub r0, lr, #8 |
158 | mov r1, #2 | 331 | mov r1, #2 |
159 | b UIE | 332 | bl UIE |
160 | 333 | ||
161 | #ifdef STUB | 334 | /****************************************************************************** |
162 | UIE: | 335 | * _dead_loop: Something really unexpected happened (like a reserved * |
163 | b UIE | 336 | * exception). Just hang. * |
164 | #endif | 337 | ******************************************************************************/ |
338 | _dead_loop: | ||
339 | b _dead_loop | ||
340 | |||
341 | .ltorg | ||
165 | 342 | ||