ARM Linux外部中断处理过程
rcc fp, [r4],#4
48 bcc 1b
49
50 str r9, [r6] @ Save processor ID
51 str r1, [r7] @ Save machine type
52 bic r2, r0, #2 @ Clear A bit
53 stmia r8, {r0, r2} @ Save control register values
54 b SYMBOL_NAME(start_kernel)
41~42行的结果是:r4=__bss_start,r5=__end,...,r8=cr_alignment,..,这里r8保存的是cr_alignment变量的地址.
到了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:
.align 5
__stubs_start:
vector_IRQ:
...
vector_data:
....
vector_prefetch:
...
vector_undefinstr:
...
vector_FIQ: disable_fiq
subs pc, lr, #4
vector_addrexcptn:
b vector_addrexcptn
...
__stubs_end:
.equ __real_stubs_start, .LCvectors + 0x200
.LCvectors: swi SYS_ERROR0
b __real_stubs_start + (vector_undefinstr - __stubs_start)
ldr pc, __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)
stmfd sp!, {r4 - r6, lr} /* 压栈,保存数据*/
/* 复制异常向量表(.LCvectors起始的8个地址)到r0指向的地址(异常向量地址),r0就是__trap_init(base)函数调用时传递的参数,不明白的请参考ATPCS*/(传递参数顺次利用r0,r1,r2,r3)
adr r1, .LCvectors @ set up the vectors
ldmia r1, {r1, r2, r3, r4, r5, r6, ip, lr}
stmia r0, {r1, r2, r3, r4, r5, r6, ip, lr}
/* 在异常向量地址后的0x200偏移处,放置散转代码,即__stubs_start~__stubs_end之间的各个异常处理代码*/
add r2, r0, #0x200
adr r0, __stubs_start @ copy stubs to 0x200
adr r1, __stubs_end
1: ldr r3, [r0], #4
str r3, [r2], #4
cmp r0, r1
blt 1b
LOADREGS(fd, sp!, {r4 - r6, pc}) /*出栈,恢复数据,函数__trap_init返回*/
__trap_init函数填充后的向量表如下:
虚拟地址 异常 处理代码
0xffff0000 reset swi SYS_ERROR0
0xffff0004 undefined b __real_stubs_start + (vector_undefinstr - __stubs_start)
0xffff0008 软件中断 ldr pc, __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)效率高。
ARMLinux外部中断处理过 相关文章:
- Windows CE 进程、线程和内存管理(11-09)
- RedHatLinux新手入门教程(5)(11-12)
- uClinux介绍(11-09)
- openwebmailV1.60安装教学(11-12)
- Linux嵌入式系统开发平台选型探讨(11-09)
- Windows CE 进程、线程和内存管理(二)(11-09)