1 ;-----------------------------------------------------------------------------
\r
2 ; This file contains the startup code used by the ICCARM C compiler.
\r
4 ; The modules in this file are included in the libraries, and may be replaced
\r
5 ; by any user-defined modules that define the PUBLIC symbol _program_start or
\r
6 ; a user defined start symbol.
\r
7 ; To override the cstartup defined in the library, simply add your modified
\r
8 ; version to the workbench project.
\r
10 ; All code in the modules (except ?RESET) will be placed in the ICODE segment.
\r
14 ;-----------------------------------------------------------------------------
\r
17 ; Naming covention of labels in this file:
\r
19 ; ?xxx - External labels only accessed from assembler.
\r
20 ; __xxx - External labels accessed from or defined in C.
\r
21 ; xxx - Labels local to one module (note: this file contains
\r
23 ; main - The starting point of the user program.
\r
26 ;---------------------------------------------------------------
\r
27 ; Macros and definitions for the whole file
\r
28 ;---------------------------------------------------------------
\r
31 ; --- Standard definitions of mode bits and interrupt (I & F) flags in PSRs
\r
35 Mode_USR DEFINE 0x10
\r
36 Mode_FIQ DEFINE 0x11
\r
37 Mode_IRQ DEFINE 0x12
\r
38 Mode_SVC DEFINE 0x13
\r
39 Mode_ABT DEFINE 0x17
\r
40 Mode_UNDEF DEFINE 0x1B
\r
41 Mode_SYS DEFINE 0x1F ; available on ARM Arch 4 and later
\r
43 I_Bit DEFINE 0x80 ; when I bit is set, IRQ is disabled
\r
44 F_Bit DEFINE 0x40 ; when F bit is set, FIQ is disabled
\r
47 ; --- System memory locations
\r
49 RAM_Base DEFINE 0x20000000
\r
50 RAM_Limit DEFINE 0x20010000
\r
51 SRAM_Base DEFINE 0x60000000
\r
53 SVC_Stack DEFINE RAM_Limit ; 512 byte SVC stack at
\r
54 ; top of memory - used by kernel.
\r
55 IRQ_Stack DEFINE SVC_Stack-512 ; followed by IRQ stack
\r
56 USR_Stack DEFINE IRQ_Stack-512 ; followed by USR stack. Tasks run in
\r
57 ; system mode but task stacks are allocated
\r
58 ; when the task is created.
\r
59 FIQ_Stack DEFINE USR_Stack-8 ; followed by FIQ stack
\r
60 ABT_Stack DEFINE FIQ_Stack-8 ; followed by ABT stack
\r
61 UNDEF_Stack DEFINE ABT_Stack-8 ; followed by UNDEF stack
\r
63 EIC_Base_addr DEFINE 0xFFFFF800 ; EIC base address
\r
64 ICR_off_addr DEFINE 0x00 ; Interrupt Control register offset
\r
65 CIPR_off_addr DEFINE 0x08 ; Current Interrupt Priority Register offset
\r
66 IVR_off_addr DEFINE 0x18 ; Interrupt Vector Register offset
\r
67 FIR_off_addr DEFINE 0x1C ; Fast Interrupt Register offset
\r
68 IER_off_addr DEFINE 0x20 ; Interrupt Enable Register offset
\r
69 IPR_off_addr DEFINE 0x40 ; Interrupt Pending Bit Register offset
\r
70 SIR0_off_addr DEFINE 0x60 ; Source Interrupt Register 0
\r
72 EMI_Base_addr DEFINE 0x6C000000 ; EMI base address
\r
73 BCON0_off_addr DEFINE 0x00 ; Bank 0 configuration register offset
\r
74 BCON1_off_addr DEFINE 0x04 ; Bank 1 configuration register offset
\r
75 BCON2_off_addr DEFINE 0x08 ; Bank 2 configuration register offset
\r
76 BCON3_off_addr DEFINE 0x0C ; Bank 3 configuration register offset
\r
78 GPIO2_Base_addr DEFINE 0xE0005000 ; GPIO2 base address
\r
79 PC0_off_addr DEFINE 0x00 ; Port Configuration Register 0 offset
\r
80 PC1_off_addr DEFINE 0x04 ; Port Configuration Register 1 offset
\r
81 PC2_off_addr DEFINE 0x08 ; Port Configuration Register 2 offset
\r
82 PD_off_addr DEFINE 0x0C ; Port Data Register offset
\r
84 CPM_Base_addr DEFINE 0xA0000040 ; CPM Base Address
\r
85 BOOTCONF_off_addr DEFINE 0x10 ; CPM - Boot Configuration Register
\r
86 FLASH_mask DEFINE 0x0000 ; to remap FLASH at 0x0
\r
87 RAM_mask DEFINE 0x0002 ; to remap RAM at 0x0
\r
88 EXTMEM_mask DEFINE 0x0003 ; to remap EXTMEM at 0x0
\r
90 ;---------------------------------------------------------------
\r
93 ; Normally, segment INTVEC is linked at address 0.
\r
94 ; For debugging purposes, INTVEC may be placed at other
\r
96 ; A debugger that honors the entry point will start the
\r
97 ; program in a normal way even if INTVEC is not at address 0.
\r
98 ;---------------------------------------------------------------
\r
101 COMMON INTVEC:CODE:NOROOT(2)
\r
102 PUBLIC __program_start
\r
104 CODE32 ; Always ARM mode after reset
\r
107 ldr pc,=?cstartup ; Absolute jump can reach 4 GByte
\r
108 b ?cstartup ; Relative branch allows remap, limited to 32 MByte
\r
114 ;---------------------------------------------------------------
\r
116 ;---------------------------------------------------------------
\r
119 ; RSEG IRQ_STACK:DATA(2)
\r
120 ; RSEG SVC_STACK:DATA:NOROOT(2)
\r
121 ; RSEG CSTACK:DATA(2)
\r
122 RSEG ICODE:CODE:NOROOT(2)
\r
133 NOP ; Wait for OSC stabilization
\r
144 /* Setup a stack for each mode - note that this only sets up a usable stack
\r
145 for system/user, SWI and IRQ modes. Also each mode is setup with
\r
146 interrupts initially disabled. */
\r
147 msr CPSR_c, #Mode_UNDEF|I_Bit|F_Bit /* Undefined Instruction Mode */
\r
148 LDR SP, =UNDEF_Stack
\r
150 msr CPSR_c, #Mode_ABT|I_Bit|F_Bit /* Abort Mode */
\r
153 msr CPSR_c, #Mode_FIQ|I_Bit|F_Bit /* FIQ Mode */
\r
156 msr CPSR_c, #Mode_IRQ|I_Bit|F_Bit /* IRQ Mode */
\r
159 msr CPSR_c, #Mode_SVC|I_Bit|F_Bit /* Supervisor Mode */
\r
162 msr CPSR_c, #Mode_SYS|I_Bit|F_Bit /* System Mode */
\r
165 /* We want to start in supervisor mode. Operation will switch to system
\r
166 mode when the first task starts. */
\r
167 msr CPSR_c, #Mode_SVC|I_Bit|F_Bit
\r
173 LDR r3, =EIC_Base_addr
\r
174 LDR r4, =0x00000000
\r
175 STR r4, [r3, #ICR_off_addr] ; Disable FIQ and IRQ
\r
176 STR r4, [r3, #IER_off_addr] ; Disable all channels interrupts
\r
177 LDR r4, =0xFFFFFFFF
\r
178 STR r4, [r3, #IPR_off_addr] ; Clear all IRQ pending bits
\r
180 STR r4, [r3, #FIR_off_addr] ; Disable FIQ channels and clear FIQ pending bits
\r
181 LDR r4, =0x00000000
\r
182 STR r4, [r3, #CIPR_off_addr] ; Reset the current priority register
\r
183 LDR r4, =0xE59F0000
\r
184 STR r4, [r3, #IVR_off_addr] ; Write the LDR pc,pc,#offset instruction code in IVR[31:16]
\r
185 LDR r2, =32 ; 32 Channel to initialize
\r
186 LDR r0, =T0TIMI_Addr ; Read the address of the IRQs address table
\r
187 LDR r1, =0x00000FFF
\r
189 LDR r5, =SIR0_off_addr ; Read SIR0 address
\r
190 SUB r4,r0,#8 ; subtract 8 for prefetch
\r
191 LDR r1, =0xF7E8 ; add the offset to the 0x00000000 address(IVR address + 7E8 = 0x00000000)
\r
192 ; 0xF7E8 used to complete the LDR pc,pc,#offset opcode
\r
193 ADD r1,r4,r1 ; compute the jump offset
\r
194 EIC_INI MOV r4, r1, LSL #16 ; Left shift the result
\r
195 STR r4, [r3, r5] ; Store the result in SIRx register
\r
196 ADD r1, r1, #4 ; Next IRQ address
\r
197 ADD r5, r5, #4 ; Next SIR
\r
198 SUBS r2, r2, #1 ; Decrement the number of SIR registers to initialize
\r
199 BNE EIC_INI ; If more then continue
\r