ARM 异常(Exception)


在这里插入图片描述

ARM

ARM异常(Exception)


什么是异常?

  异常 是处理器核在顺序执行程序指令流的过程中突然遇到了异常的事情,这些事件包括硬件错误、指令执行错误、用户程序请求服务、内存访问异常、取指令异常等,几乎每种处理器都支持特定的异常处理,中断也是异常的一种。

ARM的异常源

表1 ARM异常源
异常地址异常源描述优先级(6最低)
0x00Reset复位异常:在内核复位时执行1
0x04Undefined instructions未定义指令异常:流水线执行非法指令产生,该异常发生在流水线译码阶段,如果当前指令不能被识别为有效指令,将会出现此类异常。6
0x08SVC(Supervisor Call)、SWI软中断异常:用于程序触发软件中断执行,该异常是由应用程序自己调用时产生,当应用程序在需要访问硬件资源时需要调用该指令,该异常在管理模式(SVC)下运行。6
0x0CPrefetch abort预取指令中止异常:当一条指令从内存中取出时由于某些原因失败,且如果它能到达执行状态将会触发此异常。5
0x10Data abort数据访问中止异常:如果一个预取指令试图存取一个不存在或非法的内存单元时,将会触发此异常。5
0x14RESERVED保留保留
0x18IRQ一般中断异常4
0x1CFIQ快速中断异常3

  一般中断异常快速中断异常 的区别:快速中断具有最高优先级和最小的中断延迟,通常用于处理高速数据传输及通道中的数据恢复功能,例如DMA等,绝大部分外设使用一般中断请求,例如 IIC、SPI、UART 等。

  FIQ 较 IRQ 快的原因:

  • FIQ 优先级高于 IRQ。
  • FIQ 处于一场向量表的末端,在进行异常处理时不需要进行跳转。
  • FIQ 比 IRQ 多5个私有寄存器(R8-R12),在中断操作中压栈与出栈的次数相对较少。

在这里插入图片描述

异常处理向量表

ARM异常优先级

  当几个异常中断同时发生时,CPU决定相应哪个异常时是由优先级决定的,ARM异常的优先级如下:
从上往下依次递减

  • Reset
  • Data Abort
  • FIQ
  • IRQ
  • Prefetch abort
  • Undefined instructions/SWI

  有些异常是不可能同时发生的,例如指令预取中止异常(ABT)和软中断(SWI)异常是由同一条指令的执行触发的,它们是不可能同时发生的。

恩智浦 i.MX6ULL(ARM Cortex-A7内核) 异常向量表

    .section .isr_vector, "a".align 2.globl __isr_vector
__isr_vector:ldr     pc, =Reset_Handler           /* Reset                  */ldr     pc, =Undefined_Handler       /* Undefined instructions */ldr     pc, =SVC_Handler             /* Supervisor Call        */ldr     pc, =PrefAbort_Handler       /* Prefetch abort         */ldr     pc, =DataAbort_Handler       /* Data abort             */.word   0                            /* RESERVED               */ldr     pc, =IRQ_Handler             /* IRQ interrupt          */ldr     pc, =FIQ_Handler             /* FIQ interrupt          */.size    __isr_vector, . - __isr_vector.text.arm.align  2.arm.weak Undefined_Handler.type Undefined_Handler, %function
Undefined_Handler:b Undefined_Handler.size Undefined_Handler, . - Undefined_Handler.align 2.arm.weak SVC_Handler.type SVC_Handler, %function
SVC_Handler:ldr   r0,=SVC_Handlerbx    r0.size SVC_Handler, . - SVC_Handler.align 2.arm.weak PrefAbort_Handler.type PrefAbort_Handler, %function
PrefAbort_Handler:ldr   r0,=PrefAbort_Handlerbx    r0.size PrefAbort_Handler, . - PrefAbort_Handler.align 2.arm.weak DataAbort_Handler.type DataAbort_Handler, %function
DataAbort_Handler:ldr   r0,=DataAbort_Handlerbx    r0.size DataAbort_Handler, . - DataAbort_Handler.align 2.arm.weak IRQ_Handler.type IRQ_Handler, %function
IRQ_Handler:push    {lr}                         /* Save return address+4                                */push    {r0-r3, r12}                 /* Push caller save registers                           */MRS     r0, spsr                     /* Save SPRS to allow interrupt reentry                 */push    {r0}MRC     P15, 4, r1, C15, C0, 0       /* Get GIC base address                                 */ADD     r1, r1, #0x2000              /* r1: GICC base address                                */LDR     r0, [r1, #0xC]               /* r0: IAR                                              */push    {r0, r1}CPS     #0x13                        /* Change to Supervisor mode to allow interrupt reentry */push    {lr}                         /* Save Supervisor lr                                   */LDR     r2, =SystemIrqHandlerBLX     r2                           /* Call SystemIrqHandler with param GCC                 */POP     {lr}CPS     #0x12                        /* Back to IRQ mode                                     */POP     {r0, r1}STR     r0, [r1, #0x10]              /* Now IRQ handler finished: write to EOIR              */POP     {r0}MSR     spsr_cxsf, r0POP     {r0-r3, r12}POP     {lr}SUBS    pc, lr, #4.size IRQ_Handler, . - IRQ_Handler.align 2.arm.weak FIQ_Handler.type FIQ_Handler, %function
FIQ_Handler:ldr   r0,=FIQ_Handlerbx    r0.size FIQ_Handler, . - FIQ_Handler.end

