Assembly code for creating interrupts vector on LPC2148 ARM processor-Collection of common programming errors
I’m going to remove the conditional code, since it just complicates things:
// Runtime Interrupt Vectors
// -------------------------
Vectors:
b _start // reset - _start
ldr pc,_undf // undefined - _undf
ldr pc,_swi // SWI - _swi
ldr pc,_pabt // program abort - _pabt
ldr pc,_dabt // data abort - _dabt
nop // reserved
ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
ldr pc,_fiq // FIQ - _fiq
_undf: .word __undf // undefined
_swi: .word __swi // SWI
_pabt: .word __pabt // program abort
_dabt: .word __dabt // data abort
_irq: .word __irq // IRQ
_fiq: .word __fiq // FIQ
__undf: b . // undefined
__swi: b . // SWI
__pabt: b . // program abort
__dabt: b . // data abort
__irq: b . // IRQ
__fiq: b . // FIQ
.size _boot, . - _boot
.endfunc
Lets look first at the reset/start vector:
b _start
That instruction is an unconditional branch (a jump) to the the code labeled “_start” which I don’t see in your snippet. Basically it’ll be the assembly that initializes the stack and processor registers, maybe some memory areas then probably jumps to a C routine that performs the bulk of the initialization.
Next is the “undefined” vector that the ARM will go to when an invalid instruction is executed (if my memory is right):
ldr pc, _undf
That instruction loads the pc
register (the ‘program counter’ or instruction pointer) with the address at the “_undf” symbol. If we look at the _undf
variable, it contains the address represented by symbol __undf
. So the ldr pc, _undf
instruction loads pc
with __undf
‘s address – jumping to __undf:
.
And at __undf
we see:
__undf: b .
That’s just a branch to the same address – an infinite loop (the .
symbol means ‘here’ or ‘this location’).
So for most of these vectors (which follow the same technique as the undefined vector), they’ll just jump to little infinite loops. You could replace the infinite loops at those labels with code that’s appropriate for the vector in question, though many projects don’t because those vectors firing would represent some sort of serious error.
Finally, the vector slot that’s most interesting is the IRQ vector:
ldr pc,[pc,#-0xFF0] // IRQ - read the VIC
This looks like the handler for an NXP device.
It loads the pc
register with the value read from a memory location that’s relative to the pc
register. Since on the ARM architecture the IRQ vector is always at address 0x00000018 (I’m going to ignore implementations that can map the vectors elsewhere or ARMs like the Cortex-M3 that use a different vector model) and because of the instruction pipeline’s effect on using the PC
register value for addressing, the memory location that will be read by this instruction will be 0xFFFFF030
, which is the address of the memory-mapped VICVectAddr
register in the ‘Vectored Interrupt Controller` (VIC):
'apparent' Pipeline offset in effective
PC value effect the opcode address
------------- ------------ ----------- ----------
0x00000018 + 0x00000008 - 0x0000ff0 == 0xfffff030
This device register will contain the address of the interrupt handler for the interrupt that just occurred (of course the VIC needs to be properly initialized so it knows that address).
So when the ldr pc,[pc,#-0xFF0]
instruction executes, it’ll load the pc
register with the address of the interrupt handler routine for the appropriate device (basically, jumping to the right interrupt handler).
Originally posted 2013-11-09 22:51:02.