[Click here to download a sample complete project for arm. It uses gnuarm's arm-elf- toolchain for compilation and qemu emulator for to emulate]
This post is very much linked with my previous post arm-elf toolchain rough notes of my works...
Actually on powerON or reset, arm will start fetching and executing instructions from 0x00000000. As arm processes 32 bit instructions, each time PC is incremented by 4. like 0x00000000 0x00000004 0x0000000C like that....
In arm there are 7 type of interrupts (also called exceptions)....
So when any of the interrupt occurs PC will get loaded with a specific address which is a specific address which contains an instruction which has to be executed when that interrupt occurs. So that vector address should contain an instruction which handles the interrupt. Mostly it will be a branch instruction to the ISR(interrupt service routine) as shown below. It is normally a part of the so called boot code. Boot code is explained in my earlier post arm-elf toolchain rough notes of my works...
b RESET_HANDLER
b UNDEF_HANDLER
b SWI_HANDLER
b PREFETCH_ABORT_HANDLER
b DATA_ABORT_HANDLER
b RESERVED_HANDLER
b IRQ_HANDLER
Stack organisation
For each processor mode I have got a stack pointer. Each processor mode has got a different stack. What is its meaning ?
This post is very much linked with my previous post arm-elf toolchain rough notes of my works...
Actually on powerON or reset, arm will start fetching and executing instructions from 0x00000000. As arm processes 32 bit instructions, each time PC is incremented by 4. like 0x00000000 0x00000004 0x0000000C like that....
In arm there are 7 type of interrupts (also called exceptions)....
So when any of the interrupt occurs PC will get loaded with a specific address which is a specific address which contains an instruction which has to be executed when that interrupt occurs. So that vector address should contain an instruction which handles the interrupt. Mostly it will be a branch instruction to the ISR(interrupt service routine) as shown below. It is normally a part of the so called boot code. Boot code is explained in my earlier post arm-elf toolchain rough notes of my works...
b RESET_HANDLER
b UNDEF_HANDLER
b SWI_HANDLER
b PREFETCH_ABORT_HANDLER
b DATA_ABORT_HANDLER
b RESERVED_HANDLER
b IRQ_HANDLER
Stack organisation
Now To do all these exception handling stack organisation is important...
For each processor mode I have got a stack pointer. Each processor mode has got a different stack. What is its meaning ?
See the Register set in arm. R13 is the stack pointer which contains the address of the memory location which is the base of the stack. So for each mode there is a separate R13 and which has to be updated with the memory location which is going to be used as the base of stack for that mode. So for that we need to manually change the processor to each mode then R13_** of that mode will become visible so that we can update that stack pointer with base address of stack for that particular mode.
The code for initialise_stack is explained in my earlier post arm-elf toolchain rough notes of my works...
In the above figure bits 0-4 represents the mode. As it is in Supervisor mode now we will update SP(stack pointer) of this mode now itself ;SUPERVISOR_MODE
ldr SP,=0x1000 ;check the code
ldr SP,=0x1000 ;check the code
Next is we need to change to abort mode to update SP of that mode. which comes in the next piece of code.
.equ ABT, 0x17
.equ M_MODE, 0x1F
mrs r0,CPSR
bic r0,r0,#M_MODE
orr r0,r0,#ABT
msr CPSR,r0
ldr SP,=0x2000
To change to abort mode mode bits should be '0111' which is nothing but 7 of 0x17. The 1 in '0x17' is '0001'in binary which means T is enabled and (I,F) external interrupt pins are disabled for now to initialise the system.
Like this we will go to each mode to update the SP for that mode and finally to the user mode. Once user mode is entered the only way to go to any privileged mode is either through interrupt or SWI.
Digest: boot code + stack init code + user program(main) = elf for ARM