ARM异常处理过程

  一般CPU在异常发生后,都会进行一系列的操作,这些操作有一部分是CPU自动完成,有一部分是需要应用程序完成。

对异常的响应

  当处理器一个异常出现时,ARM处理器会执行以下操作:

  1. 执行完当前指令,将下一条指令的地址存放在相应的 LR 寄存器,以便于程序处理完异常后返回到正确的位置重新执行。若异常是从ARM状态下进入,LR 寄存器中保存的是下一条指令的地址;若异常是从 Thumb 状态进入,则在 LR 寄存器中保存当前PC的偏移量,这样异常服务程序就不需要确定当前处理的异常是从哪种状态进入的(可通过检测 SPSR 寄存器的 T 位来判断);
  2. CPSR 寄存器中的相应位保存至相应的 SPSR 寄存器中,保护处理器的执行状态;
  3. 根据异常的类型强制更改 CPSR 中的运行模式位;
  4. 更改 PC 的值,指向异常向量地址取下一条指令执行,从而跳转到相应的异常处理程序,还可以相应的中断禁止位,禁止中断的发生。

  当ARM处理器异常发生时,分组寄存器 R14SPSR 寄存器用于保存处理器状态。上述处理器对异常中断的响应过程用伪指令描述如下:

  1R14_(exception_mode) = return link2SPSR_(exception_mode) = CPSR3、CPSR[4:0] = exception mode number/* 进入ARM状态 */CPSR[5] = 0IF (exception_mode) == reset or FIQ then/* 屏蔽快速中断FIQ */CPSR[6] = 1/* 屏蔽外部中断IRQ */CPSR[7] = 14、PC = exception vector addr

从异常返回

处理器处理完异常后需要返回异常发生的下一条指令处继续执行,这个过程会出现以下几步操作从异常返回:

  1. 将LR寄存器的值减去相应的偏移量后送到PC中;
  2. 将SPSR的值重新存入CPSR寄存器中;
  3. 若进入异常处理前设置了中断禁止位,要在此清除。
  异常返回时,处理器将SPSR内容恢复至CPSR寄存器,链接寄存器R14的内容恢复至程序计数器PC中

1. 复位异常

  在处理器的复位信号有效时,处理器产生复位异常,程序终止执行当前指令。当处理器复位信号变为无效时,处理器跳转至复位异常处理程序处执行以下操作:

  R14_svc = UNPREDICTABLE Value /* 不可预知值 */SPSR_svc = UNPREDICTABLE Value /* 不可预知值 *//* 进入特权模式 */CPSR[4:0] = 0B1011/* 切换至ARM状态 */CPSR[5] = 0/* 禁止FIQ中断 */CPSR[6] = 1/* 禁止IRQ中断 */CPSR[7] = 1if high vectors configured thenPC = 0xFFFF0000elsePC = 0x00000000

  复位异常处理程序会进行一些初始化工作,主要包括:

  • 设置中断向量表
  • 初始化数据栈和寄存器
  • 初始化存储系统
  • 初始化部分I/O设备
  • 处理器切态
  • 跳转至应用程序

