ARM架构异常中断处理流程

在ARM体系中通常有以下3种方式控制程序的执行流程:

  • 在正常程序执行过程中,每执行一条ARM指令,程序计数器寄存器(PC)的值加4个字节;每执行一条Thumb指令,程序计数器寄存器(PC)的值加两个字节。整个过程是顺序执行。
  • 通过跳转指令,程序可以跳转到特定的地址标志处执行,或者跳转到特定的子程序处执行。其中,B指令用于执行跳转操作;BL指令在执行跳转动作的同时,保存子程序的返回地址;BX指令在执行跳转操作的同时,根据目标地址的最低位可以将程序状态切换到Thumb状态;BLX指令执行3个操作:跳转到目标地址处执行,保存子程序的返回地址,根据目标地址的最低位可以将程序状态切换到Thumb状态。
  • 当异常中断发生时,系统执行完当前指令后,将跳转到相应的异常中断处理程序处执行。当异常中断处理程序执行完成后,程序返回到发生中断的指令的下一条指令处执行。在进入异常中断处理程序时,要保存被中断的程序的执行现场,在从异常中断处理程序退出时,要恢复被中断的程序的执行现场。本文讨论ARM体系中的异常中断机制。

ARM体系中异常中断种类:

ARM体系中异常中断如下面的介绍。

复位(Reset):当处理器的复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行。复位异常中断通常用在下面两种情况下:系统加电时,系统复位时,跳转到复位中断向量处执行,称为软复位。

未定义指令(Undefined):当ARM处理器或者是系统中的协处理器认为当前指令未定义时,产生未定义的指令异常中断。可以通过该异常中断机制仿真浮点向量运算。

软中断(software interrupt):这是一个由用户定义的中断指令。可用于用户模式下的程序调用特权操作指令。在实时操作系统(RTOS)中可以通过该机制实现系统功能调用。

指令预取中止:如果处理器预取的指令的地址不存在,或者该地址不允许当前指令访问,当该被预取的指令执行时,处理器产生指令预取中止异常中断。

数据访问中止:如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问中止异常中断。

外部中断请求(IRQ):当处理器的外部中断请求引脚有效,而且CPSR寄存器中的I控制位被清除时,处理器产生外部中断请求异常中断。系统中各个外设通常通过该异常中断请求处理器服务。

快速中断请求(FIQ):当处理器的外部快速中断请求引脚有效,而且CPSR寄存器中的F控制位被清除时,处理器产生外部中断请求(FIQ)异常中断。

异常中断向量表及异常中断优先级:

中断异常向量表中指定了个异常中断及其处理程序的对应关系。它通常存放在存储地址的低端。在ARM体系中,异常中断向量表的大小为32个字节。其中,每个异常中断占据4个字节大小,保留4个字节空间。

每个异常中断对应的中断向量表中的4个字节的空间中存放了一个跳转指令或者一个向PC寄存器中赋值的数据访问指令。通常这两种指令,程序将跳转到相应的异常中断处理程序处执行。

当几个异常中断同时发生时,就必须按照一定的次序来处理这些异常中断。在ARM中通过给异常中断赋予一定的优先级来实现这种处理次序。当然有异常中断是不可能同时发生的,如指令预取中止异常和软中断(SWI)异常中断是由同一条指令的执行触发的,它们是不可能同时发生的。处理器执行某个特定的异常中断的过程中,称为处理器处于特定的中断模式。各异常中断的中断向量地址以及中断的处理优先级如下表所示。

中断向量地址 异常中断类型 异常中断模式 优先级
0x0 复位 特权模式(SVC) 1
0x4 未定义指令 未定义指令中止模式 6
0x8 软中断(SWI) 特权模式(SVC) 6
0xC 指令预取中止 中止模式 5
0x10 数据访问中止 中止模式 2
0x14 保留 未使用 未使用
0x18 外部中断请求 外部中断模式 4
0x1C 快速中断请求 快速中断模式 3

异常中断使用的寄存器:

各异常中断对应着一定的处理器模式。应用程序通常运行在用户模式下。ARM中的处理器模式如下表所示。

处理器模式 描述
用户模式(user) 正常程序执行的模式
快速中断模式(FIQ) 用于高速数据传输和通道处理
外部中断模式(IRQ) 用于通常的中断处理
特权模式(SVC) 供操作系统使用的一种保护模式
中止模式(abort) 用于虚拟存储及存储保护
未定义指令模式(undefined) 用于支持软件仿真硬件的协处理器
系统模式(system) 用于运行特权级的操作系统任务

