- 传送门:博客汇总帖
笔记内容参考(正点原子的FreeRTOS开发手册、cortex-m3权威指南、Cortex-M3和Cortex-M4权威指南等)
1、中断、异常
在 ARM 编程领域中,凡是打断程序顺序执行的事件,都被称为异常(exception),中断是异常的一种程序代码也可以主动请求进入异常状态的(常用于系统调用)。
所有的 Cortex-M处理器都会提供一个用于中断处理的嵌套向量中断控制器(NVIC)。除了中断请求,还有其他需要服务的事件,将其称为“异常”。 Cortex-M处理器中的其他异常包括错误异常和其他用于OS支持的系统异常(如SVC指令)。处理异常的程序代码一般被称作异常处理,NVIC接收多个中断源产生的中断请求,如图所示。
Cortex-m3和 Cortex-m4的NVIC支持最多240个IRQ(中断请求)、1个不可屏蔽中断(NMI)、1个 Sys Tick(系统节拍)定时中断及多个系统异常。多数IRQ由定时器、I/O端口和通信接口(如UART和IC)等外设产生。NMI通常由看门狗定时器或掉电检测器等外设产生,其余的异常则是来自处理器内核,中断还可以利用软件生成。
下表列出了 Cortex‐M3 可以支持的所有异常类型。
当一个发生的异常被 内核接受,对应的异常 handler 就会执行。为了决定 handler 的入口地址,CM3 使用了“向量表查表机制”。这里使用一张向量表。向量表其实是一个 WORD(32 位整数)数组,每个下标对应一种异常,该下标元素的值则是该异常 handler 的入口地址。向量表的存储位置是可以设置的(有一个寄存器可以设置中断向量表偏移),通过 NVIC 中的一个重定位寄存器来指出向量表的地址。在复位后,该寄存器的值为 0。因此,在地址 0 处必须包含一张向量表,用于初始时的异常分配。
举个例子,如果发生了异常 11(SVC),则 NVIC 会计算出偏移移量是 11x4=0x2C,然后从那里取出服务例程的入口地址并跳入。
0 号异常的功能则是个另类,它并不是什么入口地址,而是给出了复位后 MSP 的初值。
2、优先级的定义
优先级的数值越小,则优先级越高。CM3 支持中断嵌套,使得高优先级异常会抢占(preempt)低优先级异常。有 3 个系统异常:复位,NMI 以及硬 fault,它们有固定的优先级,并且它们的优先级号是负数,从而高于所有其它异常。所有其它异常的优先级则都是可编程的(但不能编程为负数)。
定义优先级的寄存器是8位 ,所以就有256个优先级,但实际不会使用这么多,考虑功耗等问题。
STM32优先级配置的寄存器是高4位有效,低四位无效(ST设计),就有16位可编程优先级
为了使抢占机能变得更可控,M3 还把 256 级优先级按位分成高低两段,分别是抢占优先级和亚优先级。(优先级分组)
图中有8个优先级分组,划线的是无效分组,因为STM32优先级配置的寄存器是高4位有效,低四位无效
/** @defgroup CORTEX_Preemption_Priority_Group CORTEX Preemption Priority Group
* @{
*/
#define NVIC_PRIORITYGROUP_0 0x00000007U /*!< 0 bits for pre-emption priority
4 bits for subpriority */
#define NVIC_PRIORITYGROUP_1 0x00000006U /*!< 1 bits for pre-emption priority
3 bits for subpriority */
#define NVIC_PRIORITYGROUP_2 0x00000005U /*!< 2 bits for pre-emption priority
2 bits for subpriority */
#define NVIC_PRIORITYGROUP_3 0x00000004U /*!< 3 bits for pre-emption priority
1 bits for subpriority */
#define NVIC_PRIORITYGROUP_4 0x00000003U /*!< 4 bits for pre-emption priority
0 bits for subprio