1
|
/* AT91SAM7 low-level startup outines for OpenPCD / OpenPICC DFU loader
|
2
|
* (C) 2006 by Harald Welte <hwelte@hmw-consulting.de>
|
3
|
*
|
4
|
* This program is free software; you can redistribute it and/or modify
|
5
|
* it under the terms of the GNU General Public License as published by
|
6
|
* the Free Software Foundation; either version 2 of the License, or
|
7
|
* (at your option) any later version.
|
8
|
*
|
9
|
* This program is distributed in the hope that it will be useful,
|
10
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
11
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
12
|
* GNU General Public License for more details.
|
13
|
*
|
14
|
* You should have received a copy of the GNU General Public License
|
15
|
* along with this program; if not, write to the Free Software
|
16
|
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
|
17
|
*
|
18
|
*/
|
19
|
|
20
|
/*------------------------------------------------------------------------------
|
21
|
//*- ATMEL Microcontroller Software Support - ROUSSET -
|
22
|
//*------------------------------------------------------------------------------
|
23
|
//* The software is delivered "AS IS" without warranty or condition of any
|
24
|
//* kind, either express, implied or statutory. This includes without
|
25
|
//* limitation any warranty or condition with respect to merchantability or
|
26
|
//* fitness for any particular purpose, or against the infringements of
|
27
|
//* intellectual property rights of others.
|
28
|
//*-----------------------------------------------------------------------------
|
29
|
//*- File source : Cstartup.s
|
30
|
//*- Object : Generic CStartup for KEIL and GCC No Use REMAP
|
31
|
//*- Compilation flag : None
|
32
|
//*-
|
33
|
//*- 1.0 18/Oct/04 JPP : Creation
|
34
|
//*- 1.1 21/Feb/05 JPP : Set Interrupt
|
35
|
//*- 1.1 01/Apr/05 JPP : save SPSR
|
36
|
//*-----------------------------------------------------------------------------*/
|
37
|
|
38
|
/* Enable DFU by press of hardware POI_BOOTLDR switch */
|
39
|
#define CONFIG_DFU_SWITCH
|
40
|
|
41
|
/* Enable DFU by magic value in RAM and software reset */
|
42
|
#define CONFIG_DFU_MAGIC
|
43
|
|
44
|
//#define DEBUG_LL
|
45
|
|
46
|
#define PIOA_PER 0xFFFFF400
|
47
|
#define PIOA_OER 0xFFFFF410
|
48
|
#define PIOA_SODR 0xFFFFF430
|
49
|
#define PIOA_CODR 0xFFFFF434
|
50
|
#define LED1 25 /* this only works on OpenPICC, not Olimex */
|
51
|
|
52
|
#ifdef DEBUG_LL
|
53
|
/* Debugging macros for switching on/off LED1 (green) */
|
54
|
.macro led1on
|
55
|
ldr r2, =PIOA_CODR
|
56
|
mov r1, #(1 << LED1)
|
57
|
str r1, [r2]
|
58
|
.endm
|
59
|
.macro led1off
|
60
|
ldr r2, =PIOA_SODR
|
61
|
mov r1, #(1 << LED1)
|
62
|
str r1, [r2]
|
63
|
.endm
|
64
|
.macro ledinit
|
65
|
ldr r2, =PIOA_PER
|
66
|
mov r1, #(1 << LED1)
|
67
|
str r1, [r2]
|
68
|
ldr r2, =PIOA_OER
|
69
|
str r1, [r2]
|
70
|
led1off
|
71
|
.endm
|
72
|
#else
|
73
|
.macro ledinit
|
74
|
.endm
|
75
|
.macro led1on
|
76
|
.endm
|
77
|
.macro led1off
|
78
|
.endm
|
79
|
#endif
|
80
|
|
81
|
.equ IRQ_Stack_Size, 0x00000400
|
82
|
.equ FIQ_Stack_Size, 0x00000400
|
83
|
|
84
|
.equ AIC_IVR, (256)
|
85
|
.equ AIC_FVR, (260)
|
86
|
.equ AIC_EOICR, (304)
|
87
|
.equ AIC_MCR_RCR, (0xf00)
|
88
|
.equ AT91C_BASE_AIC, (0xFFFFF000)
|
89
|
.equ AT91C_PMC_PCER, (0xFFFFFC10)
|
90
|
.equ AT91C_BASE_PIOA, (0xFFFFF400)
|
91
|
.equ AT91C_ID_PIOA, (2)
|
92
|
.equ PIOA_PDSR, (0x3c)
|
93
|
#if defined(PCD)
|
94
|
.equ PIO_BOOTLDR, (1 << 27)
|
95
|
#elif defined(PICC)
|
96
|
.equ PIO_BOOTLDR, (1 << 6)
|
97
|
#elif defined(OLIMEX)
|
98
|
/* Olimex SAM7-Pxxx boards have a button B1 on PA19 that is low-active */
|
99
|
.equ PIO_BOOTLDR, (1 << 19)
|
100
|
#define CONFIG_DFU_SWITCH_INV
|
101
|
#elif defined(SIMTRACE)
|
102
|
.equ PIO_BOOTLDR, (1 << 31)
|
103
|
#define CONFIG_DFU_SWITCH_INV
|
104
|
#else
|
105
|
#error please define PIO_BOOTLDR for your board
|
106
|
#endif
|
107
|
|
108
|
|
109
|
/* #include "AT91SAM7S64_inc.h" */
|
110
|
|
111
|
/* Exception Vectors in RAM */
|
112
|
|
113
|
.text
|
114
|
.arm
|
115
|
.section .vectram, "ax"
|
116
|
|
117
|
.global _remap_call_dfu
|
118
|
.func _remap_call_dfu
|
119
|
_remap_call_dfu:
|
120
|
led1on
|
121
|
/* Remap RAM to 0x00000000 for DFU */
|
122
|
ldr r1, =AT91C_BASE_AIC
|
123
|
mov r2, #0x01
|
124
|
str r2, [r1, #AIC_MCR_RCR]
|
125
|
|
126
|
ldr r4, =dfu_main
|
127
|
bx r4
|
128
|
|
129
|
.size _remap_call_dfu, . - _remap_call_dfu
|
130
|
.endfunc
|
131
|
|
132
|
|
133
|
#;------------------------------------------------------------------------------
|
134
|
#;- Section Definition
|
135
|
#;-----------------
|
136
|
#;- Section
|
137
|
#;- .internal_ram_top Top_Stack: used by the cstartup for vector initalisation
|
138
|
#;- management defined by ld and affect from ldscript
|
139
|
#;------------------------------------------------------------------------------
|
140
|
.section .internal_ram_top
|
141
|
.code 32
|
142
|
.align 0
|
143
|
.global Top_Stack
|
144
|
Top_Stack:
|
145
|
|
146
|
/*------------------------------------------------------------------------------
|
147
|
*- Area Definition
|
148
|
*------------------------------------------------------------------------------
|
149
|
* .text is used instead of .section .text so it works with arm-aout too. */
|
150
|
.section .reset
|
151
|
.text
|
152
|
reset:
|
153
|
/*------------------------------------------------------------------------------
|
154
|
//*- Exception vectors
|
155
|
//*--------------------
|
156
|
//*- These vectors can be read at address 0 or at RAM address
|
157
|
//*- They ABSOLUTELY requires to be in relative addresssing mode in order to
|
158
|
//*- guarantee a valid jump. For the moment, all are just looping.
|
159
|
//*- If an exception occurs before remap, this would result in an infinite loop.
|
160
|
//*- To ensure if a exeption occurs before start application to infinite loop.
|
161
|
//*------------------------------------------------------------------------------*/
|
162
|
|
163
|
B InitReset /* 0x00 Reset handler */
|
164
|
undefvec:
|
165
|
B undefvec /* 0x04 Undefined Instruction */
|
166
|
swivec:
|
167
|
B swivec /* 0x08 Software Interrupt */
|
168
|
pabtvec:
|
169
|
B pabtvec /* 0x0C Prefetch Abort */
|
170
|
dabtvec:
|
171
|
b dabtvec /* 0x10 Data Abort */
|
172
|
rsvdvec:
|
173
|
b rsvdvec /* 0x14 reserved */
|
174
|
irqvec:
|
175
|
b IRQ_Handler_Entry /* 0x18 IRQ */
|
176
|
fiqvec:
|
177
|
ldr pc, [pc, #-0xF20] /* 0x1c FIQ */
|
178
|
|
179
|
dfu_state_dummy:
|
180
|
.word 0
|
181
|
|
182
|
.global IRQ_Handler_Entry
|
183
|
.func IRQ_Handler_Entry
|
184
|
|
185
|
FIQ_Handler_Entry:
|
186
|
|
187
|
/*- Switch in SVC/User Mode to allow User Stack access for C code */
|
188
|
/* because the FIQ is not yet acknowledged*/
|
189
|
|
190
|
/*- Save and r0 in FIQ_Register */
|
191
|
mov r9, r0
|
192
|
ldr r0, [r8, #AIC_FVR]
|
193
|
msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_SVC
|
194
|
|
195
|
/*- Save scratch/used registers and LR in User Stack */
|
196
|
stmfd sp!, { r1-r3, r12, lr}
|
197
|
|
198
|
/*- Branch to the routine pointed by the AIC_FVR */
|
199
|
mov r14, pc
|
200
|
bx r0
|
201
|
|
202
|
/*- Restore scratch/used registers and LR from User Stack */
|
203
|
ldmia sp!, { r1-r3, r12, lr}
|
204
|
|
205
|
/*- Leave Interrupts disabled and switch back in FIQ mode */
|
206
|
msr CPSR_c, #I_BIT | F_BIT | ARM_MODE_FIQ
|
207
|
|
208
|
/*- Restore the R0 ARM_MODE_SVC register */
|
209
|
mov r0,r9
|
210
|
|
211
|
/*- Restore the Program Counter using the LR_fiq directly in the PC */
|
212
|
subs pc, lr, #4
|
213
|
|
214
|
IRQ_Handler_Entry:
|
215
|
|
216
|
/*- Manage Exception Entry */
|
217
|
/*- Adjust and save LR_irq in IRQ stack */
|
218
|
sub lr, lr, #4
|
219
|
stmfd sp!, {lr}
|
220
|
|
221
|
/*- Save SPSR need to be saved for nested interrupt */
|
222
|
mrs r14, SPSR
|
223
|
stmfd sp!, {r14}
|
224
|
|
225
|
/*- Save and r0 in IRQ stack */
|
226
|
stmfd sp!, {r0}
|
227
|
|
228
|
/*- Write in the IVR to support Protect Mode */
|
229
|
/*- No effect in Normal Mode */
|
230
|
/*- De-assert the NIRQ and clear the source in Protect Mode */
|
231
|
ldr r14, =AT91C_BASE_AIC
|
232
|
ldr r0 , [r14, #AIC_IVR]
|
233
|
str r14, [r14, #AIC_IVR]
|
234
|
|
235
|
/*- Enable Interrupt and Switch in Supervisor Mode */
|
236
|
msr CPSR_c, #ARM_MODE_SVC
|
237
|
|
238
|
/*- Save scratch/used registers and LR in User Stack */
|
239
|
stmfd sp!, { r1-r3, r12, r14}
|
240
|
|
241
|
/*- Branch to the routine pointed by the AIC_IVR */
|
242
|
mov r14, pc
|
243
|
bx r0
|
244
|
|
245
|
/*- Restore scratch/used registers and LR from User Stack*/
|
246
|
ldmia sp!, { r1-r3, r12, r14}
|
247
|
|
248
|
/*- Disable Interrupt and switch back in IRQ mode */
|
249
|
msr CPSR_c, #I_BIT | ARM_MODE_IRQ
|
250
|
|
251
|
/*- Mark the End of Interrupt on the AIC */
|
252
|
ldr r14, =AT91C_BASE_AIC
|
253
|
str r14, [r14, #AIC_EOICR]
|
254
|
|
255
|
/*- Restore SPSR_irq and r0 from IRQ stack */
|
256
|
ldmia sp!, {r0}
|
257
|
|
258
|
/*- Restore SPSR_irq and r0 from IRQ stack */
|
259
|
ldmia sp!, {r14}
|
260
|
msr SPSR_cxsf, r14
|
261
|
|
262
|
/*- Restore adjusted LR_irq from IRQ stack directly in the PC */
|
263
|
ldmia sp!, {pc}^
|
264
|
|
265
|
.size IRQ_Handler_Entry, . - IRQ_Handler_Entry
|
266
|
.endfunc
|
267
|
.align 0
|
268
|
.RAM_TOP:
|
269
|
.word Top_Stack
|
270
|
|
271
|
.global _startup
|
272
|
.func _startup
|
273
|
InitReset:
|
274
|
/*------------------------------------------------------------------------------
|
275
|
/*- Low level Init (PMC, AIC, ? ....) by C function AT91F_LowLevelInit
|
276
|
/*------------------------------------------------------------------------------*/
|
277
|
.extern AT91F_LowLevelInit
|
278
|
/*- minumum C initialization */
|
279
|
/*- call AT91F_LowLevelInit( void) */
|
280
|
|
281
|
ldr r13,.RAM_TOP /* temporary stack in internal RAM */
|
282
|
/*--Call Low level init function in ABSOLUTE through the Interworking */
|
283
|
ldr r0,=AT91F_LowLevelInit
|
284
|
mov lr, pc
|
285
|
bx r0
|
286
|
ledinit
|
287
|
|
288
|
/*------------------------------------------------------------------------------
|
289
|
//*- Top of Stack Definition
|
290
|
//*-------------------------
|
291
|
//*- Interrupt and Supervisor Stack are located at the top of internal memory in
|
292
|
//*- order to speed the exception handling context saving and restoring.
|
293
|
//*- ARM_MODE_SVC (Application, C) Stack is located at the top of the external memory.
|
294
|
//*------------------------------------------------------------------------------*/
|
295
|
|
296
|
.EQU ARM_MODE_FIQ, 0x11
|
297
|
.EQU ARM_MODE_IRQ, 0x12
|
298
|
.EQU ARM_MODE_SVC, 0x13
|
299
|
|
300
|
.EQU I_BIT, 0x80
|
301
|
.EQU F_BIT, 0x40
|
302
|
|
303
|
|
304
|
#define AT91C_RSTC_RSR 0xFFFFFD04
|
305
|
#define AT91C_RSTC_RSTTYP_SOFTWARE (0x03 << 8)
|
306
|
#define DFU_STATE_appDETACH 1
|
307
|
|
308
|
|
309
|
/*------------------------------------------------------------------------------
|
310
|
//*- Setup the stack for each mode
|
311
|
//*-------------------------------*/
|
312
|
mov r0,r13
|
313
|
|
314
|
/*- Set up Fast Interrupt Mode and set FIQ Mode Stack*/
|
315
|
msr CPSR_c, #ARM_MODE_FIQ | I_BIT | F_BIT
|
316
|
mov r13, r0
|
317
|
sub r0, r0, #FIQ_Stack_Size
|
318
|
|
319
|
/*- Init the FIQ register*/
|
320
|
ldr r8, =AT91C_BASE_AIC
|
321
|
|
322
|
/*- Set up Interrupt Mode and set IRQ Mode Stack*/
|
323
|
msr CPSR_c, #ARM_MODE_IRQ | I_BIT | F_BIT
|
324
|
mov r13, r0 /* Init stack IRQ */
|
325
|
sub r0, r0, #IRQ_Stack_Size
|
326
|
|
327
|
/*- Set up Supervisor Mode and set Supervisor Mode Stack*/
|
328
|
msr CPSR_c, #ARM_MODE_SVC | I_BIT | F_BIT
|
329
|
mov r13, r0 /* Init stack Sup */
|
330
|
|
331
|
/* - Enable Interrupts and FIQ */
|
332
|
msr CPSR_c, #ARM_MODE_SVC
|
333
|
|
334
|
#ifdef CONFIG_DFU_MAGIC
|
335
|
ldr r1, =AT91C_RSTC_RSR
|
336
|
ldr r2, [r1]
|
337
|
#and r2, r2, AT91C_RSTC_RSTTYP
|
338
|
tst r2, #AT91C_RSTC_RSTTYP_SOFTWARE
|
339
|
beq dfu_magic_end
|
340
|
|
341
|
ldr r1, =dfu_state
|
342
|
ldr r2, [r1]
|
343
|
cmp r2, #DFU_STATE_appDETACH
|
344
|
beq _reloc_dfu
|
345
|
dfu_magic_end:
|
346
|
#endif
|
347
|
|
348
|
# Relocate DFU .data.shared section (Copy from ROM to RAM)
|
349
|
LDR R1, =_etext
|
350
|
LDR R2, =_data_shared
|
351
|
LDR R3, =_edata_shared
|
352
|
LoopRelDS: CMP R2, R3
|
353
|
LDRLO R0, [R1], #4
|
354
|
STRLO R0, [R2], #4
|
355
|
BLO LoopRelDS
|
356
|
|
357
|
/*
|
358
|
# Clear DFU .bss section (Zero init)
|
359
|
MOV R0, #0
|
360
|
LDR R1, =__bss_start__
|
361
|
LDR R2, =__bss_end__
|
362
|
LoopZI: CMP R1, R2
|
363
|
STRLO R0, [R1], #4
|
364
|
BLO LoopZI
|
365
|
*/
|
366
|
|
367
|
/* prepare c function call to main */
|
368
|
mov r0, #0 /* argc = 0 */
|
369
|
ldr lr, =exit
|
370
|
ldr r10, =0x00104000
|
371
|
|
372
|
#ifdef CONFIG_DFU_SWITCH
|
373
|
/* check whether bootloader button is pressed */
|
374
|
ldr r1, =AT91C_PMC_PCER
|
375
|
mov r2, #(1 << AT91C_ID_PIOA)
|
376
|
str r2, [r1]
|
377
|
|
378
|
ldr r1, =AT91C_BASE_PIOA
|
379
|
ldr r2, [r1, #PIOA_PDSR]
|
380
|
tst r2, #PIO_BOOTLDR
|
381
|
#ifdef CONFIG_DFU_SWITCH_INV
|
382
|
beq _reloc_dfu
|
383
|
#else
|
384
|
bne _reloc_dfu
|
385
|
#endif /* SWITCH_INV */
|
386
|
#endif
|
387
|
|
388
|
bx r10
|
389
|
|
390
|
_reloc_dfu:
|
391
|
/* Relocate DFU .data section (Copy from ROM to RAM) */
|
392
|
LDR R1, =_data_flash
|
393
|
LDR R2, =_data
|
394
|
LDR R3, =_edata
|
395
|
LoopRel: CMP R2, R3
|
396
|
LDRLO R0, [R1], #4
|
397
|
STRLO R0, [R2], #4
|
398
|
BLO LoopRel
|
399
|
|
400
|
/* Clear DFU .bss section (Zero init) */
|
401
|
MOV R0, #0
|
402
|
LDR R1, =__bss_start__
|
403
|
LDR R2, =__bss_end__
|
404
|
LoopZI: CMP R1, R2
|
405
|
STRLO R0, [R1], #4
|
406
|
BLO LoopZI
|
407
|
|
408
|
/* relocate DFU .text into RAM */
|
409
|
ldr r1, =0x00100000
|
410
|
ldr r2, =0x00200000
|
411
|
ldr r3, =_etext
|
412
|
add r3, r3, r2
|
413
|
loop_rel_t: cmp r2, r3
|
414
|
ldrlo r4, [r1], #4
|
415
|
strlo r4, [r2], #4
|
416
|
blo loop_rel_t
|
417
|
ldr r4, =_remap_call_dfu
|
418
|
bx r4
|
419
|
|
420
|
.size InitReset,.-InitReset
|
421
|
.endfunc
|
422
|
|
423
|
/* "exit" dummy to avoid sbrk write read etc. needed by the newlib default "exit" */
|
424
|
.global exit
|
425
|
.func exit
|
426
|
exit:
|
427
|
b .
|
428
|
.size exit, . - exit
|
429
|
.endfunc
|
430
|
|
431
|
/*---------------------------------------------------------------
|
432
|
//* ?EXEPTION_VECTOR
|
433
|
//* This module is only linked if needed for closing files.
|
434
|
//*---------------------------------------------------------------*/
|
435
|
.global AT91F_Default_FIQ_handler
|
436
|
.func AT91F_Default_FIQ_handler
|
437
|
AT91F_Default_FIQ_handler:
|
438
|
b AT91F_Default_FIQ_handler
|
439
|
.size AT91F_Default_FIQ_handler, . - AT91F_Default_FIQ_handler
|
440
|
.endfunc
|
441
|
|
442
|
.global AT91F_Default_IRQ_handler
|
443
|
.func AT91F_Default_IRQ_handler
|
444
|
AT91F_Default_IRQ_handler:
|
445
|
b AT91F_Default_IRQ_handler
|
446
|
.size AT91F_Default_IRQ_handler, . - AT91F_Default_IRQ_handler
|
447
|
.endfunc
|
448
|
|
449
|
.global AT91F_Spurious_handler
|
450
|
.func AT91F_Spurious_handler
|
451
|
AT91F_Spurious_handler:
|
452
|
b AT91F_Spurious_handler
|
453
|
.size AT91F_Spurious_handler, . - AT91F_Spurious_handler
|
454
|
.endfunc
|
455
|
|
456
|
|
457
|
|
458
|
.end
|
459
|
|