ARM中异常中断问题分析总结

kelly的头像
kelly 发布于:周二, 08/23/2016 - 11:05 ,关键词:

一、ARM中异常中断的类型:

异常中断名称 含义 复位(Reset)

当处理器复位引脚有效时,系统产生复位异常中断,程序跳转到复位异常中断处理程序处执行。复位异常中断通常用在下面几种情况:

1、系统加电时

2、系统复位时

3、跳转到复位中断向量处执行,称为软复位

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

软件中断

(software interrupt SWI)

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

指令预取中止

(Prefech Abort)

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

数据访问中止

(Data Abort)

如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问中止异常中断 外部中断请求(IRQ) 当处理器的外部中断请求引脚有效,而且CPSR寄存器的I控制位被清除时,处理器产生外部中断请求(IRQ)异常中断。系统中各外设通常通过该异常中断请求处理器服务 快速中断请求(FIQ) 当处理器的外部快速中断请求引脚有效,而且CPSR寄存器的F控制位被清除时,处理器产生外部中断请求(FIQ)异常中断

注:不要把异常中断类型和处理器的工作模式搞混。

复位异常发生后,进入到管理模式(svc)下。 软中断发生后,进入到管理模式(svc)下。 未定义指令异常发生后,进入到未定义指令中止模式(und)下。 指令预取中止异常发生后,进入到数据访问中止模式(abt)下; 数据访问中止异常发生后,进入到数据访问中止模式(abt)下: 外部中断发生后,进入到外部中断模式(irq)下; 快速中断发生后,进入到快速中断模式(fiq)下; 二、ARM对异常中断的响应过程

(1)ARM处理器对异常中断的响应过程:

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

注:以上过程全部是由硬件自动完成的。不管是在ARM状态下还是在THUMB状态下发生异常,都会自动切换到ARM状态下进行异常的处理

(2)从异常中断处理程序中返回:

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

注:实际上,当异常中断发生时,程序计数器PC所指的位置对于不同的异常中断是不同的。同样,返回地址对于各种不同的异常中断也是不同的。详细见(3)

复位异常中断处理程序不需要返回。在复位异常中断处理程序开始整个用户程序的执行,因而它不需要返回。 由于异常模式不同以及ARM内核采用流水线技术,异常处理程序里要根据异常模式计算返回地址。 一条指令的执行分为:取指,译码,执行三个主要阶段,CPU由于使用流水线技术,造成当前执行指令的地址应该是PC – 8(32位机一条指令四个字节),那么执行指令的下条指令应该是PC – 4。在异常发生时,CPU自动会将将PC – 4的值保存到LR里,但是该值是否正确还要看异常类型才能决定

(3)详细:各个异常状态发生后,ARM处理器硬件响应过程

1、响应复位异常中断

上电复位:在上电后,复位使内部达到预定的状态,特别是程序跳到初始入口; 复位引脚上的复位脉冲:这是由外部其他控制信号引起的; 对系统电源检测发现过压或欠压; 时钟异常复位。

当发生复位时,处理器硬件响应中断,自动执行如下操作:

强制进入管理模式; 强制进入ARM状态; 禁止IRQ中断和FIQ中断; 跳转到绝对地址PC=0x00000000处执行

2、未定义指令异常

遇到一条无法执行的指令,此指令没有定义; 执行一条对协处理器的操作指令,在正常情况下,协处理器应该应答,但协处理器没有应答。

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_und; 强制进入未定义模式; 强制进入到ARM模式; 禁止IRQ中断 把下一条指令的地址拷贝给LR; 跳转到绝对地址PC=0x00000004处执行

关于从异常中断处理程序的返回:

未定义指令异常中断是由当前执行的指令自身产生的,当产生中断时,程序计数器PC的值还未更新,它指向当前指令后面的第二条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置)。当未定义指令异常中断发生时,处理器自动将值(pc-4)保存到lr_und中,此时(pc-4)指向当前指令的下一条指令,所以从未定义指令异常中断返回可以通过如下指令来实现:

