1
// #========================================================================
5
// # ARM exception vectors (Olimex LPC-P2138)
8
// # Copyright HighTec EDV-Systeme GmbH 1982-2007
10
// #========================================================================
13
#define CPSR_IRQ_DISABLE 0x80 /* IRQ disabled when = 1 */
14
#define CPSR_FIQ_DISABLE 0x40 /* FIQ disabled when = 1 */
15
#define CPSR_THUMB_ENABLE 0x20 /* Thumb mode when = 1 */
16
#define CPSR_MODE32_ENABLE 0x10 /* 32 bit mode when = 1 */
18
#define CPSR_MODE_BITS 0x1F
19
#define CPSR_USER_MODE 0x10
20
#define CPSR_FIQ_MODE 0x11
21
#define CPSR_IRQ_MODE 0x12
22
#define CPSR_SVC_MODE 0x13
23
#define CPSR_ABORT_MODE 0x17
24
#define CPSR_UNDEF_MODE 0x1B
25
#define CPSR_SYSTEM_MODE 0x1F
27
#define SWI_Location 0x28 /* HiMo: address of SWI handler */
28
#define IRQ_Location 0x38 /* HiMo: address of IRQ handler */
31
//; # Platform specific definition for LPC213x
34
/*-----------------------*/
35
/* PLL Control Registers */
36
/*-----------------------*/
37
#define SCB_BASE 0xE01FC000
38
#define PLL_BASE (SCB_BASE + 0x080)
40
/* PLL Control Register */
41
#define PLLCON (SCB_BASE + 0x80)
42
/* PLL Configuration Register */
43
#define PLLCFG (SCB_BASE + 0x84)
44
/* PLL Status Register */
45
#define PLLSTAT (SCB_BASE + 0x88)
46
/* PLL Feed Register */
47
#define PLLFEED (SCB_BASE + 0x8C)
49
#define PLLCON_PLLE 0x01 /* PLL Enable */
50
#define PLLCON_PLLC 0x02 /* PLL Connect */
52
#define PLLCFG_VAL 0x23 /* P=2,M=4 */
54
#define PLL_PLLC 0x100 /* Status of PLL Enable */
55
#define PLL_PLLE 0x200 /* Status of PLL Connect */
56
#define PLL_PLOCK 0x400 /* PLL Lock Status */
58
#define PLLFEED_PW0 0xAA
59
#define PLLFEED_PW1 0x55
61
/* Memory Mapping Control Register */
62
#define MEMMAP (SCB_BASE + 0x40)
64
#define MEMMAP_BOOT 0x00 /* vectors mapped to Boot Block */
65
#define MEMMAP_FLASH 0x01 /* vectors at 0 (internal Flash) */
66
#define MEMMAP_ISRAM 0x02 /* vectors mapped to internal SRAM */
68
#define ISRAM_START 0x40000000
70
/* APB Divider Register */
71
#define APBDIV (SCB_BASE + 0x100)
73
#define APBDIV_4 0 /* peripherals clock == CPU/4 clock */
74
#define APBDIV_2 2 /* peripherals clock == CPU/2 clock */
75
#define APBDIV_1 1 /* peripherals clock == CPU clock */
78
/*-----------------------------------------*/
79
/* Vectored Interrupt Controller Registers */
80
/*-----------------------------------------*/
81
#define VIC_BASE 0xFFFFF000
83
/* Interrupt Enable Clear Register */
84
#define VICIEC (VIC_BASE + 0x14)
85
/* IRQ Vector Register */
86
#define VICVADDR (VIC_BASE + 0x30)
88
#define ISR_VALID_MASK 0x003FFFFF
91
//; #==========================================================================
92
//; # Hardware exception vectors.
93
//; # The vector table will be copied to location 0x0000 at startup time.
96
.section ".vectors","ax"
97
.global __exception_handlers
99
//; # LPC2xxx boot code looks for a valid vector table at start of flash.
100
//; # A vector table is valid if the word sum over the 8 vector entries is zero.
101
//; # The unused word at location 0x14 is used for adjusting the checksum.
102
__exception_handlers:
103
__vector_table_start:
105
ldr pc,.undefined_instruction
106
ldr pc,.software_interrupt
107
ldr pc,.abort_prefetch
109
.word 0xB8A06F58 //; ==> checksum = 0
113
//; # The layout of these pointers should match the vector table above since
114
//; # they are copied in pairs.
119
.undefined_instruction:
120
.word undefined_instruction
122
.word software_interrupt
136
//; begin of startup code
140
.type reset_vector,function
143
//; # PLATFORM_SETUP1 //; # Early stage platform initialization
146
ldr r1,[r0,#(PLLSTAT-SCB_BASE)]
147
ldr r2,=(PLL_PLOCK + PLL_PLLE + PLL_PLLC)
149
cmp r1,#(PLL_PLOCK + PLL_PLLE + PLL_PLLC)
150
beq 10f /* clock is already running */
153
str r1,[r0,#(PLLCFG-SCB_BASE)]
155
ldr r1,=PLLCON_PLLE /* PLLCON.0 = 0x01 -> PLL enabled */
156
str r1,[r0,#(PLLCON-SCB_BASE)]
158
ldr r1,=PLLFEED_PW0 /* write feed sequence */
159
str r1,[r0,#(PLLFEED-SCB_BASE)]
161
str r1,[r0,#(PLLFEED-SCB_BASE)]
163
ldr r1,[r0,#(PLLSTAT-SCB_BASE)]
164
ands r1,r1,#PLL_PLOCK
165
beq 02b /* wait until oscillator is stabilized */
167
ldr r1,=(PLLCON_PLLE+PLLCON_PLLC) /* PLLCON.0 = 1, PLLCON.1 = 1 */
168
str r1,[r0,#(PLLCON-SCB_BASE)]
170
ldr r1,=PLLFEED_PW0 /* write feed sequence */
171
str r1,[r0,#(PLLFEED-SCB_BASE)]
173
str r1,[r0,#(PLLFEED-SCB_BASE)]
176
ldr r1,[r0,#(PLLSTAT-SCB_BASE)]
177
ands r1,r1,#PLL_PLOCK
178
beq 04b /* wait until PLL is stabilized */
181
mov r1,#APBDIV_1 /* peripherals clock == CPU clock */
182
str r1,[r0,#(APBDIV-SCB_BASE)]
186
ldr r0,=ISR_VALID_MASK /* disable all interrupts */
190
//; # copy the vector table (__vector_table_start .. __vector_table_end) to internal SRAM
193
//; # HiMo needs its own exception handlers --> don't overwrite these!!
195
ldr r9,=__exception_handlers
200
#endif /* USE_HIMO */
202
//; then remap vectors to point to internal SRAM
204
mov r1,#MEMMAP_ISRAM /* map vectors to internal SRAM */
205
str r1,[r0,#(MEMMAP-SCB_BASE)]
207
// ; Relocate [copy] data from ROM to RAM
208
ldr r0,=__rom_data_start
209
ldr r1,=__ram_data_start
210
ldr r2,=__ram_data_end
212
cmp r1,r2 //; # while (r1 < r2)
213
ldrcc r3,[r0],#4 //; # {
214
strcc r3,[r1],#4 //; # *r1++ = *r0++;
222
cmp r1,r2 //; # while (r1 < r2)
223
strcc r0,[r1],#4 //; # *r1++ = 0;
226
#if defined(USE_IRQ) && defined(USE_HIMO)
227
//; replace IRQ handler by our own handler
229
ldr r0,=HIMO_IRQ_Address
234
#endif /* USE_IRQ && USE_HIMO */
236
// ; # initialize interrupt/exception environments
237
ldr sp,=__startup_stack
238
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
240
ldr sp,=__interrupt_stack
241
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_FIQ_MODE)
243
ldr sp,=__FIQ_exception_stack
244
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
246
ldr sp,=__exception_stack
247
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_ABORT_MODE)
249
ldr sp,=__exception_stack
251
// ; # initialize CPSR (machine state register)
252
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SVC_MODE)
255
// ; # Note: some functions in LIBGCC1 will cause a "restore from SPSR"!!
259
//; # initialize interrupt tables
265
//; # do low level PXROS initialization if we are in a PXROS environment
266
ldr r0,=PxPrepareInit
273
// ; # switch to user mode, evtl. IRQs enabled
275
mov r0,#(CPSR_FIQ_DISABLE|CPSR_USER_MODE)
277
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_USER_MODE)
282
#ifndef __NO_CTOR_DTOR_SUPPORT__
283
#ifdef __USES_INITFINI__
284
/* Some arm/elf targets use the .init and .fini sections
285
to create constructors and destructors, and for these
286
targets we need to call the _init function and arrange
287
for _fini to be called at program exit. */
291
#endif /* __USES_INITFINI__ */
292
#endif /* __NO_CTOR_DTOR_SUPPORT__ */
294
mov a1,#0 //; # set argc to 0
295
mov a2,#0 //; # and argv to NUL
299
bl IrqInit //; # stop interrupts
300
bl RestoreHIMO //; # restore HIMO environment
302
#endif /* USE_HIMO */
304
#ifdef __NO_CTOR_DTOR_SUPPORT__
308
bl exit //; # exit(0)
309
#endif /* __NO_CTOR_DTOR_SUPPORT__ */
314
//; # Exception handlers
315
//; # Assumption: get here from a Supervisor context [mode]
318
undefined_instruction:
319
b undefined_instruction
342
sub lr,lr,#4 //; adjust return address before saving it
344
mrs lr,spsr //; and status bits
345
stmfd sp!,{r0-r3,r12,lr} //; save APCS working register and SPSR
349
ldr r12,[r0,#(VICVADDR-VIC_BASE)] //; load the vector routine
351
// ; switch to another mode (to avoid problem with C language handler code)
352
// ; SVC mode if interrupted service else SYSTEM mode (interrupted task)
353
mrs r0,cpsr //; read the current status register
354
bic r0,r0,#CPSR_MODE_BITS //; clear the mode bits
355
and lr,lr,#CPSR_MODE_BITS //; extract the mode bits of interrupted state
356
cmp lr,#CPSR_SVC_MODE
357
orreq r0,r0,#CPSR_SVC_MODE //; switch to SVC mode
358
orrne r0,r0,#CPSR_SYSTEM_MODE //; switch to SYSTEM mode
361
stmfd sp!,{lr} //; save original lr (lr_svc|lr)
362
adr lr,Back_From_Handler //; set the return address
364
// ; now read-modify-write the CPSR to enable interrupts
365
mrs r0,cpsr //; read the status register
366
bic r0,r0,#CPSR_IRQ_DISABLE //; clear the IRQ disable bit
367
msr cpsr_cf,r0 //; reenable interrupts
369
// ; jump to the correct handler
375
// ; now read-modify-write the CPSR to disable interrupts
376
mrs r0,cpsr //; read the status register
377
orr r0,r0,#CPSR_IRQ_DISABLE //; set the IRQ disable bit
378
msr cpsr_cf,r0 //; write it back to disable interrupts
380
ldmfd sp!,{lr} //; restore original lr (lr_svc|lr)
381
// ; and switch back to IRQ mode
382
mrs r12,cpsr //; read the status register
383
bic r12,r12,#CPSR_MODE_BITS //; clear the mode bits
384
orr r12,r12,#CPSR_IRQ_MODE //; switch to IRQ mode
385
msr cpsr_cf,r12 //; write it back
387
ldr r1,=VIC_BASE //; signal end of interrupt to VIC
388
str r1,[r1,#(VICVADDR-VIC_BASE)]
390
ldmfd sp!,{r0-r3,r12,lr} //; restore APCS working register and SPSR
392
ldmfd sp!,{pc}^ //; and return from interrupt and restore CPSR
399
#if defined(USE_IRQ) && defined(USE_HIMO)
400
//; restore HIMO's original exception handler environment
404
ldr r0,=HIMO_IRQ_Address
409
//; restore HIMO's SWI handler if it's a PXROS application
410
ldr r0,=PxPrepareInit
414
ldr r0,=oldSWIHandler
420
#endif /* USE_IRQ && USE_HIMO */
425
//; # -------------------------------------------------------------------------
426
//; # data section used by startup code
430
//; # -------------------------------------------------------------------------
431
//; # Temporary interrupt stack
435
#if defined(USE_IRQ) && defined(USE_HIMO)
438
#endif /* USE_IRQ && USE_HIMO */
440
.global __interrupt_stack
441
.global __startup_stack
442
.global _PxSysstackend
444
//; # Small stacks, only used for saving information between CPU modes
445
__exception_stack_base:
449
__FIQ_exception_stack:
455
//; # Runtime stack used during all IRQ interrupt processing
456
#ifndef IRQ_STACK_SIZE
458
#define IRQ_STACK_SIZE 512
460
#define IRQ_STACK_SIZE 16*4
462
#endif /* IRQ_STACK_SIZE */
465
__interrupt_stack_base:
471
//; # the following 2 words are used for PXROS taskret storage
475
#ifndef STARTUP_STACK_SIZE
476
#define STARTUP_STACK_SIZE 512
477
#endif /* STARTUP_STACK_SIZE */
481
__startup_stack_base:
482
.rept STARTUP_STACK_SIZE
488
#ifndef USER_STACK_SIZE
489
#define USER_STACK_SIZE 512
490
#endif /* USER_STACK_SIZE */
494
.rept USER_STACK_SIZE
501
//; # --------------------------------------------------------------------------
502
//; # end of vectors.S