为何要减去4?我的理解是这样的(不一定对)。由于ARM采用流水线结构,当CPU正在执行某一条指令的时候,其实取指的动作早就执行了,这时候PC值=正在执行的指令地址 + 8,如下所示:
----> 发生中断的指令
发生中断的指令+4
-PC-->发生中断的指令+8
发生中断的指令+12
一旦发生了中断,当前正在执行的指令当然要执行完毕,但是已经完成取指、译码的指令则终止执行。当发生中断的指令执行完毕之后,原来指向(发生中断的指令+8)的PC会继续增加4,因此发生中断后,ARM core的硬件着手处理该中断的时候,硬件现场如下图所示:
----> 发生中断的指令
发生中断的指令+4 <-------中断返回的指令是这条指令
发生中断的指令+8
-PC-->发生中断的指令+12
这时候的PC值其实是比发生中断时候的指令超前12。减去4之后,lr_irq中保存了(发生中断的指令+8)的地址。为什么HW不帮忙直接减去8呢?这样,后续软件不就不用再减去4了。这里我们不能孤立的看待问题,实际上ARM的异常处理的硬件逻辑不仅仅处理IRQ的exception,还要处理各种exception,很遗憾,不同的exception期望的返回地址不统一,因此,硬件只是帮忙减去4,剩下的交给软件去调整。
3、mask IRQ exception。也就是设定CPSR.I = 1
4、设定PC值为IRQ exception vector。基本上,ARM处理器的硬件就只能帮你帮到这里了,一旦设定PC值,ARM处理器就会跳转到IRQ的exception vector地址了,后续的动作都是软件行为了。
四、如何进入ARM中断处理
1、IRQ mode中的处理
IRQ mode的处理都在vector_irq中,vector_stub是一个宏,定义如下:
.macro vector_stub, name, mode, correction=0
.align 5
vector_\name:
.if \correction
sub lr, lr, #\correction-------------(1)
.endif
@
@ Save r0, lr_ (parent PC) and spsr_
@ (parent CPSR)
@
stmia sp, {r0, lr} @ save r0, lr--------(2)
mrs lr, spsr
str lr, [sp, #8] @ save spsr
@
@ Prepare for SVC32 mode. IRQs remain disabled.
@
mrs r0, cpsr-----------------------(3)
eor r0, r0, #(\mode ^ SVC_MODE | PSR_ISETSTATE)
msr spsr_cxsf, r0
@
@ the branch table must immediately follow this code
@
and lr, lr, #0x0f---lr保存了发生IRQ时候的CPSR,通过and操作,可以获取CPSR.M[3:0]的值
这时候,如果中断发生在用户空间,lr=0,如果是内核空间,lr=3
THUMB( adr r0, 1f )----根据当前PC值,获取lable 1的地址
THUMB( ldr lr, [r0, lr, lsl #2] )-lr根据当前mode,要么是__irq_usr的地址 ,要么是__irq_svc的地址
本文来自电脑杂谈,转载请注明本文网址:
http://www.pc-fly.com/a/jisuanjixue/article-76601-6.html
先转再看
中国几十年前就打过3--4次好不好
别太当回事