首先了解一下什么是异常,异常就是因为内部或外部的一些事情,导致处理器停下正在处理的工作,转而去处理这些发生的事情。
ARM处理器支持7中类型的异常:复位、未定义指令、软中断、指令预取终止、数据访问终止、外部中断请求、快速中断请求。当一种异常发生的时候,ARM处理器会跳转到对应该异常的固定地址去执行异常处理程序,这个固定地址就成为异常向量。这7个异常向量及其处理函数跳转关系组成的表即为异常向量表或者中断向量表。一下是ARM处理器的异常向量表:
0x00000000 b reset
0x00000004 ldr pc,_undefined_instruction
0x00000008 ldr pc,_software_interrupt
0x0000000C ldr pc,_prefetch_abort
0x00000010 ldr pc,_data_abort
0x00000014 ldr pc, _not_used
0x00000018 ldr pc,_irq
0x0000001C ldr pc,_fiq
这个中断向量表指定了各异常中断向量及其处理程序的对应关系。它通常存放在存储地址的低端。在ARM体系中,异常向量表的大小为32字节。其中每个异常中断占据4个字节的大小,保留了4个字节的空间(设置0x00000014无用向量,防止后续向量地址被安排到此处,致使地址与向量错位)。每个异常中断对应的中断向量表中的4个字节的空间中存放了一个跳转指令或者一个向PC寄存器中赋值的数据访问指令。通过这两种指令,程序跳转到相应的异常中断处理程序出执行。
首先,当异常发生的时候我们应该用怎样的代码来处理。所以我们首先写出当异常发生的时候的处理代码,在此只写出处理代码的标号,具体操作用nop代替:
undefined_instruction:
nop
software_interurpt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
nop
fiq:
nop
reset:
nop
接下来设置异常向量表,当异常发生时,我们希望pc能够跳转到这些标号处,来执行相应的处理代码。
b reset
ldr pc,_undefined_instruction
ldr pc,_software_interrupt
ldr pc,_prefetch_abort
ldr pc,_data_abort
ldr pc,_irq
ldr pc,_fiq
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
至此完整的代码为:
.text
.global _satrt
_start:
b reset
ldr pc,_undefined_instruction
ldr pc,_software_interrupt
ldr pc,_prefetch_abort
ldr pc,_data_abort
ldr pc,_irq
ldr pc,_fiq
_undefined_instruction: .word undefined_instruction
_software_interrupt: .word software_interrupt
_prefetch_abort: .word prefetch_abort
_data_abort: .word data_abort
_not_used: .word not_used
_irq: .word irq
_fiq: .word fiq
undefined_instruction:
nop
software_interrupt:
nop
prefetch_abort:
nop
data_abort:
nop
not_used:
nop
irq:
nop
fiq:
nop
reset:
nop
编写连接器脚本:lboot.lds
OUTPUT_ARCH(arm)
ENTRY(_start)
SECTIONS{
. = 0x30008000;
. = ALIGN(4);
.text :
{
start.o (.text)
*(.text)
}
. = ALIGN(4);
.data :
{
*(.data)
}
. = ALIGN(4);
bss_start = .;
.bss :
{
*(.bss)
}
bss_end = .;
}
编写Makefile:
all:start.o
arm-linux-ld -Tlboot.lds -o lboot.elf $^
arm-linux-objcopy -O binary lboot.elfgboot.bin
%.o: %.S
arm-linux-gcc -g -c $^
%.o: %.c
arm-linux-gcc -g -c $^
.PHONY:clean
clean:
rm *.o *.elf *.bin