1 /* File: startup_ARMCM3.s
2 * Purpose: startup file for Cortex-M3/M4 devices. Should use with
3 * GNU Tools for ARM Embedded Processors
7 * Copyright (C) 2011 ARM Limited. All rights reserved.
8 * ARM Limited (ARM) is supplying this software for use with Cortex-M3/M4
9 * processor based microcontrollers. This file can be freely distributed
10 * within development tools that are supporting such ARM based processors.
12 * THIS SOFTWARE IS PROVIDED "AS IS". NO WARRANTIES, WHETHER EXPRESS, IMPLIED
13 * OR STATUTORY, INCLUDING, BUT NOT LIMITED TO, IMPLIED WARRANTIES OF
14 * MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE APPLY TO THIS SOFTWARE.
15 * ARM SHALL NOT, IN ANY CIRCUMSTANCES, BE LIABLE FOR SPECIAL, INCIDENTAL, OR
16 * CONSEQUENTIAL DAMAGES, FOR ANY REASON WHATSOEVER.
21 @ Standard definitions of mode bits and interrupt (I & F) flags in PSRs
29 .equ Thum_bit , 0x20 @ CPSR/SPSR Thumb bit
31 .equ GICI_BASE , 0xe8202000
32 .equ ICCIAR_OFFSET , 0x0000000C
33 .equ ICCEOIR_OFFSET , 0x00000010
34 .equ ICCHPIR_OFFSET , 0x00000018
35 .equ GICD_BASE , 0xe8201000
36 .equ ICDISER0_OFFSET , 0x00000100
37 .equ ICDICER0_OFFSET , 0x00000180
38 .equ ICDISPR0_OFFSET , 0x00000200
39 .equ ICDABR0_OFFSET , 0x00000300
40 .equ ICDIPR0_OFFSET , 0x00000400
50 .equ I_Bit , 0x80 @ when I bit is set, IRQ is disabled
51 .equ F_Bit , 0x40 @ when F bit is set, FIQ is disabled
52 .equ T_Bit , 0x20 @ when T bit is set, core is in Thumb state
54 .equ GIC_ERRATA_CHECK_1, 0x000003FE
55 .equ GIC_ERRATA_CHECK_2, 0x000003FF
57 .equ Sect_Normal , 0x00005c06 @ outer & inner wb/wa, non-shareable, executable, rw, domain 0, base addr 0
58 .equ Sect_Normal_Cod , 0x0000dc06 @ outer & inner wb/wa, non-shareable, executable, ro, domain 0, base addr 0
59 .equ Sect_Normal_RO , 0x0000dc16 @ as Sect_Normal_Cod, but not executable
60 .equ Sect_Normal_RW , 0x00005c16 @ as Sect_Normal_Cod, but writeable and not executable
61 .equ Sect_SO , 0x00000c12 @ strongly-ordered (therefore shareable), not executable, rw, domain 0, base addr 0
62 .equ Sect_Device_RO , 0x00008c12 @ device, non-shareable, non-executable, ro, domain 0, base addr 0
63 .equ Sect_Device_RW , 0x00000c12 @ as Sect_Device_RO, but writeable
64 .equ Sect_Fault , 0x00000000 @ this translation will fault (the bottom 2 bits are important, the rest are ignored)
66 .equ RAM_BASE , 0x80000000
67 .equ VRAM_BASE , 0x18000000
68 .equ SRAM_BASE , 0x2e000000
69 .equ ETHERNET , 0x1a000000
70 .equ CS3_PERIPHERAL_BASE, 0x1c000000
75 .EQU UND_Stack_Size , 0x00000100
76 .EQU SVC_Stack_Size , 0x00008000
77 .EQU ABT_Stack_Size , 0x00000100
78 .EQU FIQ_Stack_Size , 0x00000100
79 .EQU IRQ_Stack_Size , 0x00008000
80 .EQU USR_Stack_Size , 0x00004000
82 .EQU ISR_Stack_Size, (UND_Stack_Size + SVC_Stack_Size + ABT_Stack_Size + FIQ_Stack_Size + IRQ_Stack_Size)
92 .size __StackLimit, . - __StackLimit
94 .size __StackTop, . - __StackTop
99 .EQU Heap_Size , 0x00080000
107 .size __HeapBase, . - __HeapBase
109 .size __HeapLimit, . - __HeapLimit
116 .long 0xe59ff018 /* 0x00 */
117 .long 0xe59ff018 /* 0x04 */
118 .long 0xe59ff018 /* 0x08 */
119 .long 0xe59ff018 /* 0x0c */
120 .long 0xe59ff018 /* 0x10 */
121 .long 0xe59ff018 /* 0x14 */
122 .long 0xe59ff018 /* 0x18 */
123 .long 0xe59ff018 /* 0x1c */
125 .long Reset_Handler /* 0x20 */
126 .long Undef_Handler /* 0x24 */
127 .long SVC_Handler /* 0x28 */
128 .long PAbt_Handler /* 0x2c */
129 .long DAbt_Handler /* 0x30 */
130 .long 0 /* Reserved */
131 .long IRQ_Handler /* IRQ */
132 .long FIQ_Handler /* FIQ */
135 .size __isr_vector, . - __isr_vector
140 .type Reset_Handler, %function
142 @ Put any cores other than 0 to sleep
143 mrc p15, 0, r0, c0, c0, 5 @ Read MPIDR
150 @ Enable access to NEON/VFP by enabling access to Coprocessors 10 and 11.
151 @ Enables Full Access i.e. in both privileged and non privileged modes
152 mrc p15, 0, r0, c1, c0, 2 @ Read Coprocessor Access Control Register (CPACR)
153 orr r0, r0, #(0xF << 20) @ Enable access to CP 10 & 11
154 mcr p15, 0, r0, c1, c0, 2 @ Write Coprocessor Access Control Register (CPACR)
157 @ Switch on the VFP and NEON hardware
159 vmsr fpexc, r0 @ Write FPEXC register, EN bit set
161 mrc p15, 0, r0, c1, c0, 0 @ Read CP15 System Control register
162 bic r0, r0, #(0x1 << 12) @ Clear I bit 12 to disable I Cache
163 bic r0, r0, #(0x1 << 2) @ Clear C bit 2 to disable D Cache
164 bic r0, r0, #0x1 @ Clear M bit 0 to disable MMU
165 bic r0, r0, #(0x1 << 11) @ Clear Z bit 11 to disable branch prediction
166 bic r0, r0, #(0x1 << 13) @ Clear V bit 13 to disable hivecs
167 mcr p15, 0, r0, c1, c0, 0 @ Write value back to CP15 System Control register
170 @ Set Vector Base Address Register (VBAR) to point to this application's vector table
171 ldr r0, =__isr_vector
172 mcr p15, 0, r0, c12, c0, 0
174 @ Setup Stack for each exceptional mode
175 /* ldr r0, =__StackTop */
176 ldr r0, =(__StackTop - USR_Stack_Size)
178 @ Enter Undefined Instruction Mode and set its Stack Pointer
179 msr cpsr_c, #(Mode_UND | I_Bit | F_Bit)
181 sub r0, r0, #UND_Stack_Size
183 @ Enter Abort Mode and set its Stack Pointer
184 msr cpsr_c, #(Mode_ABT | I_Bit | F_Bit)
186 sub r0, r0, #ABT_Stack_Size
188 @ Enter FIQ Mode and set its Stack Pointer
189 msr cpsr_c, #(Mode_FIQ | I_Bit | F_Bit)
191 sub r0, r0, #FIQ_Stack_Size
193 @ Enter IRQ Mode and set its Stack Pointer
194 msr cpsr_c, #(Mode_IRQ | I_Bit | F_Bit)
196 sub r0, r0, #IRQ_Stack_Size
198 @ Enter Supervisor Mode and set its Stack Pointer
199 msr cpsr_c, #(Mode_SVC | I_Bit | F_Bit)
202 @ Enter System Mode to complete initialization and enter kernel
203 msr cpsr_c, #(Mode_SYS | I_Bit | F_Bit)
207 ldr r0, =RZ_A1_SetSramWriteEnable
210 .extern create_translation_table
211 bl create_translation_table
213 @ USR/SYS stack pointer will be set during kernel init
216 ldr r0, =InitMemorySubsystem
225 ldr r4, =__copy_table_start__
226 ldr r5, =__copy_table_end__
248 ldr r3, =__zero_table_start__
249 ldr r4, =__zero_table_end__
272 ldr r0, sf_boot @ dummy to keep boot loader area
280 .size Reset_Handler, . - Reset_Handler
286 .global Undef_Handler
288 .extern CUndefHandler
290 PUSH {R0-R4, R12} /* Save APCS corruptible registers to UND mode stack */
293 TST R0, #T_Bit /* Check mode */
294 MOVEQ R1, #4 /* R1 = 4 ARM mode */
295 MOVNE R1, #2 /* R1 = 2 Thumb mode */
297 LDREQ R0, [R0] /* ARM mode - R0 points to offending instruction */
300 /* Thumb instruction */
301 /* Determine if it is a 32-bit Thumb instruction */
305 BHS undef_cont /* 16-bit Thumb instruction */
307 /* 32-bit Thumb instruction. Unaligned - we need to reconstruct the offending instruction. */
309 ORR R0, R2, R0, LSL #16
311 MOV R2, LR /* Set LR to third argument */
313 /* AND R12, SP, #4 */ /* Ensure stack is 8-byte aligned */
314 MOV R3, SP /* Ensure stack is 8-byte aligned */
316 SUB SP, SP, R12 /* Adjust stack */
317 PUSH {R12, LR} /* Store stack adjustment and dummy LR */
319 /* R0 Offending instruction */
320 /* R1 =2 (Thumb) or =4 (ARM) */
323 POP {R12, LR} /* Get stack adjustment & discard dummy LR */
324 ADD SP, SP, R12 /* Unadjust stack */
326 LDR LR, [SP, #24] /* Restore stacked LR and possibly adjust for retry */
328 LDR R0, [SP, #28] /* Restore stacked SPSR */
330 POP {R0-R4, R12} /* Restore stacked APCS registers */
331 ADD SP, SP, #8 /* Adjust SP for already-restored banked registers */
339 SUB LR, LR, #4 /* Pre-adjust LR */
340 SRSDB SP!, #Mode_ABT /* Save LR and SPRS to ABT mode stack */
341 PUSH {R0-R4, R12} /* Save APCS corruptible registers to ABT mode stack */
342 MRC p15, 0, R0, c5, c0, 1 /* IFSR */
343 MRC p15, 0, R1, c6, c0, 2 /* IFAR */
345 MOV R2, LR /* Set LR to third argument */
347 /* AND R12, SP, #4 */ /* Ensure stack is 8-byte aligned */
348 MOV R3, SP /* Ensure stack is 8-byte aligned */
350 SUB SP, SP, R12 /* Adjust stack */
351 PUSH {R12, LR} /* Store stack adjustment and dummy LR */
355 POP {R12, LR} /* Get stack adjustment & discard dummy LR */
356 ADD SP, SP, R12 /* Unadjust stack */
358 POP {R0-R4, R12} /* Restore stack APCS registers */
359 RFEFD SP! /* Return from exception */
366 SUB LR, LR, #8 /* Pre-adjust LR */
367 SRSDB SP!, #Mode_ABT /* Save LR and SPRS to ABT mode stack */
368 PUSH {R0-R4, R12} /* Save APCS corruptible registers to ABT mode stack */
369 CLREX /* State of exclusive monitors unknown after taken data abort */
370 MRC p15, 0, R0, c5, c0, 0 /* DFSR */
371 MRC p15, 0, R1, c6, c0, 0 /* DFAR */
373 MOV R2, LR /* Set LR to third argument */
375 /* AND R12, SP, #4 */ /* Ensure stack is 8-byte aligned */
376 MOV R3, SP /* Ensure stack is 8-byte aligned */
378 SUB SP, SP, R12 /* Adjust stack */
379 PUSH {R12, LR} /* Store stack adjustment and dummy LR */
383 POP {R12, LR} /* Get stack adjustment & discard dummy LR */
384 ADD SP, SP, R12 /* Unadjust stack */
386 POP {R0-R4, R12} /* Restore stacked APCS registers */
387 RFEFD SP! /* Return from exception */
393 /* An FIQ might occur between the dummy read and the real read of the GIC in IRQ_Handler,
394 * so if a real FIQ Handler is implemented, this will be needed before returning:
396 /* LDR R1, =GICI_BASE
397 LDR R0, [R1, #ICCHPIR_OFFSET] ; Dummy Read ICCHPIR (GIC CPU Interface register) to avoid GIC 390 errata 801120
402 .extern SVC_Handler /* refer RTX function */
412 SUB LR, LR, #4 /* Pre-adjust LR */
413 SRSDB SP!, #Mode_SVC /* Save LR_IRQ and SPRS_IRQ to SVC mode stack */
414 CPS #Mode_SVC /* Switch to SVC mode, to avoid a nested interrupt corrupting LR on a BL */
415 PUSH {R0-R3, R12} /* Save remaining APCS corruptible registers to SVC stack */
417 /* AND R1, SP, #4 */ /* Ensure stack is 8-byte aligned */
418 MOV R3, SP /* Ensure stack is 8-byte aligned */
420 SUB SP, SP, R1 /* Adjust stack */
421 PUSH {R1, LR} /* Store stack adjustment and LR_SVC to SVC stack */
423 LDR R0, =IRQNestLevel /* Get address of nesting counter */
425 ADD R1, R1, #1 /* Increment nesting counter */
428 /* identify and acknowledge interrupt */
430 LDR R0, [R1, #ICCHPIR_OFFSET] /* Dummy Read ICCHPIR (GIC CPU Interface register) to avoid GIC 390 errata 801120 */
431 LDR R0, [R1, #ICCIAR_OFFSET] /* Read ICCIAR (GIC CPU Interface register) */
432 DSB /* Ensure that interrupt acknowledge completes before re-enabling interrupts */
434 /* Workaround GIC 390 errata 733075
435 * If the ID is not 0, then service the interrupt as normal.
436 * If the ID is 0 and active, then service interrupt ID 0 as normal.
437 * If the ID is 0 but not active, then the GIC CPU interface may be locked-up, so unlock it
438 * with a dummy write to ICDIPR0. This interrupt should be treated as spurious and not serviced.
441 LDR R3, =GIC_ERRATA_CHECK_1
444 LDR R3, =GIC_ERRATA_CHECK_2
448 BNE int_active /* If the ID is not 0, then service the interrupt */
449 LDR R3, [R2, #ICDABR0_OFFSET] /* Get the interrupt state */
451 BNE int_active /* If active, then service the interrupt */
453 LDR R3, [R2, #ICDIPR0_OFFSET] /* Not active, so unlock the CPU interface */
454 STR R3, [R2, #ICDIPR0_OFFSET] /* with a dummy write */
455 DSB /* Ensure the write completes before continuing */
456 B ret_irq /* Do not service the spurious interrupt */
460 LDR R2, =IRQCount /* Read number of IRQs */
462 CMP R0, R2 /* Clean up and return if no handler */
463 BHS ret_irq /* In a single-processor system, spurious interrupt ID 1023 does not need any special handling */
464 LDR R2, =IRQTable /* Get address of handler */
465 LDR R2, [R2, R0, LSL #2]
466 CMP R2, #0 /* Clean up and return if handler address is 0 */
470 CPSIE i /* Now safe to re-enable interrupts */
471 BLX R2 /* Call handler. R0 will be IRQ number */
472 CPSID i /* Disable interrupts again */
474 /* write EOIR (GIC CPU Interface register) */
476 DSB /* Ensure that interrupt source is cleared before we write the EOIR */
479 STR R0, [R1, #ICCEOIR_OFFSET]
481 LDR R0, =IRQNestLevel /* Get address of nesting counter */
483 SUB R1, R1, #1 /* Decrement nesting counter */
486 POP {R1, LR} /* Get stack adjustment and restore LR_SVC */
487 ADD SP, SP, R1 /* Unadjust stack */
489 POP {R0-R3,R12} /* Restore stacked APCS registers */
490 RFEFD SP! /* Return from exception */
493 /* Macro to define default handlers. Default handler
494 * will be weak symbol and just dead loops. They can be
495 * overwritten by other handlers */
496 .macro def_default_handler handler_name
500 .type \handler_name, %function
503 .size \handler_name, . - \handler_name
506 def_default_handler SVC_Handler
509 /* User Initial Stack & Heap */
519 .extern __use_two_region_memory
520 .global __user_initial_stackheap
521 __user_initial_stackheap:
524 LDR R1, =(__StackTop)
525 LDR R2, = (__HeapBase + Heap_Size)
526 LDR R3, = (__StackTop - USR_Stack_Size)