1 | /***********************************************************************/
|
2 | /* This file is part of the uVision/ARM development tools */
|
3 | /* Copyright KEIL ELEKTRONIK GmbH 2002-2005 */
|
4 | /***********************************************************************/
|
5 | /* */
|
6 | /* STARTUP.S: Startup file for Philips LPC2000 device series */
|
7 | /* */
|
8 | /***********************************************************************/
|
9 |
|
10 | /*
|
11 | This file has been heavily modified for the GNU-Toolchain by:
|
12 | Martin Thomas, Kaiserslautern, Germany
|
13 | <mthomas@rhrk.uni-kl.de>
|
14 | http://www.siwawi.arubi.uni-kl.de/avr_projects
|
15 |
|
16 | Most of the original Keil-code is still in this file but
|
17 | disabled by "#if 0". Some but not all of my modifications
|
18 | are marked with mthomas/mt. "Diff" against the orignal
|
19 | code to see everything I have changed.
|
20 |
|
21 | If it does not work for you: don't blame Keil or Philips.
|
22 | */
|
23 |
|
24 | /* mthomas: I have not tested if the Keil Configuration Wizard
|
25 | can still handle this file.
|
26 | */
|
27 |
|
28 | /*
|
29 | //*** <<< Use Configuration Wizard in Context Menu >>> ***
|
30 | */
|
31 |
|
32 |
|
33 | /*
|
34 | mthomas: The explanation below is still kept as a reference.
|
35 | In this port of the code the RAM/ROM_MODE and the
|
36 | remapping-setting is selescted by definitions passed
|
37 | to the preprocessor from the makefile.
|
38 |
|
39 | * The STARTUP.S code is executed after CPU Reset. This file may be
|
40 | * translated with the following SET symbols. In uVision these SET
|
41 | * symbols are entered under Options - ASM - Set.
|
42 | *
|
43 | * REMAP: when set the startup code initializes the register MEMMAP
|
44 | * which overwrites the settings of the CPU configuration pins. The
|
45 | * startup and interrupt vectors are remapped from:
|
46 | * 0x00000000 default setting (not remapped)
|
47 | * 0x80000000 when EXTMEM_MODE is used
|
48 | * 0x40000000 when RAM_MODE is used
|
49 | *
|
50 | * EXTMEM_MODE: when set the device is configured for code execution
|
51 | * from external memory starting at address 0x80000000. The startup
|
52 | * vectors are located to 0x80000000.
|
53 | *
|
54 | * RAM_MODE: when set the device is configured for code execution
|
55 | * from on-chip RAM starting at address 0x40000000. The startup
|
56 | * vectors are located to 0x40000000.
|
57 | */
|
58 |
|
59 | /* mt: Map Preprocessor definitions to assembler definitions/symbols */
|
60 |
|
61 | .set EXTMEM_MODE, 0
|
62 |
|
63 | #if defined(ROM_RUN)
|
64 | .set RAM_MODE, 0
|
65 | #if defined(VECTORS_IN_RAM)
|
66 | .set REMAP, 1
|
67 | .set VECTREMAPPED, 1
|
68 | #else
|
69 | .set REMAP, 0
|
70 | .set VECTREMAPPED, 0
|
71 | #endif
|
72 | #elif defined(RAM_RUN)
|
73 | .set RAM_MODE, 1
|
74 | .set REMAP, 1
|
75 | .set VECTREMAPPED, 0
|
76 | #else
|
77 | #error "define ROM_MODE or RAM_MODE in makefile"
|
78 | #endif
|
79 |
|
80 |
|
81 |
|
82 | .if (RAM_MODE)
|
83 | .print "RAM_MODE enabled"
|
84 | .else
|
85 | .print "ROM_MODE enabled"
|
86 | .endif
|
87 |
|
88 | .if (REMAP)
|
89 | .print "remapping enabled"
|
90 | .endif
|
91 |
|
92 | .if (VECTREMAPPED)
|
93 | .print "Vectors at start of RAM"
|
94 | .else
|
95 | .print "Vectors at start of Code"
|
96 | .endif
|
97 |
|
98 |
|
99 | // Standard definitions of Mode bits and Interrupt (I & F) flags in PSRs
|
100 |
|
101 | .set Mode_USR, 0x10
|
102 | .set Mode_FIQ, 0x11
|
103 | .set Mode_IRQ, 0x12
|
104 | .set Mode_SVC, 0x13
|
105 | .set Mode_ABT, 0x17
|
106 | .set Mode_UND, 0x1B
|
107 | .set Mode_SYS, 0x1F
|
108 |
|
109 | .set I_Bit, 0x80 /* when I bit is set, IRQ is disabled */
|
110 | .set F_Bit, 0x40 /* when F bit is set, FIQ is disabled */
|
111 |
|
112 |
|
113 | /*
|
114 | // <h> Stack Configuration (Stack Sizes in Bytes)
|
115 | // <o0> Undefined Mode <0x0-0xFFFFFFFF:4>
|
116 | // <o1> Supervisor Mode <0x0-0xFFFFFFFF:4>
|
117 | // <o2> Abort Mode <0x0-0xFFFFFFFF:4>
|
118 | // <o3> Fast Interrupt Mode <0x0-0xFFFFFFFF:4>
|
119 | // <o4> Interrupt Mode <0x0-0xFFFFFFFF:4>
|
120 | // <o5> User/System Mode <0x0-0xFFFFFFFF:4>
|
121 | // </h>
|
122 | */
|
123 | .set UND_Stack_Size, 0x00000080
|
124 | .set SVC_Stack_Size, 0x00000080
|
125 | .set ABT_Stack_Size, 0x00000080
|
126 | .set FIQ_Stack_Size, 0x00000080
|
127 | .set IRQ_Stack_Size, 0x00000200
|
128 | .set USR_Stack_Size, 0x00002000
|
129 |
|
130 | #if 0
|
131 | AREA STACK, DATA, READWRITE, ALIGN=2
|
132 | DS (USR_Stack_Size+3)&~3 ; Stack for User/System Mode
|
133 | DS (SVC_Stack_Size+3)&~3 ; Stack for Supervisor Mode
|
134 | DS (IRQ_Stack_Size+3)&~3 ; Stack for Interrupt Mode
|
135 | DS (FIQ_Stack_Size+3)&~3 ; Stack for Fast Interrupt Mode
|
136 | DS (ABT_Stack_Size+3)&~3 ; Stack for Abort Mode
|
137 | DS (UND_Stack_Size+3)&~3 ; Stack for Undefined Mode
|
138 | #endif
|
139 |
|
140 | .arm
|
141 | .section .stack, "w"
|
142 | .align 4
|
143 | .space (USR_Stack_Size+3)&~3 // Stack for User/System Mode
|
144 | .space (SVC_Stack_Size+3)&~3 // Stack for Supervisor Mode
|
145 | .space (IRQ_Stack_Size+3)&~3 // Stack for Interrupt Mode
|
146 | .space (FIQ_Stack_Size+3)&~3 // Stack for Fast Interrupt Mode
|
147 | .space (ABT_Stack_Size+3)&~3 // Stack for Abort Mode
|
148 | .space (UND_Stack_Size+3)&~3 // Stack for Undefined Mode
|
149 | Top_Stack:
|
150 |
|
151 |
|
152 | // VPBDIV definitions
|
153 | .set VPBDIV, 0xE01FC100 /* VPBDIV Address */
|
154 |
|
155 | /*
|
156 | // <e> VPBDIV Setup
|
157 | // <i> Peripheral Bus Clock Rate
|
158 | // <o1.0..1> VPBDIV: VPB Clock
|
159 | // <0=> VPB Clock = CPU Clock / 4
|
160 | // <1=> VPB Clock = CPU Clock
|
161 | // <2=> VPB Clock = CPU Clock / 2
|
162 | // <o1.4..5> XCLKDIV: XCLK Pin
|
163 | // <0=> XCLK Pin = CPU Clock / 4
|
164 | // <1=> XCLK Pin = CPU Clock
|
165 | // <2=> XCLK Pin = CPU Clock / 2
|
166 | // </e>
|
167 | */
|
168 | .set VPBDIV_SETUP, 1
|
169 | .set VPBDIV_Val, 0x00000000
|
170 |
|
171 |
|
172 | // Phase Locked Loop (PLL) definitions
|
173 | .set PLL_BASE, 0xE01FC080 /* PLL Base Address */
|
174 | .set PLLCON_OFS, 0x00 /* PLL Control Offset*/
|
175 | .set PLLCFG_OFS, 0x04 /* PLL Configuration Offset */
|
176 | .set PLLSTAT_OFS, 0x08 /* PLL Status Offset */
|
177 | .set PLLFEED_OFS, 0x0C /* PLL Feed Offset */
|
178 | .set PLLCON_PLLE, (1<<0) /* PLL Enable */
|
179 | .set PLLCON_PLLC, (1<<1) /* PLL Connect */
|
180 | .set PLLCFG_MSEL, (0x1F<<0) /* PLL Multiplier */
|
181 | .set PLLCFG_PSEL, (0x03<<5) /* PLL Divider */
|
182 | .set PLLSTAT_PLOCK, (1<<10) /* PLL Lock Status */
|
183 |
|
184 | /*
|
185 | // <e> PLL Setup
|
186 | // <i> Phase Locked Loop
|
187 | // <i> CCLK - Processor Clock
|
188 | // <i> Fcco - PLL Oscillator
|
189 | // <o1.0..4> MSEL: PLL Multiplier Selection
|
190 | // <1-32><#-1>
|
191 | // <i> PLL Multiplier "M" Value
|
192 | // <i> CCLK = M * Fosc
|
193 | // <o1.5..6> PSEL: PLL Divider Selection
|
194 | // <0=> 1 <1=> 2 <2=> 4 <3=> 8
|
195 | // <i> PLL Divider "P" Value
|
196 | // <i> Fcco = CCLK * 2 * P
|
197 | // <i> 156MHz <= Fcco <= 320MHz
|
198 | // </e>
|
199 | */
|
200 | .set PLL_SETUP, 1
|
201 | .set PLLCFG_Val, 0x00000024
|
202 |
|
203 |
|
204 | // Memory Accelerator Module (MAM) definitions
|
205 | .set MAM_BASE, 0xE01FC000 /* MAM Base Address */
|
206 | .set MAMCR_OFS, 0x00 /* MAM Control Offset*/
|
207 | .set MAMTIM_OFS, 0x04 /* MAM Timing Offset */
|
208 |
|
209 | /*
|
210 | // <e> MAM Setup
|
211 | // <i> Memory Accelerator Module
|
212 | // <o1.0..1> MAM Control
|
213 | // <0=> Disabled
|
214 | // <1=> Partially Enabled
|
215 | // <2=> Fully Enabled
|
216 | // <i> Mode
|
217 | // <o2.0..2> MAM Timing
|
218 | // <0=> Reserved <1=> 1 <2=> 2 <3=> 3
|
219 | // <4=> 4 <5=> 5 <6=> 6 <7=> 7
|
220 | // <i> Fetch Cycles
|
221 | // </e>
|
222 | */
|
223 | .set MAM_SETUP, 1
|
224 | .set MAMCR_Val, 0x00000002
|
225 | .set MAMTIM_Val, 0x00000004
|
226 |
|
227 |
|
228 | // Starupt Code must be linked first at Address at which it expects to run.
|
229 |
|
230 | .if (EXTMEM_MODE)
|
231 | .set CODE_BASE, 0x80000000
|
232 | .elseif (RAM_MODE)
|
233 | .set CODE_BASE, 0x40000000
|
234 | .else
|
235 | .set CODE_BASE, 0x00000000
|
236 | .endif
|
237 |
|
238 | #if 0
|
239 | AREA STARTUPCODE, CODE, AT CODE_BASE // READONLY, ALIGN=4
|
240 | PUBLIC __startup
|
241 |
|
242 | EXTERN CODE32 (?C?INIT)
|
243 |
|
244 | __startup PROC CODE32
|
245 |
|
246 | // Pre-defined interrupt handlers that may be directly
|
247 | // overwritten by C interrupt functions
|
248 | EXTERN CODE32 (Undef_Handler?A)
|
249 | EXTERN CODE32 (SWI_Handler?A)
|
250 | EXTERN CODE32 (PAbt_Handler?A)
|
251 | EXTERN CODE32 (DAbt_Handler?A)
|
252 | EXTERN CODE32 (IRQ_Handler?A)
|
253 | EXTERN CODE32 (FIQ_Handler?A)
|
254 | #endif
|
255 |
|
256 | .text
|
257 | .arm
|
258 |
|
259 | .if (VECTREMAPPED)
|
260 | .print "Vectors in section .vectmapped -> .data"
|
261 | .section .vectmapped, "ax"
|
262 | .else
|
263 | .print "Vectors in section .vectorg -> .text"
|
264 | .section .vectorg, "ax"
|
265 | .endif
|
266 |
|
267 | // Pre-defined interrupt handlers that may be directly
|
268 | // overwritten by C interrupt functions
|
269 | .extern Undef_Handler
|
270 | .extern SWI_Handler
|
271 | .extern PAbt_Handler
|
272 | .extern DAbt_Handler
|
273 | .extern IRQ_Handler
|
274 | .extern FIQ_Handler
|
275 |
|
276 |
|
277 | // Exception Vectors
|
278 | // Mapped to Address 0.
|
279 | // Absolute addressing mode must be used.
|
280 |
|
281 | __Vectors: LDR PC,Reset_Addr
|
282 | LDR PC,Undef_Addr
|
283 | LDR PC,SWI_Addr
|
284 | LDR PC,PAbt_Addr
|
285 | LDR PC,DAbt_Addr
|
286 | NOP /* Reserved Vector */
|
287 | // LDR PC,IRQ_Addr
|
288 | // LDR PC,[PC, #-0x0FF0] /* Vector from VicVectAddr */
|
289 | LDR PC,IRQ_Wrapper_Addr
|
290 | LDR PC,FIQ_Addr
|
291 |
|
292 | Reset_Addr: .word Reset_Handler
|
293 | Undef_Addr: .word Undef_Handler
|
294 | // SWI_Addr: .word SWI_Handler
|
295 | // SWI_Wrapper_Addr: .word SWI_Wrapper
|
296 | SWI_Addr: .word SoftwareInterrupt /* in swi_handler.S */
|
297 | PAbt_Addr: .word PAbt_Handler
|
298 | DAbt_Addr: .word DAbt_Handler
|
299 | .word 0 /* Reserved Address */
|
300 | // IRQ_Addr: .word __IRQ_Handler
|
301 | IRQ_Wrapper_Addr: .word __IRQ_Wrapper
|
302 | FIQ_Addr: .word FIQ_Handler
|
303 |
|
304 | Undef_Handler: B Undef_Handler
|
305 | /* SWI_Handler: B SWI_Handler */
|
306 | PAbt_Handler: B PAbt_Handler
|
307 | DAbt_Handler: B DAbt_Handler
|
308 | /* IRQ_Handler: B IRQ_Handler */
|
309 | FIQ_Handler: B FIQ_Handler
|
310 |
|
311 | .size __Vectors, . - __Vectors
|
312 |
|
313 |
|
314 |
|
315 | .arm
|
316 | .section .init, "ax"
|
317 |
|
318 | .if (VECTREMAPPED)
|
319 | /* mthomas: Dummy used during startup when remapping is enabled
|
320 | - mind the nops since the flash-utility will overwrite the
|
321 | "reserved vector"-address with the checksum */
|
322 | B Reset_Handler
|
323 | NOP
|
324 | NOP
|
325 | NOP
|
326 | NOP
|
327 | NOP /* Reserved Address */
|
328 | NOP
|
329 | NOP
|
330 | .endif
|
331 |
|
332 | .arm
|
333 | .section .init, "ax"
|
334 | .global __startup
|
335 | .func __startup
|
336 | __startup:
|
337 |
|
338 | Reset_Handler:
|
339 |
|
340 | // .if (VPBDIV_SETUP != 0)
|
341 | .if (VPBDIV_SETUP)
|
342 | LDR R0, =VPBDIV
|
343 | LDR R1, =VPBDIV_Val
|
344 | STR R1, [R0]
|
345 | .endif
|
346 |
|
347 |
|
348 | //.if (PLL_SETUP != 0)
|
349 | // .if (PLL_SETUP)
|
350 | LDR R0, =PLL_BASE
|
351 | MOV R1, #0xAA
|
352 | MOV R2, #0x55
|
353 |
|
354 | // Configure and Enable PLL
|
355 | MOV R3, #PLLCFG_Val
|
356 | STR R3, [R0, #PLLCFG_OFS]
|
357 | MOV R3, #PLLCON_PLLE
|
358 | STR R3, [R0, #PLLCON_OFS]
|
359 | STR R1, [R0, #PLLFEED_OFS]
|
360 | STR R2, [R0, #PLLFEED_OFS]
|
361 |
|
362 | // Wait until PLL Locked
|
363 | //PLL_Loop: LDR R3, [R0, #PLLSTAT_OFS]
|
364 | // ANDS R3, R3, #PLLSTAT_PLOCK
|
365 | // BEQ PLL_Loop
|
366 |
|
367 | // Switch to PLL Clock
|
368 | MOV R3, #(PLLCON_PLLE | PLLCON_PLLC)
|
369 | STR R3, [R0, #PLLCON_OFS]
|
370 | STR R1, [R0, #PLLFEED_OFS]
|
371 | STR R2, [R0, #PLLFEED_OFS]
|
372 | // .endif
|
373 |
|
374 |
|
375 | //.if (MAM_SETUP != 0)
|
376 | .if (MAM_SETUP)
|
377 | LDR R0, =MAM_BASE
|
378 | MOV R1, #MAMTIM_Val
|
379 | STR R1, [R0, #MAMTIM_OFS]
|
380 | MOV R1, #MAMCR_Val
|
381 | STR R1, [R0, #MAMCR_OFS]
|
382 | .endif
|
383 |
|
384 |
|
385 | // Memory Mapping
|
386 | .set MEMMAP, 0xE01FC040 /* Memory Mapping Control */
|
387 |
|
388 | .if (REMAP)
|
389 | LDR R0, =MEMMAP
|
390 | .if (EXTMEM_MODE)
|
391 | MOV R1, #3
|
392 | .elseif (RAM_MODE) || (VECTREMAPPED)
|
393 | .print "MEMMAP to 2 on init"
|
394 | MOV R1, #2
|
395 | .else
|
396 | MOV R1, #1
|
397 | .endif
|
398 | STR R1, [R0]
|
399 | .endif
|
400 |
|
401 | // Setup Stack for each mode
|
402 | LDR R0, =Top_Stack
|
403 |
|
404 | // Enter Undefined Instruction Mode and set its Stack Pointer
|
405 | MSR CPSR_c, #Mode_UND|I_Bit|F_Bit
|
406 | MOV SP, R0
|
407 | SUB R0, R0, #UND_Stack_Size
|
408 |
|
409 | // Enter Abort Mode and set its Stack Pointer
|
410 | MSR CPSR_c, #Mode_ABT|I_Bit|F_Bit
|
411 | MOV SP, R0
|
412 | SUB R0, R0, #ABT_Stack_Size
|
413 |
|
414 | // Enter FIQ Mode and set its Stack Pointer
|
415 | MSR CPSR_c, #Mode_FIQ|I_Bit|F_Bit
|
416 | MOV SP, R0
|
417 | SUB R0, R0, #FIQ_Stack_Size
|
418 |
|
419 | // Enter IRQ Mode and set its Stack Pointer
|
420 | MSR CPSR_c, #Mode_IRQ|I_Bit|F_Bit
|
421 | MOV SP, R0
|
422 | SUB R0, R0, #IRQ_Stack_Size
|
423 |
|
424 | // Enter Supervisor Mode and set its Stack Pointer
|
425 | MSR CPSR_c, #Mode_SVC|I_Bit|F_Bit
|
426 | MOV SP, R0
|
427 | SUB R0, R0, #SVC_Stack_Size
|
428 |
|
429 | // Enter User Mode and set its Stack Pointer
|
430 | MSR CPSR_c, #Mode_USR /* Interrupts enabled */
|
431 | // MSR CPSR_c, #Mode_USR|I_Bit|F_Bit /* Interrupts disabled */
|
432 | MOV SP, R0 #######################################
|
433 | #######################################
|
434 |
|
435 | .if (RAM_MODE==0)
|
436 | /* Relocate .data section (Copy from ROM to RAM) */
|
437 | LDR R1, =_etext
|
438 | LDR R2, =_data
|
439 | LDR R3, =_edata
|
440 | CMP R2, R3
|
441 | BEQ DataIsEmpty
|
442 | LoopRel: CMP R2, R3
|
443 | LDRLO R0, [R1], #4
|
444 | STRLO R0, [R2], #4
|
445 | BLO LoopRel
|
446 | DataIsEmpty:
|
447 | .endif
|
448 |
|
449 | /* Clear .bss section (Zero init) */
|
450 | MOV R0, #0
|
451 | LDR R1, =__bss_start__
|
452 | LDR R2, =__bss_end__
|
453 | CMP R1,R2
|
454 | BEQ BSSIsEmpty
|
455 | LoopZI: CMP R1, R2
|
456 | STRLO R0, [R1], #4
|
457 | BLO LoopZI
|
458 | BSSIsEmpty:
|
459 |
|
460 |
|
461 | // call C++ constructors of global objects
|
462 | LDR r0, =__ctors_start__
|
463 | LDR r1, =__ctors_end__
|
464 | ctor_loop:
|
465 | CMP r0, r1
|
466 | BEQ ctor_end
|
467 | LDR r2, [r0], #4
|
468 | STMFD sp!, {r0-r1}
|
469 | MOV lr, pc
|
470 | MOV pc, r2
|
471 | LDMFD sp!, {r0-r1}
|
472 | B ctor_loop
|
473 | ctor_end:
|
474 |
|
475 | // Enter the C code
|
476 | //LDR R0,=INIT
|
477 | LDR R0,=main
|
478 | TST R0,#1 // Bit-0 set: main is Thumb
|
479 | LDREQ LR,=__exit_ARM // ARM Mode
|
480 | LDRNE LR,=__exit_THUMB // Thumb Mode
|
481 | BX R0
|
482 |
|
483 | .size __startup, . - __startup
|
484 | .endfunc
|
485 |
|
486 | .arm
|
487 | .global __exit_ARM
|
488 | .func __exit_ARM
|
489 | __exit_ARM:
|
490 | B __exit_ARM
|
491 | .size __exit_ARM, . - __exit_ARM
|
492 | .endfunc
|
493 |
|
494 | .thumb
|
495 | .global __exit_THUMB
|
496 | .func __exit_THUMB
|
497 | .thumb_func
|
498 | __exit_THUMB:
|
499 | B __exit_THUMB
|
500 | .size __exit_THUMB, . - __exit_THUMB
|
501 | .endfunc
|
502 |
|
503 |
|
504 | /* mthomas: the following code is inspired by various examples and
|
505 | documents from ARM, Atmel, Anglia Designs and others */
|
506 |
|
507 |
|
508 | .text
|
509 | .arm
|
510 |
|
511 | .if (VECTREMAPPED)
|
512 | .print "Handlers in section .vectmapped -> .data"
|
513 | .section .vectmapped, "ax"
|
514 | .else
|
515 | .print "Handlers in section .vectorg -> .code/.text"
|
516 | .section .vectorg, "ax"
|
517 | .endif
|
518 |
|
519 | .set VIC_base_addr, 0xFFFFF000
|
520 | .set VIC_vect_offs, 0x30
|
521 |
|
522 | .arm
|
523 | .global __IRQ_Wrapper
|
524 | .func __IRQ_Wrapper
|
525 | __IRQ_Wrapper:
|
526 | /*- Manage Exception Entry */
|
527 | /*- Adjust and save LR_irq in IRQ stack */
|
528 | sub lr, lr, #4
|
529 | stmfd sp!, {lr}
|
530 |
|
531 | /*- Save SPSR need to be saved for nested interrupt */
|
532 | mrs r14, SPSR
|
533 | stmfd sp!, {r14}
|
534 |
|
535 | /*- Save and r0 in IRQ stack */
|
536 | stmfd sp!, {r0}
|
537 |
|
538 | /*- Write in the IVR to support Protect Mode */
|
539 | /*- No effect in Normal Mode */
|
540 | /*- De-assert the NIRQ and clear the source in Protect Mode */
|
541 | /* R14 = LR */
|
542 | ldr r14, =VIC_base_addr
|
543 | ldr r0 , [r14, #VIC_vect_offs]
|
544 | /*str r14, [r14, #VIC_vect_offs]*/
|
545 |
|
546 | /*- Enable Interrupt and Switch in Supervisor Mode */
|
547 | msr CPSR_c, #Mode_SVC
|
548 |
|
549 | /*- Save scratch/used registers and LR in User Stack */
|
550 | /*stmfd sp!, { r1-r3, r12, r14}*/
|
551 | stmfd sp!, { r1-r12, r14 }
|
552 |
|
553 | /*- Branch to the routine pointed by the VIC-Vector-Address */
|
554 | mov r14, pc
|
555 | bx r0
|
556 | /*- Restore scratch/used registers and LR from User Stack*/
|
557 | /* ldmia sp!, { r1-r3, r12, r14} */
|
558 | ldmia sp!, { r1-r12, r14 }
|
559 |
|
560 | /*- Disable Interrupt and switch back in IRQ mode */
|
561 | msr CPSR_c, #I_Bit | Mode_IRQ
|
562 |
|
563 | #if 0
|
564 | /* VICVectAddr=0 is already done in the ISRs of the Philips-Examples
|
565 | so commented out here */
|
566 | /*- Mark the End of Interrupt on the VIC */
|
567 | ldr r14, =VIC_base_addr
|
568 | str r14, [r14, #VIC_vect_offs]
|
569 | #endif
|
570 |
|
571 | /*- Restore SPSR_irq and r0 from IRQ stack */
|
572 | ldmia sp!, {r0}
|
573 |
|
574 | /*- Restore SPSR_irq and r0 from IRQ stack */
|
575 | ldmia sp!, {r14}
|
576 | msr SPSR_cxsf, r14
|
577 |
|
578 | /*- Restore adjusted LR_irq from IRQ stack directly in the PC */
|
579 | ldmia sp!, {pc}^
|
580 |
|
581 | .size __IRQ_Wrapper, . - __IRQ_Wrapper
|
582 | .endfunc
|
583 |
|
584 |
|
585 | #if 0
|
586 | /* mthomas:
|
587 | Wrapper to call a C swi-Function declared with
|
588 | void SWI_Handler(int swi_num, int *regs)
|
589 | Inspired by Anglia Designs example
|
590 | -- not used here - see swi_handler.S
|
591 | */
|
592 | .arm
|
593 | .global __SWI_Wrapper
|
594 | .func __SWI_Wrapper
|
595 | __SWI_Wrapper: /* r0 holds swi number */
|
596 | STMFD sp!,{r0-r12,lr} /* Save The workspace plus the current return */
|
597 | /* address lr_ mode into the stack */
|
598 | MRS r1, spsr /* Save the spsr_mode into r1 */
|
599 | STMFD sp!, {r1} /* Save spsr */
|
600 | MOV r1, sp /* load regs */
|
601 | LDR r0,=SWI_Handler
|
602 | MOV lr, pc
|
603 | BX r0 /* call the C-funcktion */
|
604 | LDMFD sp!, {r1} /* Restore the saved spsr_mode into r1 */
|
605 | MSR spsr_cxsf, r1 /* Restore spsr_mode */
|
606 | LDMFD sp!, {r0-r12,pc} /* Return to the instruction following */
|
607 | /* the exception interrupt */
|
608 | .size __SWI_Wrapper, . - __SWI_Wrapper
|
609 | .endfunc
|
610 | #endif
|
611 |
|
612 | #if 0
|
613 | /* mthomas: not used here - reminder for future tests */
|
614 | .arm
|
615 | .global __IRQ_Wrapper
|
616 | .func __IRQ_Wrapper
|
617 | __IRQ_Wrapper:
|
618 | SUB lr, lr, #4 /* Update the link register */
|
619 | STMFD sp!,{r0-r12,lr} /* Save The workspace plus the current return */
|
620 | /* address lr_ mode into the stack */
|
621 | MRS r1, spsr /* Save the spsr_mode into r1 */
|
622 | STMFD sp!, {r1} /* Save spsr */
|
623 | LDR lr, =ReturnAddress /* Read the return address. */
|
624 | LDR r0, =VIC_base_addr /* Load VIC Base-Address */
|
625 | LDR r1, [r0, #VIC_vect_offs] /* Load ISR-Address from VICVectAddr */
|
626 | bx r1 /* Branch to the IRQ handler. */
|
627 | ReturnAddress:
|
628 | LDR r2, =VIC_base_addr /* clear Interrupt */
|
629 | MOV r3, #0
|
630 | STR R3, [R2, #VIC_vect_offs] /* by writing to VICVectAddr */
|
631 | LDMFD sp!, {r1} /* Restore the saved spsr_mode into r1 */
|
632 | MSR spsr_cxsf, r1 /* Restore spsr_mode */
|
633 | LDMFD sp!, {r0-r12,pc}^ /* Return to the instruction following */
|
634 | /* the exception interrupt */
|
635 | .size __IRQ_Wrapper, . - __IRQ_Wrapper
|
636 | .endfunc
|
637 | #endif
|
638 |
|
639 | .end
|