各种不同的处理器模式可能有对应于该处理器模式的物理寄存器组,如下表所示。其中R13_svc表示特权模式下的R13寄存器,R13_abt表示中止模式下的R13寄存器,其余的各寄存器名称含义类推。

ARM架构异常中断处理流程_第1张图片

如果异常中断处理程序中使用它自己的物理寄存器之外的其他寄存器,异常中断处理程序必须保存和恢复这些寄存器。在上表中各物理寄存器名称在ARM汇编中并没有被预定义。用户使用这些寄存器时,必须使用伪操作RN来定义这些名称。如可以通过下面操作定义寄存器名称R13_svc:

R13_svc RN R13

进入和退出异常中断的过程:

下面介绍处理器对于各种异常中断的响应过程以及从异常中断处理程序中返回的方法。对于不同的异常中断处理程序,返回地址以及使用的指令是不同的。

ARM处理器对异常中断的响应过程如下:

(1).保存处理器当前状态、中断屏蔽位以及各条件标志位。这是通过将当前程序状态寄存器CPSR的内容保存到将要执行的异常中断对应的SPSR寄存器中实现的。各异常中断有自己的物理SPSR寄存器。
(2).设置当前程序状态寄存器CPSR中相应的位。包括设置CPSR中的位,使处理器进入相应的执行模式;设置CPSR中的位,禁止IRQ中断,当进入FIQ模式时,禁止IRQ中断。
(3).将寄存器lr_mode设置成返回地址。
(4).将程序计数器(PC)值,设置成该异常中断的中断向量地址,从而跳转到相应的异常中断处理程序处执行。
上述的处理器对异常中断的响应过程可以用如下的伪代码描述。

R14_ = return link
SPSR_ = CPSR
CPSR[4:0] = exception mode number
/* 当运行于ARM状态时 */
CPSR[5] = 0
/* 当相应FIQ异常中断时,禁止新的FIQ中断 */
if  == RESET or FIQ then
CPSR[6] = 1
/* 禁止新的FIQ中断 */
CPSR[7] = 1
PC = exception vector address

1.响应复位异常中断
当处理器的复位引脚有效时,处理器终止当前指令。当处理器的复位引脚变成无效时,处理器开始执行下面的操作。

R14_svc = UNPREDICATBLE value
SPSR_svc = UNPREDICATBLE value
/* 进入特权模式 */
CPSR[4:0] = 0b10011
/* 切换到ARM状态 */
CPSR[5] = 0
/* 禁止FIQ异常中断 */
CPSR[6] = 1
/* 禁止IRQ中断 */
CPSR[7] = 1
if high vectors configured then
PC = 0XFFFF0000
else
PC = 0X00000000

2.响应未定义指令异常中断
处理器响应未定义指令异常中断时的处理过程如下面的伪代码所示。

R14_und = address of next instruction after the undefined instruction
SPSR_und = CPSR
/* 进入未定义指令异常中断 */
CPSR[4:0] = 0b11011
/* 切换到ARM状态 */
CPSR[5] = 0
/* CPSR[6]不变 */
/* 禁止IRQ异常中断 */
CPSR[7] = 1
if high vectors configured then
PC = 0xFFFF0004
else 
PC = 0x00000004

3.响应SWI异常中断
处理器响应SWI异常中断的处理过程如下面的伪代码所示。

R14_svc = address of next instruction after the SWI instruction
SPSR_svc = CPSR
/* 进入特权模式 */
CPSR[4:0] = 0b10011
/* 切换到ARM状态 */
CPSR[5] = 0
/* CPSR[6]不变 */
/* 禁止IRQ异常中断 */
CPSR[7] = 1
if high vectors configured then
PC = 0xFFFF0008
else 
PC = 0x00000008

4.响应指令预中止异常中断
处理器响应指令预取中止异常中断时的处理过程如下面的伪代码所示。

R14_abt = address of the aborted instruction+4
SPSR_abt = CPSR
/* 进入指令预取中止模式 */
CPSR[4:0] = 0b10111
/* 切换到ARM状态 */
CSPR[5] = 0
/* CPSR[6]不变 */
/* 禁止IRQ异常中断 */
CPSR[7] = 1
if high vectors configured then
PC = 0xFFFF000C
else 
PC = 0x0000000C

5.响应数据访问中止异常中断
处理器响应数据访问中止异常中断时的处理过程如下面的伪代码所示。

R14_abt = address of the aborted instruction+8
SPSR_abt = CPSR
/* 进入数据访问中止 */
CPSR[4:0] = 0b10111
/* 切换到ARM状态 */
CSPR[5] = 0
/* CPSR[6]不变 */
/* 禁止IRQ异常中断 */
CPSR[7] = 1
if high vectors configured then
PC = 0xFFFF0010
else 
PC = 0x00000010

