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
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
|
/* File: startup_ARMCM3.s
* Purpose: startup file for Cortex-M3/M4 devices. Should use with
* GNU Tools for ARM Embedded Processors
* Version: V1.1
* Date: 17 June 2011
*
* Copyright (C) 2011 ARM Limited. All rights reserved.
* ARM Limited (ARM) is supplying this software for use with Cortex-M3/M4
* processor based microcontrollers. This file can be freely distributed
* within development tools that are supporting such ARM based processors.
*
* THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
* MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
* ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
* CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
*/
.syntax unified
.extern _start
@ Standard definitions of mode bits and interrupt (I & F) flags in PSRs
.equ USR_MODE , 0x10
.equ FIQ_MODE , 0x11
.equ IRQ_MODE , 0x12
.equ SVC_MODE , 0x13
.equ ABT_MODE , 0x17
.equ UND_MODE , 0x1b
.equ SYS_MODE , 0x1f
.equ Thum_bit , 0x20 @ CPSR/SPSR Thumb bit
.equ GICI_BASE , 0xe8202000
.equ ICCIAR_OFFSET , 0x0000000C
.equ ICCEOIR_OFFSET , 0x00000010
.equ ICCHPIR_OFFSET , 0x00000018
.equ GICD_BASE , 0xe8201000
.equ ICDISER0_OFFSET , 0x00000100
.equ ICDICER0_OFFSET , 0x00000180
.equ ICDISPR0_OFFSET , 0x00000200
.equ ICDABR0_OFFSET , 0x00000300
.equ ICDIPR0_OFFSET , 0x00000400
.equ Mode_USR , 0x10
.equ Mode_FIQ , 0x11
.equ Mode_IRQ , 0x12
.equ Mode_SVC , 0x13
.equ Mode_ABT , 0x17
.equ Mode_UND , 0x1B
.equ Mode_SYS , 0x1F
.equ I_Bit , 0x80 @ when I bit is set, IRQ is disabled
.equ F_Bit , 0x40 @ when F bit is set, FIQ is disabled
.equ T_Bit , 0x20 @ when T bit is set, core is in Thumb state
.equ GIC_ERRATA_CHECK_1, 0x000003FE
.equ GIC_ERRATA_CHECK_2, 0x000003FF
.equ Sect_Normal , 0x00005c06 @ outer & inner wb/wa, non-shareable, executable, rw, domain 0, base addr 0
.equ Sect_Normal_Cod , 0x0000dc06 @ outer & inner wb/wa, non-shareable, executable, ro, domain 0, base addr 0
.equ Sect_Normal_RO , 0x0000dc16 @ as Sect_Normal_Cod, but not executable
.equ Sect_Normal_RW , 0x00005c16 @ as Sect_Normal_Cod, but writeable and not executable
.equ Sect_SO , 0x00000c12 @ strongly-ordered (therefore shareable), not executable, rw, domain 0, base addr 0
.equ Sect_Device_RO , 0x00008c12 @ device, non-shareable, non-executable, ro, domain 0, base addr 0
.equ Sect_Device_RW , 0x00000c12 @ as Sect_Device_RO, but writeable
.equ Sect_Fault , 0x00000000 @ this translation will fault (the bottom 2 bits are important, the rest are ignored)
.equ RAM_BASE , 0x80000000
.equ VRAM_BASE , 0x18000000
.equ SRAM_BASE , 0x2e000000
.equ ETHERNET , 0x1a000000
.equ CS3_PERIPHERAL_BASE, 0x1c000000
@ Stack Configuration
.EQU UND_Stack_Size , 0x00000100
.EQU SVC_Stack_Size , 0x00008000
.EQU ABT_Stack_Size , 0x00000100
.EQU FIQ_Stack_Size , 0x00000100
.EQU IRQ_Stack_Size , 0x00008000
.EQU USR_Stack_Size , 0x00004000
.EQU ISR_Stack_Size, (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + FIQ_Stack_Size + IRQ_Stack_Size)
.section .stack
.align 3
.globl __StackTop
.globl __StackLimit
__StackLimit:
.space ISR_Stack_Size
__initial_sp:
.space USR_Stack_Size
.size __StackLimit, . - __StackLimit
__StackTop:
.size __StackTop, . - __StackTop
@ Heap Configuration
.EQU Heap_Size , 0x00080000
.section .heap
.align 3
.globl __HeapBase
.globl __HeapLimit
__HeapBase:
.space Heap_Size
.size __HeapBase, . - __HeapBase
__HeapLimit:
.size __HeapLimit, . - __HeapLimit
.section .isr_vector
.align 2
.globl __isr_vector
__isr_vector:
.long 0xe59ff018 /* 0x00 */
.long 0xe59ff018 /* 0x04 */
.long 0xe59ff018 /* 0x08 */
.long 0xe59ff018 /* 0x0c */
.long 0xe59ff018 /* 0x10 */
.long 0xe59ff018 /* 0x14 */
.long 0xe59ff018 /* 0x18 */
.long 0xe59ff018 /* 0x1c */
.long Reset_Handler /* 0x20 */
.long Undef_Handler /* 0x24 */
.long SVC_Handler /* 0x28 */
.long PAbt_Handler /* 0x2c */
.long DAbt_Handler /* 0x30 */
.long 0 /* Reserved */
.long IRQ_Handler /* IRQ */
.long FIQ_Handler /* FIQ */
.size __isr_vector, . - __isr_vector
.text
.align 2
.globl Reset_Handler
.type Reset_Handler, %function
Reset_Handler:
@ Put any cores other than 0 to sleep
mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR
ands r0, r0, #3
goToSleep:
wfine
bne goToSleep
@ Enable access to NEON/VFP by enabling access to Coprocessors 10 and 11.
@ Enables Full Access i.e. in both privileged and non privileged modes
mrc p15, 0, r0, c1, c0, 2 @ Read Coprocessor Access Control Register (CPACR)
orr r0, r0, #(0xF << 20) @ Enable access to CP 10 & 11
mcr p15, 0, r0, c1, c0, 2 @ Write Coprocessor Access Control Register (CPACR)
isb
@ Switch on the VFP and NEON hardware
mov r0, #0x40000000
vmsr fpexc, r0 @ Write FPEXC register, EN bit set
mrc p15, 0, r0, c1, c0, 0 @ Read CP15 System Control register
bic r0, r0, #(0x1 << 12) @ Clear I bit 12 to disable I Cache
bic r0, r0, #(0x1 << 2) @ Clear C bit 2 to disable D Cache
bic r0, r0, #0x1 @ Clear M bit 0 to disable MMU
bic r0, r0, #(0x1 << 11) @ Clear Z bit 11 to disable branch prediction
bic r0, r0, #(0x1 << 13) @ Clear V bit 13 to disable hivecs
mcr p15, 0, r0, c1, c0, 0 @ Write value back to CP15 System Control register
isb
@ Set Vector Base Address Register (VBAR) to point to this application's vector table
ldr r0, =__isr_vector
mcr p15, 0, r0, c12, c0, 0
@ Setup Stack for each exceptional mode
/* ldr r0, =__StackTop */
ldr r0, =(__StackTop - USR_Stack_Size)
@ Enter Undefined Instruction Mode and set its Stack Pointer
msr cpsr_c, #(Mode_UND | I_Bit | F_Bit)
mov sp, r0
sub r0, r0, #UND_Stack_Size
@ Enter Abort Mode and set its Stack Pointer
msr cpsr_c, #(Mode_ABT | I_Bit | F_Bit)
mov sp, r0
sub r0, r0, #ABT_Stack_Size
@ Enter FIQ Mode and set its Stack Pointer
msr cpsr_c, #(Mode_FIQ | I_Bit | F_Bit)
mov sp, r0
sub r0, r0, #FIQ_Stack_Size
@ Enter IRQ Mode and set its Stack Pointer
msr cpsr_c, #(Mode_IRQ | I_Bit | F_Bit)
mov sp, r0
sub r0, r0, #IRQ_Stack_Size
@ Enter Supervisor Mode and set its Stack Pointer
msr cpsr_c, #(Mode_SVC | I_Bit | F_Bit)
mov sp, r0
@ Enter System Mode to complete initialization and enter kernel
msr cpsr_c, #(Mode_SYS | I_Bit | F_Bit)
mov sp, r0
isb
ldr r0, =RZ_A1_SetSramWriteEnable
blx r0
.extern create_translation_table
bl create_translation_table
@ USR/SYS stack pointer will be set during kernel init
ldr r0, =SystemInit
blx r0
ldr r0, =InitMemorySubsystem
blx r0
@ fp_init
mov r0, #0x3000000
vmsr fpscr, r0
@ data sections copy
ldr r4, =__copy_table_start__
ldr r5, =__copy_table_end__
.L_loop0:
cmp r4, r5
bge .L_loop0_done
ldr r1, [r4]
ldr r2, [r4, #4]
ldr r3, [r4, #8]
.L_loop0_0:
subs r3, #4
ittt ge
ldrge r0, [r1, r3]
strge r0, [r2, r3]
bge .L_loop0_0
adds r4, #12
b .L_loop0
.L_loop0_done:
@ bss sections clear
ldr r3, =__zero_table_start__
ldr r4, =__zero_table_end__
.L_loop2:
cmp r3, r4
bge .L_loop2_done
ldr r1, [r3]
ldr r2, [r3, #4]
movs r0, 0
.L_loop2_0:
subs r2, #4
itt ge
strge r0, [r1, r2]
bge .L_loop2_0
adds r3, #8
b .L_loop2
.L_loop2_done:
ldr r0, =_start
bx r0
ldr r0, sf_boot @ dummy to keep boot loader area
loop_here:
b loop_here
sf_boot:
.word boot_loader
.pool
.size Reset_Handler, . - Reset_Handler
.text
Undef_Handler:
.global Undef_Handler
.func Undef_Handler
.extern CUndefHandler
SRSDB SP!, #Mode_UND
PUSH {R0-R4, R12} /* Save APCS corruptible registers to UND mode stack */
MRS R0, SPSR
TST R0, #T_Bit /* Check mode */
MOVEQ R1, #4 /* R1 = 4 ARM mode */
MOVNE R1, #2 /* R1 = 2 Thumb mode */
SUB R0, LR, R1
LDREQ R0, [R0] /* ARM mode - R0 points to offending instruction */
BEQ undef_cont
/* Thumb instruction */
/* Determine if it is a 32-bit Thumb instruction */
LDRH R0, [R0]
MOV R2, #0x1c
CMP R2, R0, LSR #11
BHS undef_cont /* 16-bit Thumb instruction */
/* 32-bit Thumb instruction. Unaligned - we need to reconstruct the offending instruction. */
LDRH R2, [LR]
ORR R0, R2, R0, LSL #16
undef_cont:
MOV R2, LR /* Set LR to third argument */
/* AND R12, SP, #4 */ /* Ensure stack is 8-byte aligned */
MOV R3, SP /* Ensure stack is 8-byte aligned */
AND R12, R3, #4
SUB SP, SP, R12 /* Adjust stack */
PUSH {R12, LR} /* Store stack adjustment and dummy LR */
/* R0 Offending instruction */
/* R1 =2 (Thumb) or =4 (ARM) */
BL CUndefHandler
POP {R12, LR} /* Get stack adjustment & discard dummy LR */
ADD SP, SP, R12 /* Unadjust stack */
LDR LR, [SP, #24] /* Restore stacked LR and possibly adjust for retry */
SUB LR, LR, R0
LDR R0, [SP, #28] /* Restore stacked SPSR */
MSR SPSR_cxsf, R0
POP {R0-R4, R12} /* Restore stacked APCS registers */
ADD SP, SP, #8 /* Adjust SP for already-restored banked registers */
MOVS PC, LR
.endfunc
PAbt_Handler:
.global PAbt_Handler
.func PAbt_Handler
.extern CPAbtHandler
SUB LR, LR, #4 /* Pre-adjust LR */
SRSDB SP!, #Mode_ABT /* Save LR and SPRS to ABT mode stack */
PUSH {R0-R4, R12} /* Save APCS corruptible registers to ABT mode stack */
MRC p15, 0, R0, c5, c0, 1 /* IFSR */
MRC p15, 0, R1, c6, c0, 2 /* IFAR */
MOV R2, LR /* Set LR to third argument */
/* AND R12, SP, #4 */ /* Ensure stack is 8-byte aligned */
MOV R3, SP /* Ensure stack is 8-byte aligned */
AND R12, R3, #4
SUB SP, SP, R12 /* Adjust stack */
PUSH {R12, LR} /* Store stack adjustment and dummy LR */
BL CPAbtHandler
POP {R12, LR} /* Get stack adjustment & discard dummy LR */
ADD SP, SP, R12 /* Unadjust stack */
POP {R0-R4, R12} /* Restore stack APCS registers */
RFEFD SP! /* Return from exception */
.endfunc
DAbt_Handler:
.global DAbt_Handler
.func DAbt_Handler
.extern CDAbtHandler
SUB LR, LR, #8 /* Pre-adjust LR */
SRSDB SP!, #Mode_ABT /* Save LR and SPRS to ABT mode stack */
PUSH {R0-R4, R12} /* Save APCS corruptible registers to ABT mode stack */
CLREX /* State of exclusive monitors unknown after taken data abort */
MRC p15, 0, R0, c5, c0, 0 /* DFSR */
MRC p15, 0, R1, c6, c0, 0 /* DFAR */
MOV R2, LR /* Set LR to third argument */
/* AND R12, SP, #4 */ /* Ensure stack is 8-byte aligned */
MOV R3, SP /* Ensure stack is 8-byte aligned */
AND R12, R3, #4
SUB SP, SP, R12 /* Adjust stack */
PUSH {R12, LR} /* Store stack adjustment and dummy LR */
BL CDAbtHandler
POP {R12, LR} /* Get stack adjustment & discard dummy LR */
ADD SP, SP, R12 /* Unadjust stack */
POP {R0-R4, R12} /* Restore stacked APCS registers */
RFEFD SP! /* Return from exception */
.endfunc
FIQ_Handler:
.global FIQ_Handler
.func FIQ_Handler
/* An FIQ might occur between the dummy read and the real read of the GIC in IRQ_Handler,
* so if a real FIQ Handler is implemented, this will be needed before returning:
*/
/* LDR R1, =GICI_BASE
LDR R0, [R1, #ICCHPIR_OFFSET] ; Dummy Read ICCHPIR (GIC CPU Interface register) to avoid GIC 390 errata 801120
*/
B .
.endfunc
.extern SVC_Handler /* refer RTX function */
IRQ_Handler:
.global IRQ_Handler
.func IRQ_Handler
.extern IRQCount
.extern IRQTable
.extern IRQNestLevel
/* prologue */
SUB LR, LR, #4 /* Pre-adjust LR */
SRSDB SP!, #Mode_SVC /* Save LR_IRQ and SPRS_IRQ to SVC mode stack */
CPS #Mode_SVC /* Switch to SVC mode, to avoid a nested interrupt corrupting LR on a BL */
PUSH {R0-R3, R12} /* Save remaining APCS corruptible registers to SVC stack */
/* AND R1, SP, #4 */ /* Ensure stack is 8-byte aligned */
MOV R3, SP /* Ensure stack is 8-byte aligned */
AND R1, R3, #4
SUB SP, SP, R1 /* Adjust stack */
PUSH {R1, LR} /* Store stack adjustment and LR_SVC to SVC stack */
LDR R0, =IRQNestLevel /* Get address of nesting counter */
LDR R1, [R0]
ADD R1, R1, #1 /* Increment nesting counter */
STR R1, [R0]
/* identify and acknowledge interrupt */
LDR R1, =GICI_BASE
LDR R0, [R1, #ICCHPIR_OFFSET] /* Dummy Read ICCHPIR (GIC CPU Interface register) to avoid GIC 390 errata 801120 */
LDR R0, [R1, #ICCIAR_OFFSET] /* Read ICCIAR (GIC CPU Interface register) */
DSB /* Ensure that interrupt acknowledge completes before re-enabling interrupts */
/* Workaround GIC 390 errata 733075
* If the ID is not 0, then service the interrupt as normal.
* If the ID is 0 and active, then service interrupt ID 0 as normal.
* If the ID is 0 but not active, then the GIC CPU interface may be locked-up, so unlock it
* with a dummy write to ICDIPR0. This interrupt should be treated as spurious and not serviced.
*/
LDR R2, =GICD_BASE
LDR R3, =GIC_ERRATA_CHECK_1
CMP R0, R3
BEQ unlock_cpu
LDR R3, =GIC_ERRATA_CHECK_2
CMP R0, R3
BEQ unlock_cpu
CMP R0, #0
BNE int_active /* If the ID is not 0, then service the interrupt */
LDR R3, [R2, #ICDABR0_OFFSET] /* Get the interrupt state */
TST R3, #1
BNE int_active /* If active, then service the interrupt */
unlock_cpu:
LDR R3, [R2, #ICDIPR0_OFFSET] /* Not active, so unlock the CPU interface */
STR R3, [R2, #ICDIPR0_OFFSET] /* with a dummy write */
DSB /* Ensure the write completes before continuing */
B ret_irq /* Do not service the spurious interrupt */
/* End workaround */
int_active:
LDR R2, =IRQCount /* Read number of IRQs */
LDR R2, [R2]
CMP R0, R2 /* Clean up and return if no handler */
BHS ret_irq /* In a single-processor system, spurious interrupt ID 1023 does not need any special handling */
LDR R2, =IRQTable /* Get address of handler */
LDR R2, [R2, R0, LSL #2]
CMP R2, #0 /* Clean up and return if handler address is 0 */
BEQ ret_irq
PUSH {R0,R1}
CPSIE i /* Now safe to re-enable interrupts */
BLX R2 /* Call handler. R0 will be IRQ number */
CPSID i /* Disable interrupts again */
/* write EOIR (GIC CPU Interface register) */
POP {R0,R1}
DSB /* Ensure that interrupt source is cleared before we write the EOIR */
ret_irq:
/* epilogue */
STR R0, [R1, #ICCEOIR_OFFSET]
LDR R0, =IRQNestLevel /* Get address of nesting counter */
LDR R1, [R0]
SUB R1, R1, #1 /* Decrement nesting counter */
STR R1, [R0]
POP {R1, LR} /* Get stack adjustment and restore LR_SVC */
ADD SP, SP, R1 /* Unadjust stack */
POP {R0-R3,R12} /* Restore stacked APCS registers */
RFEFD SP! /* Return from exception */
.endfunc
/* Macro to define default handlers. Default handler
* will be weak symbol and just dead loops. They can be
* overwritten by other handlers */
.macro def_default_handler handler_name
.align 1
.thumb_func
.weak \handler_name
.type \handler_name, %function
\handler_name :
b .
.size \handler_name, . - \handler_name
.endm
def_default_handler SVC_Handler
/* User Initial Stack & Heap */
.ifdef __MICROLIB
.global __initial_sp
.global __heap_base
.global __heap_limit
.else
.extern __use_two_region_memory
.global __user_initial_stackheap
__user_initial_stackheap:
LDR R0, = __HeapBase
LDR R1, =(__StackTop)
LDR R2, = (__HeapBase + Heap_Size)
LDR R3, = (__StackTop - USR_Stack_Size)
BX LR
.endif
.END
|