; *********************************************************************** ; * * ; * Initialisation Routines for Push-button Program, Second Version * ; * * ; *********************************************************************** ; Author: John Zaitseff ; Date: 18th June, 2003 ; Version: 1.3 ; This file contains the initialisation routines for the second version of ; the IRQ-enabled Push-button Switches program (pb-irq-v2.elf), as used in ; ELEC2041 Experiment 5. In particular, it contains the ARM processor ; exception vector table and the boot code that (among other things) ; enables various hardware interrupts and sets the processor into User ; mode. .global _start ; "_start" is where the code starts running .extern main ; "main" is defined in another file .extern irq_handler ; "irq_handler" is also defined elsewhere .include "header-v3.s" ; Include various definitions ; ----------------------------------------------------------------------- ; The following code will be placed into the ".zeropage" section, NOT into ; the ".text" section. The GNU Linker will place the ".zeropage" section ; at address 0x0. .section .zeropage, "awx" ; For code located at address 0x00000000 _start: ; Start of the entire program ; ARM processor exception vector table ; The ARM processor exception vector table must appear at address 0x0. ; This particular table only handles the Reset and Interrupt exceptions; ; all other exceptions will NOT be handled correctly at all. ev00: b init ; Reset exception ev04: nop ; Undefined Instruction exception ev08: nop ; Software Interrupt exception ev0C: nop ; Prefetch Abort exception ev10: nop ; Data Abort exception ev14: nop ; (Not used) ev18: b irq_handler ; Interrupt exception ev1C: nop ; Fast Interrupt exception ; ----------------------------------------------------------------------- ; The following code will be placed into the ".ospage" section, NOT into ; the ".text" section. The GNU Linker will place the ".ospage" section at ; address 0x1000. .section .ospage, "awx" ; For "operating system" code ; Initialisation routine ; This routine is run at processor reset. It sets up the stacks for ; different processor modes, initialises the hardware interrupts ; corresponding to push-button switches S2 and S3, then changes the ARM ; processor into User mode with the Fast and normal interrupts enabled. init: ; This code initially runs in Supervisor mode ; Set up the stack pointers ldr sp, =svc_stack_top ; Initialise SP_svc mrs r0, cpsr ; Get current value of CPSR into R0 bic r0, r0, #ARM_PSR_mode_mask ; Mask out the bottom 5 bits orr r1, r0, #ARM_PSR_mode_irq ; R1 = CPSR + IRQ mode msr cpsr_c, r1 ; Switch into IRQ mode ldr sp, =irq_stack_top ; and set SP_irq appropriately orr r1, r0, #ARM_PSR_mode_fiq ; R1 = CPSR + FIQ mode msr cpsr_c, r1 ; Switch into FIQ mode ldr sp, =fiq_stack_top ; and set SP_fiq appropriately orr r1, r0, #ARM_PSR_mode_sys ; R1 = CPSR + System mode msr cpsr_c, r1 ; Switch into System mode ldr sp, =usr_stack_top ; and set SP appropriately ; Note that User and System modes ; share the same registers ; Set up the DSLMU Microcontroller Board hardware ldr r0, =iobase ; R0 = base of Microcontroller I/O space mov r1, #(irq_pbs2 | irq_pbs3) ; R1 = enable IRQs mask for S2/S3 strb r1, [r0, #irq_enable] ; Actually enable the IRQs ; Switch to User mode with interrupts enabled mrs ip, cpsr ; Get current value of CPSR into IP (R12) bic ip, ip, #(ARM_PSR_i | ARM_PSR_f | ARM_PSR_mode_mask) ; Mask out bottom 5 bits. Also clear I and F ; bits; this enables the interrupts orr ip, ip, #ARM_PSR_mode_usr ; Set User mode msr cpsr, ip ; Actually make the changes to CPSR b main ; Now in User mode; jump to the main program ; ----------------------------------------------------------------------- ; Stack space for the different processor modes .bss ; Use uninitialised memory for the stack .align ; Make sure the stack is word-aligned ; Technically, the stack should appear in its own section called ".stack". ; Doing it this way (using the ".bss" section), however, is easier. The ; ".bss" section is similar to the ".data" section, except that no values ; are actually stored in the final executable file. For that reason, the ; only assembler directives that make sense in the ".bss" section are ; ".align" and ".skip". If you do not understand this paragraph, ignore ; it. .skip 1024 ; Allow a 1KB stack for the User/System modes usr_stack_top: ; "usr_stack_top" points to top of this stack .skip 512 ; Allow 512 bytes stack for IRQ mode irq_stack_top: ; "irq_stack_top" points to top of this stack .skip 512 ; Allow 512 bytes stack for FIQ mode fiq_stack_top: ; "fiq_stack_top" points to top of this stack .skip 512 ; Allow 512 bytes stack for Supervisor mode svc_stack_top: ; "svc_stack_top" points to top of this stack .end