1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
|
/***************************************************************************
* __________ __ ___.
* Open \______ \ ____ ____ | | _\_ |__ _______ ___
* Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
* Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
* Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
* \/ \/ \/ \/ \/
* $Id$
*
* Copyright (C) 2010 by Karl Kurbjun
*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
* KIND, either express or implied.
*
****************************************************************************/
#include "config.h"
#include "cpu.h"
#define CACHE_NONE 0
#define CACHE_ALL 0x0C
#define BUFFERED 0x04
#define LONG_VECTORS 1
/******************************************************************************
* vectors: *
* This is the ARM vector table *
* Long call exception handlers are used for simplicity between flash *
* bootloader and SDRAM main-application. These need to be copied to address *
* 0x0 at start. *
******************************************************************************/
.section .vectors,"ax"
.code 32
.global _vectors
@entry:
_vectors:
#if defined(SHORT_VECTORS) /* Use relative branch vectors (64 MB limit) */
b _start /* Reset Vector */
b undef_instr_handler /* Undefined instruction */
b software_int_handler /* Software Vector */
b prefetch_abort_handler /* Prefetch Abort */
b data_abort_handler /* Data Abort */
b reserved_handler /* Reserved/Unused */
b irq_handler /* IRQ vector */
b fiq_handler /* FIQ vector */
#else
#if defined(LONG_VECTORS)
/* Load the PC with the word values stored below */
ldr pc, [pc, #0x18] /* Reset */
ldr pc, [pc, #0x18] /* Undefined instruction */
ldr pc, [pc, #0x18] /* Software interrupt */
ldr pc, [pc, #0x18] /* Prefetch Abort */
ldr pc, [pc, #0x18] /* Data Abort */
ldr pc, [pc, #0x18] /* Reserved/Unused */
ldr pc, [pc, #0x18] /* IRQ */
ldr pc, [pc, #0x18] /* FIQ */
/* Addresses of the handlers */
.word _start
.word undef_instr_handler
.word software_int_handler
.word prefetch_abort_handler
.word data_abort_handler
.word reserved_handler
.word irq_handler
.word fiq_handler
#else
#error Vector type undefined
#endif
#endif
/******************************************************************************
* _start: *
* This is the main entry point to the program *
******************************************************************************/
.section .init, "ax"
.code 32
.align 0x04
.global _start
_start:
/* Go into supervisor state with IRQ's disabled.
* This register is described in section "A2.5 Program status registers"
* of the "ARM Architecture Reference Manual".
*/
msr cpsr, #0xd3
/* Disable all the fancy stuff */
mov r0, #0
mcr p15, 0, r0, c1, c0, 0
/* Disable data and instruction cache, high vectors (at 0xffff0000 instead
* of 0x00000000)
*/
mrc p15, 0, r0, c1, c0, 0
/* clear bits 13, 9:8 (--VI --RS) */
bic r0, r0, #0x00003300
/* clear bits 7, 2:0 (B--- -C-M) */
bic r0, r0, #0x00000085
/* make sure bit 2 (A) Align is set */
orr r0, r0, #0x00000002
mcr p15, 0, r0, c1, c0, 0
/* Add a few cycles of delay before continuing due to system requirements */
mov r0, #0x20
bl _delay_cycles
#if defined(BOOTLOADER) && !defined(CREATIVE_ZVx)
bl _init_board
#endif
/* Copy exception handler code to address 0 */
ldr r0, =_vectorscopy
ldr r1, =_vectorsstart
ldr r2, =_vectorsend
bl _copy_section
#if !defined(SANSA_CONNECT)
/* Add some delay time to make sure JTAG can be accessed cleanly */
mov r0, #0x100000
bl _delay_cycles
#endif
#if defined(BOOTLOADER)
/* Copy the DRAM */
ldr r0, =_dramcopy
ldr r1, =_dramstart
ldr r2, =_dramend
bl _copy_section
#endif
/* Zero out the IBSS */
mov r0, #0
ldr r1, =_ibss_start
ldr r2, =_ibss_end
bl _init_section
/* Copy the IRAM */
ldr r0, =_iramcopy
ldr r1, =_iramstart
ldr r2, =_iramend
bl _copy_section
/* Zero out the BSS */
mov r0, #0
ldr r1, =_bss_start
ldr r2, =_bss_end
bl _init_section
/* Initialize fiq stack */
ldr r0, =0xDEADBEEF
ldr r1, =_fiq_stack_end /* Stack counts backwards, so end is first*/
ldr r2, =_fiq_stack_start
bl _init_section
msr cpsr_c, #0xd1 /* Go into fiq state */
ldr sp, =_fiq_stack_start /* set the fiq stack pointer */
/* Initialize irq stack */
ldr r0, =0xDEADBEEF /* Can be taken out; left for clarity */
ldr r1, =_irq_stack_end /* Stack counts backwards, so end is first*/
ldr r2, =_irq_stack_start
bl _init_section
msr cpsr_c, #0xd2 /* Go into irq state */
ldr sp, =_irq_stack_start /* set the irq stack pointer */
/* SVC, ABT, UNDEF share irq stack */
msr cpsr_c, #0xd3 /* Go into svc state */
ldr sp, =_irq_stack_start /* set svc stack pointer */
msr cpsr_c, #0xd7 /* Go into abort state */
ldr sp, =_irq_stack_start /* set the stack pointer */
msr cpsr_c, #0xdb /* Go into undefined state */
ldr sp, =_irq_stack_start /* set the stack pointer */
/* Initialize program stack */
msr cpsr_c, #0xdf /* Go into sys state */
ldr r0, =0xDEADBEEF /* Can be taken out; left for clarity */
ldr r1, =_pro_stack_end /* Stack counts backwards, so end is first*/
ldr r2, =_pro_stack_start
bl _init_section
ldr sp, =_pro_stack_start /* set the sys stack pointer */
/* MMU initialization */
bl ttb_init
/* Make sure everything is mapped on itself */
ldr r0, =0x0
ldr r1, =0x0
ldr r2, =0x1000
mov r3, #CACHE_NONE
bl map_section
/* Enable write-through caching for FLASH */
ldr r0, =_flash_start
ldr r1, =_flash_start
ldr r2, =_flash_sizem
mov r3, #(CACHE_ALL & ~BUFFERED)
bl map_section
/* Enable write-back caching for RAM */
ldr r0, =_sdram_start
ldr r1, =_sdram_start
ldr r2, =_sdram_sizem
mov r3, #CACHE_ALL
bl map_section
bl enable_mmu
/* Initial setup is complete, go into main */
ldr pc, =main
/* If main returns go into an infinite loop */
b _dead_loop
/* Constants go here (from _start - .ltorg): */
.ltorg
/******************************************************************************
* _init_section: *
* This function initializes a section with the 32-bit value specified. *
******************************************************************************/
.section .init, "ax"
.code 32
.align 0x04
.global _init_section
.type _init_section, %function
/* r0 = init value
* r1 = start location
* r2 = end location
*/
/* This function will not run if end is less than or equal to start */
_init_section:
cmp r2, r1
strhi r0, [r1], #4 /* store and increment start location */
bhi _init_section
bx lr
.ltorg
.size _init_section, .-_init_section
/******************************************************************************
* _copy_section: *
* This function copies a section to a new location *
******************************************************************************/
.section .init, "ax"
.code 32
.align 0x04
.global _copy_section
.type _copy_section, %function
/* r0 = source address
* r1 = destination start address
* r2 = destination end address
*
* r3 is a scratch register
*/
_copy_section:
cmp r2, r1
ldrhi r3, [r0], #4
strhi r3, [r1], #4
bhi _copy_section
bx lr
.ltorg
.size _copy_section, .-_copy_section
/******************************************************************************
* _delay_cycles: *
* This function delays for the specified number of cycles *
******************************************************************************/
.section .init, "ax"
.code 32
.align 0x04
.global _delay_cycles
.type _delay_cycles, %function
/* r0 = number of cycles to delay */
/* If r0 is zero it will be the maximum length delay */
_delay_cycles:
subs r0, r0, #1
bne _delay_cycles
bx lr
.ltorg
.size _delay_cycles, .-_delay_cycles
/******************************************************************************
* _dead_loop: Something really unexpected happened (like a reserved *
* exception). Just hang. *
******************************************************************************/
_dead_loop:
b _dead_loop
.ltorg
|