2. 未定义指令异常

  处理器响应未定义指令异常时处理过程如下所示:

  R14_und = 未定义指令的下一条指令的地址SPSR_und = CPSR/* 进入未定义指令异常中断 */CPSR[4:0] = 0b11011/* 切换至ARM状态 */CPSR[5] = 0/* CPSR[6]不变 *//* 禁止IRQ异常中断 */CPSR[7] = 1if high vectors configured thenPC = 0xFFFF0004elsePC = 0x00000004

3. SWI(软中断)异常

  软中断异常发生时,处理器进入特权模式,执行一些特权模式下的操作系统功能。处理器响应 SWI 中断时处理过程伪代码如下:

  R14_svc = SWI指令的下一条指令的地址SPSR_svc = CPSR/* 进入特权模式 */CPSR[40] = 0b10011/* 切换至ARM状态 */CPSR[5] = 0/* CPSR[6]不变 *//* 禁止IRQ异常中断 */CPSR[7] = 1if high vectors configured thenPC = 0xFFFF0008elsePC = 0x00000008

4. 指令预取中止异常

  预取异常是由系统存储器报告的。当处理器试图去取一条被标记为预取无效的指令时,发生预取异常。如果系统中不包含 MMU,指令预取异常中断处理程序只是简单地报告错误并退出;若包含MMU,引起异常的指令的物理地址将被存储到内存中。预取异常发生时,处理器执行下列伪操作:

  R14_abt = 发生中止异常的指令的地址 + 4SPSR_abt = CPSR/* 进入指令预取中止异常 */CPSR[4:0] = 0b10111/* 切换至ARM状态 */CPSR[5] = 0/* CPSR[6]不变 *//* 禁止IRQ异常中断 */CPSR[7] = 1if high vectors configured thenPC = 0xFFFF000CelsePC = 0x0000000C

5、数据访问中止异常

  数据访问中止异常是由存储器发出数据中止信号,它由存储器访问指令 Load/Store 产生。当数据访问指令的目标地址不存在或者该地址不允许当前指令访问时,处理器将会产生数据访问中止异常。当数据异常发生时,处理器执行下列伪操作:

  R14_abt = 需要执行的下一条指令的地址 + 4SPSR_abt = CPSR/* 进入数据访问中止异常 */CPSR[4:0] = 0b10111/* 切换至ARM状态 */CPSR[5] = 0/* CPSR[6]不变 *//* 禁止IRQ异常中断 */CPSR[7] = 1if high vectors configured thenPC = 0xFFFF0010elsePC = 0x00000010

6、IRQ异常中断

  当处理器的外部中断请求引脚有效,且 CPSR 寄存器的I控制位被清除时(I=1时,外部IRQ被禁止)处理器产生外部中断异常。SoC系统中各外部设备通常采用该异常中断请求处理器服务。处理器响应 IRQ 异常中断时,处理过程伪代码如下:

  R14_irq = 需要执行的下一条指令的地址 + 4SPSR_irq = CPSR/* 进入IRQ异常中断模式 */CPSR[4:0] = 0b10010/* 切换至ARM状态 */CPSR[5] = 0/* CPSR[6]不改变 */if high vectors configured thenPC = 0xFFFF0018elsePC = 0x00000018

7、响应FIQ异常中断

  当处理器的快速中断引脚有效且 CPSR 寄存器F控制位被清除时(F = 1 FIQ被禁止)处理器产生快速中断异常。处理器响应快速中断异常时,执行下列伪操作:

  R14_fiq = 需要执行的下一条指令的地址 + 4SPSR_fiq = CPSR/* 进入FIQ异常中断模式 */CPSR[4:0] = 0b10001/* 切换至ARM状态 */CPSR[5] = 0/* 禁止FIQ异常中断 */CPSR[6] = 1/* 禁止IRQ异常中断 */CPSR[7] = 1if high vectors configured thenPC = 0xFFFF001CelsePC = 0x0000001C

参考资料

《ARM体系结构与编程_第2版》杜春雷 著
《ARM处理器开发详解》


🎁
🎨


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部