linux for arm的中断处理流程[转载自:http://hi.baidu.com/wudx05/blog/item/5314935c834f4e41fbf2c0dc.html]

本文介绍了Linux for ARM平台上的中断处理流程,包括中断向量表的位置及其处理机制。详细解析了中断向量表如何被放置在内存特定位置,硬件中断如何找到对应的中断入口函数,以及进入中断模式后的工作流程。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

linux for arm的中断处理流程
2007-06-24 20:54

Armor的中断向量表放在内存的什么位置?

中断向量表放在arch/arm/kernel/entry-armv.S这个文件里

__vectors_start:
#swi SYS_ERROR0
b vector_addrexcptn + stubs_offset
b vector_und + stubs_offset
ldr pc, .LCvswi + stubs_offset
b vector_pabt + stubs_offset
b vector_dabt + stubs_offset
b vector_addrexcptn + stubs_offset
b vector_irq + stubs_offset
b vector_fiq + stubs_offset

.globl __vectors_end
__vectors_end:

在arch/arm/traps.c中

     memcpy((void *)0xffff0000, __vectors_start, __vectors_end - __vectors_start);   //中断向量表被拷贝到0xffff0000处,硬件规定的位置
memcpy((void *)0xffff0200, __stubs_start, __stubs_end - __stubs_start);

 

硬件发生中断后怎样找到中断入口函数的?

从上面的中断向量表中可 以看到,发生中断时系统会跳到 vector_irq + stubs_offset处运行,这个位置实际上就是中断入口函数。vector_irq已经是中断的入口函数了,为什么又要加上 stubs_offset?是因为b指令实际上是相对相前PC的跳转,也就是说当汇编器看到B指令后会把要跳转的标签转化为相对于当前PC的偏移量写入指 令码。从上面的代码可以看到中断向量表和stubs都发生了代码搬移,所以如果中断向量表中仍然写成b vector_irq,那么实际执行的时候就无法跳转到搬移后的vector_irq处,因为指令码里写的是原来的偏移量,所以需要把指令码中的偏移量写 成搬移后的。我们把搬移前的中断向量表中的irq入口地址记irq_PC,它在中断向量表的偏移量就是irq_PC-vectors_start, vector_irq在stubs中的偏移量是vector_irq-stubs_start,这两个偏移量在搬移前后是不变的。搬移后 vectors_start在0xffff0000处,而stubs_start在0xffff0200处,所以搬移后的vector_irq相对于中断 向量中的中断入口地址的偏移量就是,200+vector_irq在stubs中的偏移量再减去中断入口在向量表中的偏移量,即200+ vector_irq-stubs_start-irq_PC+vectors_start = (vector_irq-irq_PC) + vectors_start+200-stubs_start,对于括号内的值实际上就是中断向量表中写的vector_irq,减去irq_PC是由汇 编器完成的,而后面的 vectors_start+200-stubs_start就应该是stubs_offset,实际上在entry-armv.S中也是这样定义的

进入中断后在irq模式完成什么工作?

vector_irq是通过宏来vector_stub定义的:

        .macro  vector_stub, name, mode, correction=0
.align 5
vector_/name:
.if /correction
sub lr, lr, #/correction
.endif

@
@ Save r0, lr_<exception> (parent PC) and spsr_<exception>
@ (parent CPSR)
@
stmia sp, {r0, lr} @ save r0, lr
mrs lr, spsr
str lr, [sp, #8] @ save spsr

@
@ Prepare for SVC32 mode. IRQs remain disabled.
@
mrs r0, cpsr
eor r0, r0, #(/mode ^ SVC_MODE)
msr spsr_cxsf, r0

@
@ the branch table must immediately follow this code
@
and lr, lr, #0x0f
mov r0, sp
ldr lr, [pc, lr, lsl #2]
movs pc, lr @ branch to handler in SVC mode
.endm

vector_stub irq, IRQ_MODE, 4
.long __irq_usr @ 0 (USR_26 / USR_32)
.long __irq_invalid @ 1 (FIQ_26 / FIQ_32)
.long __irq_invalid @ 2 (IRQ_26 / IRQ_32)
.long __irq_svc @ 3 (SVC_26 / SVC_32)
.long __irq_invalid @ 4
......

从 上面这段代码可以看出,vector_irq把发生中断时的r0,PC-4以及CPSR压栈(注意,压入的的irq模式的堆栈),把中断栈的栈指针赋给 r0,最后根据原来发生中断时CPU所处的工作模式(CPSR的低4位)找到相应的入口函数,在进入svc模式后进一步处理中断。

__irq_usr完成的工作是什么?

它主要通过调用宏usr_entry进一步保存现场,然后调用irq_handler进行中断处理,保存的栈结构如下:

-1

CPSR

PC-4

LR

SP

R12

...

R2

R1

R0

其中的LR,SP是USR模式下的,R0,CPSR,PC-4是从中断栈中拷贝的

irq_handler的作用是什么?

  • 它首先通过宏 get_irqnr_and_base获得中断号,存在r0,然后把上面建立的pt_regs结构的指针,也就是sp值赋给r1,把调用宏 get_irqnr_and_base的位置作为返回地址(为了处理下一个中断???)然后调用 asm_do_IRQ进一步处理中断,以上这些操作都在建立在获得中断号的前提下,也就是有中断发生
  • 代码实现

 

.macro  irq_handler
1: get_irqnr_and_base r0, r6, r5, lr
movne r1, sp
@
@ routine called with r0 = irq number, r1 = struct pt_regs *
@
adrne lr, 1b
bne asm_do_IRQ

.endm

具体的中断处理会在asm_do_IRQ根据中断号调用相应的中断处理程序完成。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值