CM3异常实现
异常类型
1-15 是系统异常,大于等于 16 是外部中断。
优先级的定义
- 优先级的数值越小,则优先级越高。CM3 支持中断嵌套,使得高优先级异常会抢占(preempt)低优先级异常。
- 3 个系统异常:复位,NMI 以及硬 fault。有固定的优先级,优先级号是负数,从而高于所有其它异常。且不可编程。除此之外其他的异常都是可编程的。
- CM3 支持 3 个固定的高优先级和多达 256 级的可编程优先级,支持 128级抢占
- 只使用 3 个位来表达优先级的优先级配置如下图:
[4:0]没有被实现,所以读它们总是返回零。CM3 允许的最少使用位数为 3 个位,亦即至少要支持 8 级优先级。 - 优先级号是以MSB 对齐的(左对齐,高位对齐)
支持 256 个优先级,为什么只有 128 个抢占级?
答:为了使抢占机能变得更可控,CM3 把 256 级优先级按位分成高低两段,分别是抢占优先级和亚优先级
应用程序中断及复位控制寄存器
:有一个位段名为“优先级组”。该位段的值对每一个优先级可配置的异常都有影响——把其优先级分为个位段:MSB 所在的位段(左边的)对应抢占优先级
,而LSB 所在的位段(右边的)对应亚优先级
,如下图。
- 抢占优先级分工: 当系统正在响应某异常 L 时,如果来了抢占优先级更高的异常 H,则 H 可以抢占 L
- 亚优先级分工: 当抢占优先级相同的异常不止一个悬起时,就优先响应亚优先级最高的异常
规定:亚优先级至少是 1 个位。因此抢占优先级最多是 7 个位
-
除能 CM3 的中断嵌套机制
:CM3 允许从比特 7 处分组,此时所有的位都表达亚优先级,没有任何位表达抢占优先级,所有优先级可编程的异常之间就不会发生抢占, -
复位,NMI 和硬 fault。无论何时出现,都立即无条件抢占所有优先级
-
如果优先级完全相同,则先响应异常编号最小的
-
优先级的分组要预先经过计算论证,并且在开机初始化时一次性地设置好,以后再也不动它。
向量表
-
“(异常)向量表”存放CM3异常处理函数的入口地址。CM3 认为该表位于零地址处,且各向量占用 4 字节
-
地址 0 处存储引导代码,通常是 Flash 或者是 ROM 器件,它们的值不得在运行时改变
-
CM3 允许
向量表重定位
——从其它地址处开始定位各异常向量。其他地址包括:代码区、RAM区。 -
动态地更改向量表,对于任何器件,向量表的起始处都必须包含以下向量:
- 主堆栈指针(MSP)的初始值
- 复位向量
- NMI
- 硬 fault 服务例程
-
“向量表偏移量寄存器”,实现在 RAM区修改向量的入口地址,修改它的值就能定位向量表。
向量表的起始地址要求
:先求出系统中共有多少个向量,再把这个数字向上增大到是 2 的整次幂,而起始地址必须对齐到后者的边界上。例如,如果一共有 32 个 中断,则共有 32+16(系统异常)=48 个向量,向上增大到 2 的整次幂后值为 64,因此地址 地址必须能被 64* 4=256 整除,从而合法的起始地址可以是:0x0, 0x100, 0x200 等。
中断输入以及悬起行为
-
当中断输入脚被 assert 后,该中断就被悬起。即使后来中断源取消了中断请求,已经被标记成悬起的中断也被记录下来。到了系统中它的优先级最高的时候,就会得到响应。
-
在某个中断得到响应之前,其悬起状态被清除(例如,在 PRIMASK 或FAULTMASK 置位的时候软件清除了悬起状态标志),则中断被取消。
-
当某中断的服务例程开始执行时,称此中断进入了“活跃”状态,其悬起位被硬件自动清除。在一个中断活跃后,直到其服务例程执行完毕,并且返回 (亦称为中断退出),才能对该中断的新请求予以响应(即单实例)。中断服务例程也可以在执行过程中把自己对应的中断重新悬起
-
中断源咬住请求信号不放,该中断会在其上次服务例程返回后再次被置为悬起状态
-
如果某个中断在得到响应之前,其请求信号以若干的脉冲的方式呈现,则被视为只有一次中断请求,多出的请求脉冲全部错失。
-
在服务例程执行时,中断请求被释放,但是在服务例程返回前又重新被置为有效, 则 CM3 会记住此动作,重新悬起该中断。
Fault 异常
- 专用于 fault 处理的若干个系统异常。CM3 中的 Faults 分类:
- 总线 faults
- 存储器管理 faults
- 用法 faults
- 硬 fault
总线 Faults
-
当AHB 接口上正在传送数据时,如果回复一个错误信号(error response),则会产生总线 faults
-
使能总线 fault 服务例程,在 NVIC的 “系统 Handler 控制及状态寄存器”中置位BUSFAULTENA 位。
-
针对数据传输的场所:
- 取指,通常被称作“预取流产”(prefetch abort)
- 数据读/写,通常被称作“数据流产”(data abort)
-
针对错误信号触发的动作
- 中断处理起始阶段的堆栈 PUSH 动作。 称为“入栈错误”
- 中断处理收尾阶段的堆栈 POP 动作。 称为“出栈错误”
- 在处理器启动中断处理序列(sequence)后的向量读取时。是一种罕见的特殊情况,被归类为硬 fault
哪些因素会导致 AHB 回复一个错误信号?
- 企图访问无效的存储器 region。常见于访问的地址没有相对应的存储器。
- 设备还没有作好传送数据的准备。比如,在尚未初始化 SDRAM 控制器的 时候试图访问 SDRAM。
- 在企图启动一次数据传送时,传送的尺寸不能为目标设备所支持。例如, 某设备只接受字型数据,却试图送给它字节型数据。
- 因为某些原因,设备不能接受数据传送。例如,某些设备只有在特权级下 才允许访问,可当前却是用户级。
总线 fault悬起和硬fault
- 在检测到总线 fault 时还检测到了更高优先级的异常,则先处理后者,而总线 fault 则被标记成悬起。
- 如果总线fault被除能,或者总线 fault 发生时正在处理同级或更高优先级异常,则总线 fault 被迫成为“硬伤”——上访成硬 fault,使得最后执行的是硬 fault 的服务例程。在硬 fault 服务例程的执行中又产生了总线 fault(钻牛角尖),内核将进入锁定状态
发生总线 fault 后,如何找出该 fault 的事故原因?
-
NVIC 提供若干个 fault 状态寄存器
-
“总线 fault 状态寄存器”(BFSR),确定产生 fault 的场合:在数据访问时?在取指时?还是在中断的堆栈操作时?以字方式访问,地址是 0xE000_ED28,以字节方式访问,地址是0xE000_ED29
-
精确的总线 fault,肇事的指令的地址被压在堆栈中。如果 BFSR 中 的 BFARVALID 位为 1,还可以找出是在访问哪块存储器时产生该总线 fault ,该存储器的地址被放到“总线 fault 地址寄存器(BFAR)”。
-
不精确的总线 fault,无从定位
精确的总线 fault vs. 不精确的总线 fault
- 由数据访问产生的总线 fault,被归类为精确总线 fault 和不精确总线 fault。
- 不精确的总线 faults 中,导致此 fault 的指令早已完成。例如,缓冲区写入。启动缓冲区写入的指令不知何时已经执行了,但是写到中途时才触发总线 fault。可见,这个操作是在若干个时钟周期前执行的,而且不能确定是具体几个周 期之前,也没有记录这期间的程序跳转动作,因此无法确认“肇事者”,故而是不精确的。
- 精确的总线 fault 是被最后一个完成的操作触发的。例如,一个存储器读取导致的 fault总是精确的,因为该指令必须等全部读完时才算执行完成。这样,任何在读取过程中发生的 fault 总能落在该指令的头上。
- 由取指和堆栈操作产生的 fault 总是精确的
- BFSR 寄存器是一个 8 位的寄存器,可以使用字传送和字节传送来读取。
- 以字方式访问,地址是 0xE000_ED28,且第 2 个字节有效;
- 以字节方式访问,地址是 0xE000_ED29
存储器管理 faults
- 多与MPU有关,其诱因一是某次访问触犯了MPU设置的保护策略。二是某些非法访问。
- MemManage faults 的常见诱因:
- 访问了 MPU 设置区域覆盖范围之外的地址(越界)
- 往只读 region 写数据(越权)
- 用户级下访问了只允许在特权级下访问的地址(越权)
- MemManage fault 发生后,其服务例程是使能的,则执行服务例程。如果同时还发生了其它高优先级异常,则优先处理这些高优先级的异常,MemManage 异常被悬起。如果此时处理器已经在处理同级或高优先级异常,或者 MemManage fault 服务例程被除能,则和总线 fault 一样:上访成硬 fault,最终执行的是硬 fault 的服务例程。如果硬 fault 服务例程或 NMI 服务例程的执行也导致了 MemManage fault,那就不可救要了——内核将被锁定。
- 和总线 fault 一样,MemManage fault 必须被使能才能正常响应。
- MemManage fault在 NVIC“系统 handler 控制及状态寄存器”中的
使能位是 MEMFAULTENA
。 - “存储器管理 fault 状态寄存器(
MFSR
)”,调查 MemManage fault 的案发现场,指出导致 MemManage fault 的原因
- 8 位的寄存器,可以使用字传送和字节传送来读取。
- 两种访问方式的地址都是 0xE000_ED28,按字访问时第 1 个字节有效。
用法 faults
硬 fault
- 硬 fault 是总线 fault、存储器管理 fault 以及用法 fault 上访的结果(非硬fault 的服务例程无法执行,它们就会成为“硬伤”——上访(escalation)成硬 fault。)
- 在取向量(异常处理是对异常向量表的读取)时产生的总线 fault 也按硬 fault 处理
硬fault 状态寄存器(HFSR)
,指出产生硬 fault 的原因
应对 faults???
- 根据各种 fault 状态寄存器的值来判定程序错误,并且改正它们
- 应付 fault 的常用方法:
复位
。设置 NVIC“应用程序中断及复位控制寄存器
”中的VECTRESET 位
,将只复位处理器内核而不复位其它片上设施
。有些CM3 芯片可以使用该寄存器的 SYSRESETREQ 位来复位。这种只限于内核中的复位不会复位其它系统部件。恢复
。如果程序尝试访问了协处理器,可以通过一个协处理器的软件模拟器来解决此问题(牺牲性能)中止相关任务
。系统运行了一个 RTOS,则相关的任务可以被终结或者重新开始
SVC 和 PendSV
NVIC
中断配置基础
中断的使能与除能
中断的悬起与解悬
优先级
活动状态
PRIMASK 与 FAULTMASK 特殊功能寄存器
BASEPRI寄存器
异常的配置寄存器
中断建立全过程、
软件中断
SysTick定时器
中断的具体行为
中断/异常的响应序列
异常返回
嵌套的中断
咬尾中断
晚到(的高优先级)异常
异常返回值
中断延迟
异常响应期间的faults
使用异常系统
使用中断
异常/中断服务程序
软件触发中断
使用SVC
SVC示范:用于输出函数
在C中使用SVC
异常服务例程的范例
本文来自博客园,作者:登云上人间,转载请注明原文链接:https://www.cnblogs.com/lj15941314/p/ArmInterruptandAbnormal.html