1
// #========================================================================
5
// # ARM exception vectors (phyCORE_PXA255)
8
// # Copyright HighTec EDV-Systeme GmbH 1982-2006
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_DBG_MODE 0x15 /* XScale extension */
24
#define CPSR_ABORT_MODE 0x17
25
#define CPSR_UNDEF_MODE 0x1B
26
#define CPSR_SYSTEM_MODE 0x1F
28
#define SWI_Location 0x28 /* HiMo: address of SWI handler */
29
#define IRQ_Location 0x38 /* HiMo: address of IRQ handler */
32
//; # Platform specific definition for phyCORE-PXA255 board
35
/* Reset Controller Registers */
36
#define RST_BASE 0x40F00030
38
#define RCSR (RST_BASE + 0x00)
40
/* Operating System Timer */
41
#define OSTIMER_BASE 0x40A00000
42
#define OSMR3_OFFS 0x0C
43
#define OSCR_OFFS 0x10
44
#define OWER_OFFS 0x18
45
#define OIER_OFFS 0x1C
47
/* Clock Manager Register */
48
#define CC_BASE 0x41300000
49
#define CCCR_OFFS 0x00
50
#define CKEN_OFFS 0x04
52
/* Interrupt Controller Registers */
53
#define IC_BASE 0x40D00000
54
/* Interrupt Mask Register */
55
#define ICMR (IC_BASE + 0x04)
56
#define ICMR_OFFS 0x04
58
/* MMU bit definitions */
60
#define MMU_Control_M (1 << 0) /* Enable MMU */
61
#define MMU_Control_A (1 << 1) /* Enable address alignment faults */
62
#define MMU_Control_C (1 << 2) /* Enable cache */
63
#define MMU_Control_B (1 << 7) /* Enable Big-Endian */
64
#define MMU_Control_S (1 << 8) /* Enable system protection */
65
#define MMU_Control_R (1 << 9) /* Enable ROM protection */
66
#define MMU_Control_Z (1 << 11) /* Branch Target Buffer Enable */
67
#define MMU_Control_I (1 << 11) /* Enable Instruction cache */
68
#define MMU_Control_V (1 << 12) /* Interrupt vectors at 0xFFFF0000 */
70
#define PHYS_RAM_BASE 0xa0000000
72
/* Intel proposed macro for writing CP15 */
80
//; #==========================================================================
81
//; # Hardware exception vectors.
82
//; # The vector table will be copied to location 0x0000 at startup time.
85
.section ".vectors","ax"
86
.global __exception_handlers
92
ldr pc,.undefined_instruction
93
ldr pc,.software_interrupt
94
ldr pc,.abort_prefetch
100
//; # The layout of these pointers should match the vector table above since
101
//; # they are copied in pairs.
106
.undefined_instruction:
107
.word undefined_instruction
109
.word software_interrupt
123
//; begin of startup code
127
.type reset_vector,function
130
//; # PLATFORM_SETUP1 //; # Early stage platform initialization
133
//; # MMU disabled, Alignment fault disabled, DCache disabled
134
//; # exceptions vectors at 0
136
bic r1,r1,#(MMU_Control_M+MMU_Control_A+MMU_Control_C)
137
bic r1,r1,#MMU_Control_V
141
mcr p15,0,r0,c8,c7,0 //; # invalidate all TLBs
142
mcr p15,0,r0,c7,c7,0 //; # invalidate caches
147
str r1,[r0,#ICMR_OFFS]
149
//; # initialize clock
151
mov r1,#0 //; disable all peripheral clocks
152
str r1,[r0,#CKEN_OFFS] //; CKEN Clock Enable Register
154
ldr r1,=0x161 //; 4 x fMemory
156
ldr r1,=0x141 //; 2 x fMemory
157
#endif /* FAST_CLOCK */
158
str r1,[r0,#CCCR_OFFS] //; CCCR Core Clock Configuration Register
160
mcr p14,0,r0,c6,c0 //; activate clock change
162
/* ToDo: initialize RAM/ROM/SDRAM */
165
/* initialize MMU tables */
166
ldr r0,=PHYS_RAM_BASE
167
ldr sp,=__startup_stack
174
orr r0,r0,#MMU_Control_M /* enable MMU */
181
#endif /* DONT_USE_MMU */
185
//; # copy the vector table (__vector_table_start .. __vector_table_end) to address 0
188
//; # HiMo needs its own exception handlers --> don't overwrite these!!
190
ldr r9,=__exception_handlers
195
#endif /* !USE_HIMO */
197
// ; Relocate [copy] data from ROM to RAM
198
ldr r0,=__rom_data_start
199
ldr r1,=__ram_data_start
200
ldr r2,=__ram_data_end
202
cmp r1,r2 //; # while (r1 < r2)
203
ldrcc r3,[r0],#4 //; # {
204
strcc r3,[r1],#4 //; # *r1++ = *r0++;
212
cmp r1,r2 //; # while (r1 < r2)
213
strcc r0,[r1],#4 //; # *r1++ = 0;
216
#if defined(USE_IRQ) && defined(USE_HIMO)
217
//; replace IRQ handler by our own handler
219
ldr r0,=HIMO_IRQ_Address
224
#endif /* USE_IRQ && USE_HIMO */
226
// ; # initialize interrupt/exception environments
227
ldr sp,=__startup_stack
228
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_IRQ_MODE)
230
ldr sp,=__interrupt_stack
231
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_FIQ_MODE)
233
ldr sp,=__FIQ_exception_stack
234
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_UNDEF_MODE)
236
ldr sp,=__exception_stack
237
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_ABORT_MODE)
239
ldr sp,=__exception_stack
241
// ; # initialize CPSR (machine state register)
242
mov r0,#(CPSR_IRQ_DISABLE|CPSR_FIQ_DISABLE|CPSR_SVC_MODE)
245
// ; # Note: some functions in LIBGCC1 will cause a "restore from SPSR"!!
249
//; # initialize interrupt tables
255
//; # do low level PXROS initialization if we are in a PXROS environment
256
ldr r0,=PxPrepareInit
265
orr r0,r0,#MMU_Control_I /* enable instruction cache */
267
orr r0,r0,#(MMU_Control_C) /* enable data cache */
268
#endif /* ENABLE_DCACHE */
271
#endif /* ENABLE_ICACHE */
272
#endif /* DONT_USE_MMU */
274
// ; # switch to user mode, evtl. IRQs enabled
276
#ifdef USE_SYSTEM_MODE
277
mov r0,#(CPSR_FIQ_DISABLE | CPSR_SYSTEM_MODE)
279
mov r0,#(CPSR_FIQ_DISABLE | CPSR_USER_MODE)
280
#endif /* USE_SYSTEM_MODE */
282
#ifdef USE_SYSTEM_MODE
283
mov r0,#(CPSR_IRQ_DISABLE | CPSR_FIQ_DISABLE | CPSR_SYSTEM_MODE)
285
mov r0,#(CPSR_IRQ_DISABLE | CPSR_FIQ_DISABLE | CPSR_USER_MODE)
286
#endif /* USE_SYSTEM_MODE */
291
#ifndef __NO_CTOR_DTOR_SUPPORT__
292
#ifdef __USES_INITFINI__
293
/* Some arm/elf targets use the .init and .fini sections
294
to create constructors and destructors, and for these
295
targets we need to call the _init function and arrange
296
for _fini to be called at program exit. */
300
#endif /* __USES_INITFINI__ */
301
#endif /* !__NO_CTOR_DTOR_SUPPORT__ */
303
mov a1,#0 //; # set argc to 0
304
mov a2,#0 //; # and argv to NUL
308
bl IrqInit //; # stop interrupts
309
bl RestoreHIMO //; # restore HIMO environment
311
#endif /* USE_HIMO */
313
#ifdef __NO_CTOR_DTOR_SUPPORT__
317
bl exit //; # exit(0)
318
#endif /* __NO_CTOR_DTOR_SUPPORT__ */
323
//; # Exception handlers
324
//; # Assumption: get here from a Supervisor context [mode]
327
undefined_instruction:
328
b undefined_instruction
351
sub lr,lr,#4 //; adjust return address before saving it
353
mrs lr,spsr //; and status bits
354
stmfd sp!,{r0-r3,r12,lr} //; save APCS working register and SPSR
356
// ; switch to another mode (to avoid problem with C language handler code)
357
// ; SVC mode if interrupted service else SYSTEM mode (interrupted task)
358
mrs r0,cpsr //; read the current status register
359
bic r0,r0,#CPSR_MODE_BITS //; clear the mode bits
360
and lr,lr,#CPSR_MODE_BITS //; extract the mode bits of interrupted state
361
cmp lr,#CPSR_SVC_MODE
362
orreq r0,r0,#CPSR_SVC_MODE //; switch to SVC mode
363
orrne r0,r0,#CPSR_SYSTEM_MODE //; switch to SYSTEM mode
367
stmfd sp!,{lr} //; save original lr (lr_svc|lr)
371
ldmfd sp!,{lr} //; restore original lr (lr_svc|lr)
372
// ; and switch back to IRQ mode
373
mrs r12,cpsr //; read the status register
374
bic r12,r12,#CPSR_MODE_BITS //; clear the mode bits
375
orr r12,r12,#CPSR_IRQ_MODE //; switch to IRQ mode
376
msr cpsr_cf,r12 //; write it back
379
ldmfd sp!,{r0-r3,r12,lr} //; restore APCS working register and SPSR
381
ldmfd sp!,{pc}^ //; and return from interrupt and restore CPSR
388
#if defined(USE_IRQ) && defined(USE_HIMO)
389
//; restore HIMO's original exception handler environment
393
ldr r0,=HIMO_IRQ_Address
398
//; restore HIMO's SWI handler if it's a PXROS application
399
ldr r0,=PxPrepareInit
403
ldr r0,=oldSWIHandler
409
#endif /* USE_IRQ && USE_HIMO */
414
//; # -------------------------------------------------------------------------
415
//; # data section used by startup code
419
//; # -------------------------------------------------------------------------
420
//; # Temporary interrupt stack
424
#if defined(USE_IRQ) && defined(USE_HIMO)
427
#endif /* USE_IRQ && USE_HIMO */
429
.global __interrupt_stack
430
.global __startup_stack
431
.global _PxSysstackend
433
//; # Small stacks, only used for saving information between CPU modes
434
__exception_stack_base:
438
__FIQ_exception_stack:
444
//; # Runtime stack used during all IRQ interrupt processing
445
#ifndef IRQ_STACK_SIZE
447
#define IRQ_STACK_SIZE 2048
449
#define IRQ_STACK_SIZE 16*4
451
#endif /* IRQ_STACK_SIZE */
454
__interrupt_stack_base:
460
//; # the following 2 words are used for PXROS taskret storage
464
#ifndef STARTUP_STACK_SIZE
465
#define STARTUP_STACK_SIZE 2048
466
#endif /* STARTUP_STACK_SIZE */
470
__startup_stack_base:
471
.rept STARTUP_STACK_SIZE
477
#ifndef USER_STACK_SIZE
478
#define USER_STACK_SIZE 2048
479
#endif /* USER_STACK_SIZE */
483
.rept USER_STACK_SIZE
490
//; # --------------------------------------------------------------------------
491
//; # end of vectors.S