您的位置:首页 > 其它

ARM中断进入和退出分析

2014-08-09 16:01 323 查看
个人觉得中断进入和退出比较重要,本文是根据:杜春雷的《ARM体系结构与编程》中第九章 异常中断处理 整理而来
0x00复位(reset): 1
svc

复位引脚有效产生复位异常中断,程序跳转到子程序执行;复位情况加电,复位按键;直接跳转到复位中断服务子程序

0x04未定义指令(undefined instruction):6 und

0x08软件中断:用户自定义的中断指令,目的是为了获取到特权 6 svc

0x0c指令预取中止 5 abt

0x10数据访问中止 2 abt

0x14

0x18外部中断请求(IRQ) 4 fiq

0x1c快中断请求(FIQ) 3 irq



0b10000 usr

0b10001 FIQ

0b10010 irq

0b10011 supervisor

0b10111 abort

0b11011 undefined

0b11111 system



中断向量表大小是32字节,每个中断占4字节。里面存放跳转指令,使pc跳转到服务子程序入口地址。



处理器对异常中断响应过程:



保存当前处理器的状态寄存器cpsr的 内容保存到异常发生的spsr内。

设置当前cpsr:m0-m4进入相应模式;t 位:thumb还是arm;fiq 置1禁止;irq置1禁止;

FIQ中断比IRQ中断优先级高,如果进入IRQ中断,可以不禁止FIQ;但如果是FIQ中断,则要屏蔽所有中断。

设置lr为返回地址,pc赋值跳转到相应的子程序;



1. 复位中断

当处理器复位引脚有效时,产生复位中断,处理器中止当前指令,当引脚无效时,处理器执行中断现场保护。

Lr_(svc/und/abt/irq/fiq) = addr + 4 //保存返回地址

Spsr_(svc/und/abt/irq/fiq)=cpsr //保存当前处理器状态

Cpsr[4:0] = 0x…. //设置模式(进入中断对应的特权模式)

Cpsrp[5] = 0 //设置ARM模式(1:thumb模式)

If<exception_mode> == reset or fiq

Cpsr[6] = 1 /如果是快中断或复位则禁止该中断(因为快中断优先级高)

Cpsr[7] = 1 //无条件禁止快中断

Pc = 0x… //跳转到中断子程序入口地址

上面的操作是cpu完成的。



下面现场恢复是有程序员完成的;

从异常中断中返回

1. 恢复中断前的处理器状态,spsr_mode 内容复制到cpsr中;

2. 返回到发生异常中断的指令的下一条指令去执行,lr_mode寄存器内容复制到pc

3. 复位中断不要返回;



==================================================

SWI和未定义指令异常:



ARM9处理器的三级流水线

Pc : 取值(表示指令a正在被取值,接下来是译码,然后执行)

Pc -4 译码

Pc – 8 执行



pc永远指向正在取值的指令



Pc = 当前执行指令 + 8

未定义指令和swi软件中断指令返回的地址是:mov pc, lr_mode;

因为在中断发生时,ld_mode = pc – 4;就是把现在执行的指令的下一条指令保存,也即是把译码的指令地址保存起来。

因为undefined/swi中断发生时,pc没有更新。

所以ld_mode = pc -4;保存的是下一条要执行的指令



==========================================================

FIQ、IRQ异常:

处理器是执行完当前指令后再去检查是否有irq/fiq中断

Irq/FIQ中断时先执行当前执行,然后查询IRQ/FIQ中断引脚,已经判断是否允许irq/fiq中断。只有引脚有效和系统允许才发生异常中断。所以当irq和fiq中断发生时,pc的值已经改变了。指向当前中断指令的后面第三个:pc – 12;



更新前:正在执行irq/fiq要发生的指令

取值 译码 执行

Pc + 4:a

Pc : b

Pc – 4: c

Pc – 8: d



更新后:irq/fiq已经发生

取值 译码 执行

Pc + 4:

Pc : a

Pc – 4: b

Pc – 8: c(没有执行因为有中断,但是已经在执行的队列中)

执行过:pc – 12 d



当发生异常时先把pc – 4 的值保存到lr_mode寄存器中:指向中断发生指令后的第2条指令;

所以:subs pc,lr,#4 ;==》pc = lr – 4,lr =pc -4 è 返回给pc
= pc -8;

如果最后要直接用堆栈调用pc则存入堆栈时要把lr再减4;(因为处理器保存的pc-4,跳转要pc - 8)

Subbs lr,lr,#4

Stmfd sp!,(reglist,lr)

..

Ldmfd sp!,{reglist,pc}^

=====================================================================

指令预取中止:

指令预取中止异常:在指令预取时,如果目标地址是非法的,该指令将被标记是有问题的。

流水线上之前的指令继续执行,当执行到有问题的指令时,处理器产生预取值指令中止异常中断;预取指令中止的服务子程序最后是要返回到出问题的指令地址,再次执行。

预取值指令中断是指令本身问题,所以pc的值没有更新值,所以pc指向当前执行指令的后第二个。处理器保存的是pc
-4即:指向当前问题指令(执行指令)的下一条;因为要返回有问题指令(即当前指令)所以要再减4,操作和上面相同;



===================================================================

数据访问中止异常:

和上面的预取指令异常一样,最后中断子程序都要返回到出问题的指令地址上再次执行。但是不同的是预取指令中止异常时pc的值没有更新,而数据访问中止异常pc已经更新了。所以处理器保存在lr的pc-4是指向问题指令的后两条,要返回到问题指令,所以还得lr-8。自己可以画下流水线图。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: