1 | /*****************************************************************************
|
2 | * Copyright (c) 2001, 2002 Rowley Associates Limited. *
|
3 | * *
|
4 | * This file may be distributed under the terms of the License Agreement *
|
5 | * provided with this software. *
|
6 | * *
|
7 | * THIS FILE IS PROVIDED AS IS WITH NO WARRANTY OF ANY KIND, INCLUDING THE *
|
8 | * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. *
|
9 | *****************************************************************************/
|
10 |
|
11 | /*****************************************************************************
|
12 | * Preprocessor Definitions
|
13 | * ------------------------
|
14 | *
|
15 | * VECTORED_IRQ_INTERRUPTS
|
16 | *
|
17 | * Enable vectored IRQ interrupts. If defined, the PC register will be loaded
|
18 | * with the contents of the VICVectAddr register on an IRQ exception.
|
19 | *
|
20 | * STARTUP_FROM_RESET
|
21 | *
|
22 | * If defined, the program will startup from power-on/reset. If not defined
|
23 | * the program will just loop endlessly from power-on/reset.
|
24 | *
|
25 | * This definition is not defined by default on this target because the
|
26 | * debugger is unable to reset this target and maintain control of it over the
|
27 | * JTAG interface. The advantage of doing this is that it allows the debugger
|
28 | * to reset the CPU and run programs from a known reset CPU state on each run.
|
29 | * It also acts as a safety net if you accidently download a program in FLASH
|
30 | * that crashes and prevents the debugger from taking control over JTAG
|
31 | * rendering the target unusable over JTAG. The obvious disadvantage of doing
|
32 | * this is that your application will not startup without the debugger.
|
33 | *
|
34 | * We advise that on this target you keep STARTUP_FROM_RESET undefined whilst
|
35 | * you are developing and only define STARTUP_FROM_RESET when development is
|
36 | * complete.
|
37 | *
|
38 | * PLLCFG_VAL
|
39 | *
|
40 | * Override the default PLL configuration by defining PLLCFG_VAL.
|
41 | *
|
42 | * CCLKCFG_VAL
|
43 | *
|
44 | * Override the default CPU clock divider configuration by defining
|
45 | * CCLKCFG_VAL.
|
46 | *
|
47 | * NO_PLL_ENABLE
|
48 | *
|
49 | * If defined, the PLL will not be enabled.
|
50 | *
|
51 | * USBCLKCFG_VAL
|
52 | *
|
53 | * Override the default USB clock divider configuration by defining
|
54 | * USBCLKCFG_VAL.
|
55 | *
|
56 | * MAMCR_VAL & MAMTIM_VAL
|
57 | *
|
58 | * Override the default MAM configuration (fully enabled, 3 fetch cycles)
|
59 | * by defining MAMCR_VAL and MAMTIM_VAL.
|
60 | *
|
61 | * SRAM_EXCEPTIONS
|
62 | *
|
63 | * If defined, enable copying and re-mapping of interrupt vectors from User
|
64 | * FLASH to SRAM. If undefined, interrupt vectors will be mapped in User
|
65 | * FLASH.
|
66 | *
|
67 | *****************************************************************************/
|
68 |
|
69 | #include <targets/LPC2000.h>
|
70 |
|
71 | #if OSCILLATOR_CLOCK_FREQUENCY==12000000
|
72 |
|
73 | /* Fosc = 12Mhz, Fcco = 288Mhz, cclk = 57.6Mhz */
|
74 | #ifndef PLLCFG_VAL
|
75 | #define PLLCFG_VAL ((11 << PLLCFG_MSEL_BIT) | (0 << PLLCFG_NSEL_BIT))
|
76 | #endif
|
77 | #ifndef CCLKCFG_VAL
|
78 | #define CCLKCFG_VAL 4
|
79 | #endif
|
80 | #ifndef USBCLKCFG_VAL
|
81 | #define USBCLKCFG_VAL 5
|
82 | #endif
|
83 |
|
84 | #endif
|
85 |
|
86 | #ifndef MAMCR_VAL
|
87 | #define MAMCR_VAL 2
|
88 | #endif
|
89 |
|
90 | #ifndef MAMTIM_VAL
|
91 | #define MAMTIM_VAL 3
|
92 | #endif
|
93 |
|
94 | .section .vectors, "ax"
|
95 | .code 32
|
96 | .align 0
|
97 | .global _vectors
|
98 | .global reset_handler
|
99 |
|
100 | /*****************************************************************************
|
101 | * Exception Vectors *
|
102 | *****************************************************************************/
|
103 | _vectors:
|
104 | ldr pc, [pc, #reset_handler_address - . - 8] /* reset */
|
105 | ldr pc, [pc, #undef_handler_address - . - 8] /* undefined instruction */
|
106 | ldr pc, [pc, #swi_handler_address - . - 8] /* swi handler */
|
107 | ldr pc, [pc, #pabort_handler_address - . - 8] /* abort prefetch */
|
108 | ldr pc, [pc, #dabort_handler_address - . - 8] /* abort data */
|
109 | #ifdef VECTORED_IRQ_INTERRUPTS
|
110 | .word 0xB9206E58 /* boot loader checksum */
|
111 | ldr pc, [pc, #-0x120] /* irq handler */
|
112 | #else
|
113 | .word 0xB8A06F60 /* boot loader checksum */
|
114 | ldr pc, [pc, #irq_handler_address - . - 8] /* irq handler */
|
115 | #endif
|
116 | ldr pc, [pc, #fiq_handler_address - . - 8] /* fiq handler */
|
117 |
|
118 | reset_handler_address:
|
119 | #ifdef STARTUP_FROM_RESET
|
120 | .word reset_handler
|
121 | #else
|
122 | .word reset_wait
|
123 | #endif
|
124 | undef_handler_address:
|
125 | .word undef_handler
|
126 | swi_handler_address:
|
127 | .word swi_handler
|
128 | pabort_handler_address:
|
129 | .word pabort_handler
|
130 | dabort_handler_address:
|
131 | .word dabort_handler
|
132 | #ifndef VECTORED_IRQ_INTERRUPTS
|
133 | irq_handler_address:
|
134 | .word irq_handler
|
135 | #endif
|
136 | fiq_handler_address:
|
137 | .word fiq_handler
|
138 |
|
139 | .section .init, "ax"
|
140 | .code 32
|
141 | .align 0
|
142 |
|
143 | /******************************************************************************
|
144 | * *
|
145 | * Default exception handlers *
|
146 | * *
|
147 | ******************************************************************************/
|
148 | reset_handler:
|
149 | ldr r0, =SCB_BASE
|
150 |
|
151 | #if defined(PLLCFG_VAL) && !defined(NO_PLL_ENABLE)
|
152 | /* Configure PLL Multiplier/Divider */
|
153 | ldr r1, [r0, #PLLSTAT_OFFSET]
|
154 | tst r1, #PLLSTAT_PLLC
|
155 | beq 1f
|
156 |
|
157 | /* Disconnect PLL */
|
158 | ldr r1, =PLLCON_PLLE
|
159 | str r1, [r0, #PLLCON_OFFSET]
|
160 | mov r1, #0xAA
|
161 | str r1, [r0, #PLLFEED_OFFSET]
|
162 | mov r1, #0x55
|
163 | str r1, [r0, #PLLFEED_OFFSET]
|
164 | 1:
|
165 | /* Disable PLL */
|
166 | ldr r1, =0
|
167 | str r1, [r0, #PLLCON_OFFSET]
|
168 | mov r1, #0xAA
|
169 | str r1, [r0, #PLLFEED_OFFSET]
|
170 | mov r1, #0x55
|
171 | str r1, [r0, #PLLFEED_OFFSET]
|
172 |
|
173 | /* Enable main oscillator */
|
174 | ldr r1, [r0, #SCS_OFFSET]
|
175 | orr r1, r1, #SCS_OSCEN
|
176 | str r1, [r0, #SCS_OFFSET]
|
177 | 1:
|
178 | ldr r1, [r0, #SCS_OFFSET]
|
179 | tst r1, #SCS_OSCSTAT
|
180 | beq 1b
|
181 |
|
182 | /* Select main oscillator as the PLL clock source */
|
183 | ldr r1, =1
|
184 | str r1, [r0, #CLKSRCSEL_OFFSET]
|
185 |
|
186 | /* Set PLLCFG */
|
187 | ldr r1, =PLLCFG_VAL
|
188 | str r1, [r0, #PLLCFG_OFFSET]
|
189 | mov r1, #0xAA
|
190 | str r1, [r0, #PLLFEED_OFFSET]
|
191 | mov r1, #0x55
|
192 | str r1, [r0, #PLLFEED_OFFSET]
|
193 |
|
194 | /* Enable PLL */
|
195 | ldr r1, =PLLCON_PLLE
|
196 | str r1, [r0, #PLLCON_OFFSET]
|
197 | mov r1, #0xAA
|
198 | str r1, [r0, #PLLFEED_OFFSET]
|
199 | mov r1, #0x55
|
200 | str r1, [r0, #PLLFEED_OFFSET]
|
201 |
|
202 | #ifdef CCLKCFG_VAL
|
203 | /* Set the CPU clock divider */
|
204 | ldr r1, =CCLKCFG_VAL
|
205 | str r1, [r0, #CCLKCFG_OFFSET]
|
206 | #endif
|
207 |
|
208 | #ifdef USBCLKCFG_VAL
|
209 | /* Set the CPU clock divider */
|
210 | ldr r1, =USBCLKCFG_VAL
|
211 | str r1, [r0, #USBCLKCFG_OFFSET]
|
212 | #endif
|
213 |
|
214 | /* Wait for PLL to lock */
|
215 | 1:
|
216 | ldr r1, [r0, #PLLSTAT_OFFSET]
|
217 | tst r1, #PLLSTAT_PLOCK
|
218 | beq 1b
|
219 | /* PLL Locked, connect PLL as clock source */
|
220 | mov r1, #(PLLCON_PLLE | PLLCON_PLLC)
|
221 | str r1, [r0, #PLLCON_OFFSET]
|
222 | mov r1, #0xAA
|
223 | str r1, [r0, #PLLFEED_OFFSET]
|
224 | mov r1, #0x55
|
225 | str r1, [r0, #PLLFEED_OFFSET]
|
226 | /* Wait for PLL to connect */
|
227 | 1:
|
228 | ldr r1, [r0, #PLLSTAT_OFFSET]
|
229 | tst r1, #PLLSTAT_PLLC
|
230 | beq 1b
|
231 | #endif
|
232 |
|
233 | /* Initialise memory accelerator module */
|
234 | mov r1, #0
|
235 | str r1, [r0, #MAMCR_OFFSET]
|
236 | ldr r1, =MAMTIM_VAL
|
237 | str r1, [r0, #MAMTIM_OFFSET]
|
238 | ldr r1, =MAMCR_VAL
|
239 | str r1, [r0, #MAMCR_OFFSET]
|
240 |
|
241 | #if defined(SRAM_EXCEPTIONS)
|
242 | /* Copy exception vectors into SRAM */
|
243 | mov r8, #0x40000000
|
244 | ldr r9, =_vectors
|
245 | ldmia r9!, {r0-r7}
|
246 | stmia r8!, {r0-r7}
|
247 | ldmia r9!, {r0-r6}
|
248 | stmia r8!, {r0-r6}
|
249 |
|
250 | /* Re-map interrupt vectors from SRAM */
|
251 | ldr r0, =SCB_BASE
|
252 | mov r1, #2 /* User RAM Mode. Interrupt vectors are re-mapped from SRAM */
|
253 | str r1, [r0, #MEMMAP_OFFSET]
|
254 | #endif /* SRAM_EXCEPTIONS */
|
255 |
|
256 | b _start
|
257 |
|
258 | #ifndef STARTUP_FROM_RESET
|
259 | reset_wait:
|
260 | b reset_wait
|
261 | #endif
|
262 |
|
263 | /******************************************************************************
|
264 | * *
|
265 | * Default exception handlers *
|
266 | * These are declared weak symbols so they can be redefined in user code. *
|
267 | * *
|
268 | ******************************************************************************/
|
269 | undef_handler:
|
270 | b undef_handler
|
271 |
|
272 | swi_handler:
|
273 | b swi_handler
|
274 |
|
275 | pabort_handler:
|
276 | b pabort_handler
|
277 |
|
278 | dabort_handler:
|
279 | b dabort_handler
|
280 |
|
281 | fiq_handler:
|
282 | b fiq_handler
|
283 |
|
284 | irq_handler:
|
285 | b irq_handler
|
286 |
|
287 | .weak undef_handler, swi_handler, pabort_handler, dabort_handler, fiq_handler, irq_handler
|