MOV PC,LR

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

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

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

3、软件中断异常

是由指令SWI引起的,程序在执行这一指令后,进入异常中断。

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_svc; 强制进入管理模式; 强制进入到ARM状态; 禁止IRQ中断。 把下一条指令的地址拷贝给LR; 跳转到绝对地址PC=0x00000008处执行;

关于从异常中断处理程序的返回:

软件中断异常是由当前执行的指令自身产生的,当产生中断时,程序计数器PC的值还未更新,它指向当前指令后面的第二条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置)。当软件中断发生时,处理器自动将值(pc-4)保存到lr_siw中,此时(pc-4)指向当前指令的下一条指令,所以从软件中断返回可以通过如下指令来实现:

MOV PC,LR

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

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

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

4、预取指中止异常

由程序存储器引起的中止异常叫做预取指中止异常; 由数据存储器引起的中止异常叫做数据中止异常。 由于ARM的指令是3级流水线结构,读取指令周期是提前进行的,因此把读取指令的过程一般称预取指。在指令预取时,如果目标地址是非法的,该指令被标记成有问题的指令,这时,流水线上该指令之前的指令继续执行。有两种可能如下:

1.当执行这条指令前程序发生跳转,则这条无效指令不引起异常中断; 2.当执行到这条指令时,处理器会发生预取指中止异常,引起中断。

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_abt; 强制进入中止异常模式; 强制进入到ARM状态; 禁止IRQ中断。 把中断时PC的地址拷贝给LR; 跳转到绝对地址PC=0x0000000C处执行;

关于从异常中断处理程序的返回:

在指令预取时,如果目标地址是非法的,该指令被标记成有问题的指令,这时,流水线上该指令之前的指令继续执行,当执行到该被标记成有问题的指令时,处理器产生指令预取中止异常中断。发生指令预取异常中断时,程序要返回到该有问题的指令处,重新读取并执行该指令,因此指令预取中止异常中断应该返回到产生该指令预取中止异常中断的指令处,而不是当前指令的下一条指令。

指令预取异常是由当前执行的指令自身产生的,当产生中断时,程序计数器PC的值还未更新,它指向当前指令后面的第二条指令(对于ARM指令,它指向当前指令地址加8字节的位置;对于Thumb指令,它指向当前指令地址加4字节的位置)。当指令预取中止异常中断发生时,处理器自动将值(pc-4)保存到lr_abt中,此时(pc-4)指向当前指令的下一条指令,所以从软件中断返回可以通过如下指令来实现:

SUBS PC,LR,#4

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

SUBS LR,LR,#4

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

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

5、数据中止异常

ARM处理器访问数据存储器时,在读取数据的同时数据存储器发出了中止信号,引起数据中止异常。 如果数据访问指令的目标地址不存在,或者该地址不允许当前指令访问,处理器产生数据访问中止异常中断

处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_abt; 强制进入中止异常模式; 强制进入到ARM状态; 禁止IRQ中断; 把中断时的PC的地址拷贝给LR; 跳转到绝对地址PC=0x00000010处执行

关于从异常中断处理程序的返回:

发生数据访问异常中断时,程序要返回到该有问题的指令处,重新访问该数据,因此数据访问异常中断应该返回到产生该数据访问中止异常中断的指令处,而不是当前指令的下一条指令。 数据访问异常中断由当前执行的指令在ALU里执行时产生,当数据访问异常中断发生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置)。此时处理器将值(pc-4)保存到lr_abt中,它指向当前指令后面第2条指令,所以返回操作可以通过下面指令实现:

SUBS PC, LR, #8

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

SUBS LR,LR,#8

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

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

6、中断请求(IRQ)异常

