在介绍arm处理器异常中断处理过程之前,先看一下arm寄存器的基本情况。
从这个博客引用一些知识点:
R0~R7:在所有模式下对应的物理寄存器都是相同的,在中断或者异常处理程序中需要对这几个寄存器的数据进行保存;
R8~R12:fiq模式下一组物理寄存器,其余模式下一组物理寄存器;
R13、R14:用户、系统模式共享一组寄存器,其余每个模式各一组寄存器。
R13(SP指针)即栈指针,系统初始化时需对所有模式的SP指针赋值,MCU工作在不同模式下时,栈指针会自动切换;
R14:1、调用子程序时用于保存调用返回地址,2、发生异常时用于保存异常返回地址
R15(程序计数器PC):可以用作通用寄存器(未验证,一旦使用后果自负),部分指令在使用R15时有特殊限制(暂不清楚是哪些指令);
其中状态寄存器cpsr是这样的:
CPSR(当前程序状态寄存器):所有模式下可读写
条件标志位如下
N:Negative,负标志
Z:Zero,0
C:Carry,进位
V:Overflow,溢出
中断标志位如下:
I:1表示禁止IRQ中断响应,0表示允许IRQ中断响应
F:1表示禁止FIQ中断响应,偶表示允许FIQ中断响应
ARM/Thumb控制标志位:
T:0表示执行32 bits的ARM指令,1表示执行16 bits的Thumb指令
模式控制位M0~M4:有了上面知识以后,再来看一下arm的中断向量是如何分布的。根据协处理器中的中断向量标志位,选择中断向量放在0x0地址还是0xffff0000地址。如果放在0地址,中断向量的地址和优先级如下:
异常类型 优先级 工作模式 异常向量地址
复位 RESET 1 管理模式 0x00000000
未定义的指令 UND 6 未定义指令的终止模式 0x00000004软件中断 SWI 6 管理模式 0x00000008
指令预取中止 PABT 5 中止模式 0x0000000C
数据访问中止 DABT 2 中止模式 0x00000010
外部中断请求 IRQ 4 外部中断模式 0x00000018
快速中断请求 FIQ 3 快速中断模式 0x0000001C
有了这些基础知识以后,看一下arm处理器如何处理中断响应:1 arm处理器对异常中断的响应过程
arm处理器对异常中断的响应过程如下:
(1)保存处理器的当前状态,中断屏蔽位以及各条件标志位。这是通过将当前程序状态寄存器cpsr的内容保存到将要执行的异常中断对应的spsr寄存器中实现的,各异常中断有自己的物理spsr寄存器。
(2)设置当前程序状态寄存器cpsr中相应的位。使处理器进入相应的执行模式,并屏蔽中断。
(3)将寄存器lr_mode 设置成返回地址。
(4)将pc设置成该 异常的中断向量入口地址,跳转到相应的异常中断处理程序执行。
具体看各个异常如何处理,下面只分析swi异常中断,irq异常中断,以及数据访问终止异常中断。
1.1 响应swi异常中断(系统调用)
用如下伪代码描述:
R14_srv = address of next instruction after the SWI instruction
SPSP_svc = CPSR
//进入特权模式
CPSR[4:0]=0b10011
//切换到arm状态
CPSR[5]=0
//禁止IRQ异常中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF0008
else
PC=0x00000008
1.2 响应数据访问中止异常中断
用如下伪代码描述:
R14_srv = address of the aborted instruction +8
SPSP_abt = CPSR
//进入特权模式
CPSR[4:0]=0b10111
//切换到arm状态
CPSR[5]=0
//禁止IRQ异常中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF0010
else
PC=0x00000010
1.3 响应IRQ异常中断
用如下伪代码描述:
R14_irq = address of next instruction to be executed +4
SPSP_abt = CPSR
//进入特权模式
CPSR[4:0]=0b10111
//切换到arm状态
CPSR[5]=0
//禁止IRQ异常中断
CPSR[7]=1
if high vectors configured then
PC=0xFFFF0010
else
PC=0x00000010
2 从异常中断处理器程序中返回
为了理解ARM异常发生的时候,填写在LR寄存器中的返回地址的不同,先看一下ARM流水线的概念:
流水线技术通过多个功能部件并行工作来缩短程序执行时间,提高处理器核的效率和吞吐率,从而成为微处理器设计中最为重要的技术之一。也就是说,通过划分指令执行过程中的不同阶段,并通过并行执行,从而提高指令的执行效率。ARM7处理器采用了三级流水线结构,包括取指(fetch)、译码(decode)、执行(execute)三级。
如上图所示,在执行add r0, r1, #5指令时,第二条指令正在译码阶段,而第三条指令正在取指阶段。在执行第一条指令时,PC寄存器应指向第三条指令。也即,当处理器为三级流水线结构时,PC寄存器总是指向随后的第三条指令。
当处理器处于ARM指令集状态时,每条指令4字节,所以PC得值为当前指令地址+8
此外,在ARM9中,采用了五级流水线结构,是在ARM7的三级流水线结构后面添加了两个新的过程。因此,指令的执行过程和取指过程还是相隔一个译码过程,因而PC还是指向当前指令随后的第三条指令。
从异常中断处理程序中返回包括下面两个基本操作:
(1) 恢复被中断的程序的处理器状态,即将SPSR_mode 寄存器内容复制到当前的状态寄存器CPSR中。
(2)返回到发生异常中断的指令的下一条指令处执行,即将lr_mode 寄存器的内容复制到PC中。
下面详细介绍各种异常的返回处理。
2.1 SWI 和未定义指令异常中断处理程序的返回
SWI 和未定义指令异常中断是由当前执行的指令自身产生的,当SWI 和未定义指令异常中断产生时,PC的值还没有更新,它指向当前指令后面第二条指令(对于arm指令集来说,它指向当前执行的指令地址加8个字节的位置),这时中断发生,处理器会把PC-4保存到异常模式下的寄存器lr_mode中。这时PC-4 即指向当前指令的下一条指令。所以返回操作可以直接使用如下指令实现:
MOVS PC,LR s后缀会把SPSR_mode寄存器替换CPSR
2.2 IRQ 和FIQ异常中断处理程序的返回
通常处理器执行完当前指令以后,查询是否有IRQ和FIQ到来。如果有中断产生,PC值已经更新,它指向当前指令后面第三条指令(ARM指令集是当前指令地址加12个字节的位置),然后处理器会将PC-4 保存到异常模式下的寄存器lr_mode中。这时PC-4
即指向当前指令后的第二条指令,因此返回操作可通过下面的指令实现:
SUBS PC,LR ,#4
先将LR指令减4,赋值到PC中,同时把SPSR_mode寄存器替换CPSR
2.3 数据访问中止异常中断处理程序的返回
当发生数据访问中止异常中断时(比如缺页异常),程序在处理完异常地址以后,需要返回到该有问题的数据访问处,重新访问该数据。因此数据访问中止异常程序应该返回到产生该数据访问中止异常中断的指令处,而不是像前面两种情况下返回到当前指令的下一条指令。
数据范文中止异常中断是由数据访问指令产生的,当数据访问中止异常中断产生时,程序计数器已经更新,它指向当前指令后面的第二条指令(当前指令指的是异常指令的后一条指令),然后处理器会将PC-4保存到异常模式下的lr_mode中,PC-4 即为当前指令后面那条指令。所以要返回那条异常指令重新执行,lr寄存器必须要减去8
SUBS PC,LR,#8