微波EDA网,见证研发工程师的成长!
首页 > 硬件设计 > 嵌入式设计 > ARM Linux外部中断处理过程

ARM Linux外部中断处理过程

时间:11-20 来源:互联网 点击:

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)效率高。


Copyright © 2017-2020 微波EDA网 版权所有

网站地图

Top