例如:定时器中断、串行口通讯中断、外部信号中断和A/D处理中断等。IRQ中断是可屏蔽的。在状态寄存器中的I位就是IRQ的屏蔽位。当I=1时。则屏蔽IRQ中断,当I=0时,则允许中断。处理器复位后置I为1,关闭中断。 处理器响应中断后,硬件自动执行下列操作: 把程序状态寄存器CPSR拷贝给SPSR_irq; 强制进入IRQ异常模式; 强制进入到ARM状态; 禁止IRQ中断; 把中断时的PC的地址值拷贝给LR; 跳转到绝对地址PC=0x00000018处执行;

关于从异常中断处理程序的返回:

通常处理器执行完当前指令后,查询IRQ中断引脚,并查看系统是否允许IRQ中断,如果某个中断引脚有效,并且系统允许该中断产生,处理器将产生IRQ异常中断,当IRQ异常中断产生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置),当IRQ异常中断产生时,处理器将值(pc-4)保存到IRQ异常模式下的寄存器lr_irq中,它指向当前指令之后的第2条指令,因此正确返回地址可以通过下面指令算出:

SUBS PC,LR,#4

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

SUBS LR, LR, #4

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

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

注:为什么PC会指向当前执行指令的后12个字节?

当前指令执行时(此时PC指向当前指令后面的第2条指令),如果发生IRQ中断,ARM检测到IRQ中断后,取指和执行单元都不会改变,只有译码单元会改变,译码单元改为开始译码中断指令。执行完当前指令后,PC值加4个字节(此时PC指向刚刚那条指令后面的第3条指令),译码单元将译完的中断指令送到执行单元,执行单元执行中断指令,保存PC-4(此时PC指向当前指令后面的第2条指令)的值到LR_irq,同时跳转到IRQ中断向量处。(详细可看ARM流水线机制

7、快速中断(FIQ)请求异常。

FIQ快速中断是可屏蔽的。在状态寄存器中的F位就是FIQ的屏蔽位。当F=1时。则屏蔽FIQ中断,当F=0时,则允许中断。处理器复位后置F为1,关闭中断。 处理器响应中断后,硬件自动执行下列操作:

把程序状态寄存器CPSR拷贝给SPSR_fiq; 强制进入FIQ异常模式; 强制进入到ARM状态; 禁止FIQ中断; 把中断时的PC的地址值拷贝给LR; 跳转到绝对地址PC=0x0000001C处执行;

关于从异常中断处理程序的返回:

通常处理器执行完当前指令后,查询FIQ中断引脚,并查看系统是否允许FIQ中断,如果某个中断引脚有效,并且系统允许该中断产生,处理器将产生FIQ异常中断,当FIQ异常中断产生时,程序计数器pc的值已经更新,它指向当前指令后面第3条指令(对于ARM指令,它指向当前指令地址加12字节的位置;对于Thumb指令,它指向当前指令地址加6字节的位置),当FIQ异常中断产生时,处理器将值(pc-4)保存到IRQ异常模式下的寄存器lr_fiq中,它指向当前指令之后的第2条指令,因此正确返回地址可以通过下面指令算出:

SUBS PC,LR,#4

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

SUBS LR, LR, #4

STMFD sp! , {reglist,lr}

....

LDMFD sp! , {reglist,pc}^

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

注:为什么PC会指向当前执行指令的后12个字节?

当前指令执行时(此时PC指向当前指令后面的第2条指令),如果发生FIQ中断,ARM检测到FIQ中断后,取指和执行单元都不会改变,只有译码单元会改变,译码单元改为开始译码中断指令。执行完当前指令后,PC值加4个字节(此时PC指向刚刚那条指令后面的第3条指令),译码单元将译完的中断指令送到执行单元,执行单元执行中断指令,保存PC-4(此时PC指向当前指令后面的第2条指令)的值到LR_fiq,同时跳转到FIQ中断向量处。(详细可看ARM流水线机制)

围观 493