ARM Linux 中断向量表建立流程
地址.
到了53行,由于之前r0保存的是cp15的control register(c1)的值,这里把r0的值写入r8指向的地址,即cr_alignment=r0.到此为止,我们就看清楚了cr_alignment的赋值过程。
让我们回到trap_init()函数,经过上面的分析,我们知道vectors_base返回0xffff0000。函数__trap_init由汇编代码编写,在arch/arm/kernel/entry-arm.S:
.align5
__stubs_start:
vector_IRQ:
...
vector_data:
....
vector_prefetch:
...
vector_undefinstr:
...
vector_FIQ:disable_fiq
subspc, lr, #4
vector_addrexcptn:
bvector_addrexcptn
...
__stubs_end:
.equ__real_stubs_start, .LCvectors + 0x200
.LCvectors:swiSYS_ERROR0
b__real_stubs_start + (vector_undefinstr - __stubs_start)
ldrpc, __real_stubs_start + (.LCvswi - __stubs_start)
b__real_stubs_start + (vector_prefetch - __stubs_start)
b__real_stubs_start + (vector_data - __stubs_start)
b__real_stubs_start + (vector_addrexcptn - __stubs_start)
b__real_stubs_start + (vector_IRQ - __stubs_start)
b__real_stubs_start + (vector_FIQ - __stubs_start)
ENTRY(__trap_init)
stmfdsp!, {r4 - r6, lr}/* 压栈,保存数据*/
/* 复制异常向量表(.LCvectors起始的8个地址)到r0指向的地址(异常向量地址),r0就是__trap_init(base)函数调用时传递的参数,不明白的请参考ATPCS*/
adrr1, .LCvectors@ set up the vectors
ldmiar1, {r1, r2, r3, r4, r5, r6, ip, lr}
stmiar0, {r1, r2, r3, r4, r5, r6, ip, lr}
/* 在异常向量地址后的0x200偏移处,放置散转代码,即__stubs_start~__stubs_end之间的各个异常处理代码*/
addr2, r0, #0x200
adrr0, __stubs_start@ copy stubs to 0x200
adrr1, __stubs_end
1: ldrr3, [r0], #4
strr3, [r2], #4
cmpr0, r1
blt1b
LOADREGS(fd, sp!, {r4 - r6, pc})/*出栈,恢复数据,函数__trap_init返回*/
__trap_init函数填充后的向量表如下:
虚拟地址异常 处理代码
0xffff0000reset swi SYS_ERROR0
0xffff0004 undefined b__real_stubs_start + (vector_undefinstr - __stubs_start)
0xffff0008 软件中断 ldrpc, __real_stubs_start + (.LCvswi - __stubs_start)
0xffff000c 取指令异常b__real_stubs_start + (vector_prefetch - __stubs_start)
0xffff0010 数据异常 b__real_stubs_start + (vector_data - __stubs_start)
0xffff0014 reserved b__real_stubs_start + (vector_addrexcptn - __stubs_start)
0xffff0018 irq b__real_stubs_start + (vector_IRQ - __stubs_start)
0xffff001c fiq b__real_stubs_start + (vector_FIQ - __stubs_start)
当有异常发生时,处理器会跳转到对应的0xffff0000起始的向量处取指令,然后,通过b指令散转到异常处理代码.因为ARM中b指令是相对跳转,而且只有+/-32MB的寻址范围,所以把__stubs_start~__stubs_end之间的异常处理代码复制到了0xffff0200起始处.这里可直接用b指令跳转过去,这样比使用绝对跳转(ldr)效率高。
-------------------------参考资料--------------------
1, 刘淼,嵌入式系统接口设计与Linux驱动程序开发,北京航天航空大学出版社,2006.
2, ARM Architecture Reference Manual, ARM limited,2000.
http://jimmy-lee.blog.hexun.com/cate.aspx?cateid=7311&cate=ARM%26Linux
ARMLinux中断向量 相关文章:
- ARM Linux中断向量表搬移设计过程(11-09)
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)