ARM异常处理(1):异常类型、优先级分组和异常向量表

本系列文章将以Cortex-M3内核为例,对ARM的异常(exception)进行分析。


1 异常类型

Cortex-M3提供了一个功能丰富的异常体系结构,它支持很多系统异常和外部中断。异常编号1-15表示系统异常,16及以上表示外部中断输入。大多数异常具有可编程优先级,少数具有固定优先级。

Exception NumberException TypePriorityDescription
1Reset-3(Highest)Reset
2NMI-2Nonmaskable interrupt(external NMI input)
3Hard fault-1如果其它具体的fault handler没有使能,所有的fault都会归为Hard fault
4MemManage fault可编程内存管理错误;MPU(内存保护单元)非法操作或访问了非法地址
5Bus fault可编程总线错误,当AHB接口收到了bus slave的错误响应(指令预取时出错称为prefetch abort,数据访问时出错称为data abort)
6Usage fault可编程程序中的错误或访问coprocesser(协处理器)
7-10Reserved--
11SVC可编程Supervisor Call
12Debug monitor可编程代码断点、watch window的变量断点和外部调试请求时触发
13Reserved--
14PendSV可编程Pendable Service Call
15SYSTICK可编程System Tick Timer
16External Interrupt #0可编程-
17External Interrupt #1可编程-
-
255External Interrupt #239可编程-
  • 前三个异常为负优先级,表示他们的优先级高于其它所有异常
  • NMI异常:它的用途取决于具体的微控制器或SoC产品的硬件设计,大多数情况下NMI连接看门狗时钟或者电压监测模块,在发送看门狗复位或电压过低的情况时触发。

当前正在运行的异常可以通过特殊寄存器IPSR(Interrupt Program Status Register)或者NVIC中断控制状态寄存器(Nested Vectored Interrupt Controllers Interrupt Control State Register)中的VECTACTIVE字段来查看。

  • 这里的中断号指的是对Cortex-M3 NVIC的中断输入,在实际的微控制器或SoC中,外部中断输入引脚编号可能与NVIC中的输入编号不同,比如External Interrupt #0External Interrupt #1可能会分配给片上外设,剩下的再分配给外部,需查询具体芯片的数据手册

当一个使能的异常产生但不能被立即执行的时候(比如有一个更高优先级的中断服务程序正在处理),它会被挂起(有一个例外:当发生这种情况后,可能会触发Hard fault,具体细节参考 ARM v7-M Architecture Application Level Reference Manual)。也就是说NVIC的挂起寄存器将保存这个异常请求,直到该异常可以被处理为止。

  • 即使请求中断的源撤销了这个请求,产生的异常也还是会被处理。

2 优先级

异常是否可以执行以及何时执行与异常的优先级有关,高优先级异常可以抢占低优先级异常。Cortex-M3支持三种固定的最高优先级(Reset/NMI/Hard Fault)和最大256级的可编程优先级(最多128级抢占,因为还分为抢占优先级和子优先级)。但不同的芯片支持的数量不一样,因为Cortex-M3允许设计师通过删除优先级配置寄存器的LSB来减少支持的优先级层数。

  • 例:如果芯片仅允许三位优先级,则读0-4位将返回0,写0-4位的任何数值都将被忽略
    在这里插入图片描述
    芯片支持更多的优先级就意味着芯片内部的门电路就更多,从而增加功耗。对于Cortex-M3来说,允许设置的最低优先级层数为8层(3位)。

问:为什么是删除寄存器的LSB而不是MSB

答:方便移植到其它设备,这样具有4位优先级配置寄存器的设备可以直接移植到具有3位优先级配置寄存器的设备上。如果删除MSB,则移植过后可能产生会优先级反转。


优先级寄存器AIRCR(Application Interrupt and Reset Control Register)分为两个部分,前半部分是抢占优先级(preempt priority),后半部分是子优先级(subpriority)。首先来看看AIRCR寄存器中的字段:
在这里插入图片描述

BitsNameTypeReset ValueDescription
31:16VECTKEYR/W-访问密钥,必须写为0x05FA,否则对该寄存器的写操作将被忽略
15ENDIANNESSR-1为大端,0为小端,只能在复位后改变
10:8PRIGROUPR/W-优先级分组
2SYSRESETREQW-通过访问芯片控制逻辑来产生一个复位
1VECTCLRACTIVEW-清除所有异常的激活状态信息,通常用在debug或OS中以允许系统从错误中恢复
0VECTRESETW-复位Cortex-M3处理器(除debug部分外),但不会复位处理器外围的电路

对于PRIGROUP来说,有8个分组,如下表所示:

Priority Group抢占优先级子优先级
0Bit [7:1]Bit [0]
1Bit [7:2]Bit [1:0]
2Bit [7:3]Bit [2:0]
3Bit [7:4]Bit [3:0]
4Bit [7:5]Bit [4:0]
5Bit [7:6]Bit [5:0]
6Bit [7:7]Bit [6:0]
7NoneBit [7:0]

抢占优先级决定一个中断可以在另一个中断处理程序执行时产生,子优先级仅在抢占优先级相同时使用。当分组为0时,抢占优先级有128级;当分组为7时,异常之间不会发生抢占,除非发生硬件错误(负优先级的异常)。


例:芯片允许三位优先级,优先级分组为5
在这里插入图片描述


3 向量表

    当异常发生时,Cortex-M3需要知道异常处理程序的地址并执行,而异常处理函数的地址保存在内存中的向量表中。默认情况下,该向量表保存在0地址处。

AddressException NumberValue(Word Size)
0x00000000-MSP初始值
0x000000041Reset Vector(PC的初始值)
0x000000082NMI中断处理函数地址
0x0000000C3Hard fault中断处理函数地址
其它中断处理函数的地址

    0地址一般为boot程序,它不能在运行时期修改。但是,向量表可以被重定位到其它内存位置或RAM中,这样我们就可以在运行时期修改。这是通过设置NVIC寄存器中的vector table offset regiser来实现的,如下表所示:

BitsNAMETypeReset ValueDecription
29TBLBASER/W0向量表基地址在code(0)还是RAM(1)
28:7TBLOFFR/W0向量表在code或RAM中的偏移

这个offset应该与向量表的大小对齐。

  • 由于在boot过程中也可能会发生NMIHard fault异常,而其它的异常只要不使能就不会产生,所以这两个向量表也需要写入零地址。当boot结束后,可以将SRAM中的一段内存定义为新的向量表的基地址

例:我们有32个中断向量,加上系统默认的16个异常共48个。首先要2字节对齐到64,接着一个向量表地址占4字节,即最后这个偏移量应该设置为256(0x100)。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

tilblackout

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值