6.响应IRQ异常中断
处理器响应IRQ异常中断时的处理器过程如下面的伪代码所示。

R14_irq = address of next instruction to be executed + 4
SPSR_irq = CPSR
/* 进入IRQ异常中断模式 */
CPSR[4:0] = 0b10010
/* 切换到ARM状态 */
CSPR[5] = 0
/* CPSR[6]不变 */
/* 禁止IRQ异常中断 */
CPSR[7] = 1
if high vectors configured then
PC = 0xFFFF0018
else 
PC = 0x00000018

7.响应FIQ异常中断
处理器响应FIQ异常中断时的处理器过程如下面的伪代码所示。

R14_fiq = address of next instruction to be executed + 4
SPSR_fiq = CPSR
/* 进入FIQ异常中断模式 */
CPSR[4:0] = 0b10001
/* 切换到ARM状态 */
CSPR[5] = 0
/* 禁止FIQ中断 */
CPSR[6] = 1
/* 禁止IRQ异常中断 */
CPSR[7] = 1
if high vectors configured then
PC = 0xFFFF001C
else 
PC = 0x0000001C

从异常中断处理程序中返回包括下面两个基本操作:

  • 恢复被中断的程序的处理器状态,即将SPSR_mode寄存器内容复制到当前程序状态寄存器CPSR中。
  • 返回到发生异常中断的指令的下一条指令处执行,即将lr_mode寄存器的内容复制到程序计数器PC中。

复位异常中断处理程序不需要返回。整个应用系统是从复位异常中断处理程序开始执行的,因为它不需要返回。

实际上,当异常中断发生时,程序计数器PC所指的位置对于各种不同的异常中断是不同的。同样,返回地址对于各种不同的异常中断也是不同的。下面详细介绍各种异常中断处理程序的返回方法。

1.SWI和未定义指令异常中断处理程序的返回
SWI和未定义指令异常中断是由当前执行的指令自身产生的,当SWI和未定义指令异常中断发生时,程序计数器PC的值还未更新,它指向当前指令后面第2条指令。当SWI和未定义指令异常中断发生时,处理器将值(PC-4)保存到异常模式下的寄存器lr_mode中。这时(PC-4)即指向当前指令的下一条指令。因此返回操作可以通过下面的指令来实现:

MOV PC LR

该指令寄存器LR中的值复制到程序计数器PC中,实现程序返回,同时将SPSR_mode寄存器内容复制到当前程序状态寄存器CPSR中。

当异常中断处理程序使用了数据栈时,可以通过下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断处理程序中使用的数据栈由用户提供。

stmfd sp!, {reglist,lr}
....
ldmfd sp!, {reglist,pc}^

在上述指令中,reglist是异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器内容复制到当前程序状态寄存器CPSR中。该指令只能在特权模式下使用。

2.IRQ和FIQ异常中断处理程序的返回
通常处理器执行完当前指令后,查询IRQ中断引脚和FIQ中断引脚,并且查看系统是否允许FIQ中断及IRQ中断。如果有中断引脚有效,并且系统允许该中断发生,处理器将产生IRQ异常中断或FIQ异常中断。当IRQ和FIQ异常中断产生时,程序计数器PC的值已经更新,它指向当前指令后面第3条指令。当IRQ和FIQ异常中断发生时,处理器将值(PC-4)保存到异常模式下的寄存器lr_mode中。这时(PC-4)即指向当前指令后的第2条指令。因此返回操作可以通过下面的指令来实现:

SUB PC, LR, #4

该指令将寄存器LR中的值减4后,复制到程序计数器PC中,实现程序返回,同时将SPSR_mode寄存器内容复制到当前程序状态寄存器CPSR中。

当异常中断发处理程序使用了数据栈时,可以通过下面的指令在进入异常中断处理程序时保存被中断程序的执行现场,在退出异常中断处理程序时恢复被中断程序的执行现场。异常中断处理程序中使用的数据栈由用户提供。

SUB LR, LR, #4
STMFD sp!, {reglist, lr}
...
LDMFD sp!, {reglist, pc}^

上述指令中,reglist是异常中断处理程序中使用的寄存器列表。标识符^指示将SPSR_mode寄存器内容复制到当前程序状态寄存器CPSR中。该指令只能在特权模式下使用。

其它异常中断返回情况请参考《ARM体系结构与编程》一书中的第9章。

你可能感兴趣的:(tiny4412开发板学习记录)