Fork me on GitHub

9. Exception Handling

The examples given so far have a major bug. The first 8 words in the memory map are reserved for the exception vectors. When an exception occurs the control is transferred to one these 8 locations. The exceptions and their exception vector addresses are show in the following table.

Table 1. Exception Vector Addresses

Exception Address

Reset

0x00

Undefined Instruction

0x04

Software Interrupt (SWI)

0x08

Prefetch Abort

0x0C

Data Abort

0x10

Reserved, not used

0x14

IRQ

0x18

FIQ

0x1C


These locations are supposed to contain a branch that will transfer control the appropriate exception handler. In the examples we have seen so far, we haven’t inserted branch instructions at the exception vector addresses. We got away without issues since these exceptions did not occur. All the above programs can be fixed, by linking them with the following assembly code.

        .section "vectors"
reset:  b     start
undef:  b     undef
swi:    b     swi
pabt:   b     pabt
dabt:   b     dabt
        nop
irq:    b     irq
fiq:    b     fiq

Only the reset exception is vectored to a different address start. All other exceptions are vectored to the same address. So if any exception other that reset occurs, the processor will be spinning in the same location. The exception can then be identified by looking at the value of pc through a debugger (the monitor interface in our case).

To ensure that these instruction are placed at the exception vector addresses, the linker script should look something like below.

SECTIONS {
        . = 0x00000000;
        .text : {
                * (vectors);
                * (.text);
                ...
        }
        ...
}

Notice how the vectors section is placed before all other code, ensuring that the vectors is located at address starting from 0x0.