目录
中断优先级分组
ARM Cortex-M 内核的 MCU 具有一个用于中断管理的嵌套向量中断控制器(NVIC,全称:Nested vectored interrupt controller)。ARM Cortex-M 的 NVIC 最大可支持 256 个中断源,其中包括 16 个系统中断和 240 个外部中断,然而芯片厂商一般情况下都用不完这些资源。以下为Cortex-M3的异常类型表:
ARM Cortex-M 使用 NVIC 对不同优先级的中断进行管理,在 core_cm3.h中可以找到如下的结构体定义:
typedef struct
{
__IOM uint32_t ISER[8U]; /* 中断使能寄存器 */
uint32_t RESERVED0[24U];
__IOM uint32_t ICER[8U]; /* 中断除能寄存器 */
uint32_t RSERVED1[24U];
__IOM uint32_t ISPR[8U]; /* 中断使能挂起寄存器 */
uint32_t RESERVED2[24U];
__IOM uint32_t ICPR[8U]; /* 中断除能挂起寄存器 */
uint32_t RESERVED3[24U];
__IOM uint32_t IABR[8U]; /* 中断有效位寄存器 */
uint32_t RESERVED4[56U];
__IOM uint8_t IP[240U]; /* 中断优先级寄存器 */
uint32_t RESERVED5[644U];
__OM uint32_t STIR; /* 软件触发中断寄存器 */
} NVIC_Type;
其中比较重要的是成员变量 IP,该成员变量是一个uint8_t类型的数组,数组内有240个元素,每一个8bit的元素就用来配置对应的外部中断的优先级,所以最大中断的优先级配置范围应该是0-255。但是芯片厂商一般并不会用完所有的位来配置中断,对于STM32只用到了其高4位[7:4],低四位[3:0]取零处理,因此STM32提供了16级的中断优先等级。
STM32将中断分为了5个组,组0~4,该组是由SCB->AIRCR 寄存器的 bit10~8 来定义的。
根据写入的值不同以配置不同的优先级分组,对应的值在库函数中有如下定义:
#define NVIC_PriorityGroup_0 ((uint32_t)0x700) /*!< 0 bits for pre-emption priority
4 bits for subpriority */
#define NVIC_PriorityGroup_1 ((uint32_t)0x600) /*!< 1 bits for pre-emption priority
3 bits for subpriority */
#define NVIC_PriorityGroup_2 ((uint32_t)0x500) /*!< 2 bits for pre-emption priority
2 bits for subpriority */
#define NVIC_PriorityGroup_3 ((uint32_t)0x400) /*!< 3 bits for pre-emption priority
1 bits for subpriority */
#define NVIC_PriorityGroup_4 ((uint32_t)0x300) /*!< 4 bits for pre-emption priority
不同分组对应的抢占优先级与子优先级的分配如下:
对于FreeRTOS,官方建议使用中断优先级分组4,即高4位全部用于抢占优先级,不使用子优先级,这样做是为了使得任务调度与中断屏蔽更加简单与清晰。
除了外部中断,系统中断有独立的中断优先级配置寄存器,分别为 SHPR1、SHPR2、SHPR3系统处理程序优先级寄存器。
三个系统中断优先级配置寄存器
SHPR1
SHPR1 寄存器的地址为 0xE000ED18,用于配置 MemManage、BusFault、UsageFault 的中断优先级,各比特位的功能描述如下所示:
寄存器描述如下
SHPR2
SHPR2 寄存器的地址为 0xE000ED1C,用于配置 SVCall(系统服务调用中断) 的中断优先级。
寄存器描述如下
SHPR3
SHPR3 寄存器的地址为 0xE000ED20,用于配置 PendSV(可悬挂请求)、SysTick 的中断优先级。
寄存器描述如下
FreeRTOS 在配置 PendSV 和 SysTick中断优先级的时候,就使用到了 SHPR3 寄存器。
其他的系统中断如NMI(不可屏蔽中断)、hard fault(硬fault)是不可编程的,所以无法进行配置。
NMI(Non-Maskable Interrupt):NMI(不可屏蔽中断)是一种特殊类型的中断,其优先级高于大多数其他中断,包括硬件错误中断(HardFault)。它通常用于处理一些关键的系统级事件,如存储器校验错误或外部事件。NMI中断在优先级上位于硬件故障(HardFault)之上,这意味着即使系统发生了HardFault,NMI中断也可能得到处理。
HardFault(硬件故障)中断:HardFault是指发生在CPU执行期间的硬件故障,例如访问无效地址或未对齐的存储器访问。在STM32中,HardFault中断由CPU自动生成,当出现严重的硬件错误或不可恢复的软件错误时触发。它通常表示系统进入了无法继续正常执行的状态。HardFault中断处理程序允许开发者检测和记录发生的错误,并在可能的情况下采取某些修复措施,尽管在大多数情况下,这个中断处理程序主要用于诊断和记录故障状态,而不是尝试继续执行。
三个中断屏蔽寄存器
ARM Cortex-M 有三个用于屏蔽中断的寄存器,分别为 PRIMASK、FAULTMASK 和BASEPRI。
PRIMASK
作用:PRIMASK 寄存器有 32bit,但只有 bit0 有效,是可读可写的,将 PRIMASK 寄存器设置为 1 用于屏蔽除 了NMI(不可屏蔽中断)和 HardFault(硬件错误中断)外的所有异常和中断,将 PRIMASK 寄存器清 0 用于使能中断。
FAULTMASK
作用:FAULTMASK 寄存器有 32bit,但只有 bit0 有效,也是可读可写的,将 FAULTMASK寄存器设置为 1 用于屏蔽除NMI(不可屏蔽中断)外的所有异常和中断,也就是说连同 hard fault 也会被屏蔽掉。将 FAULTMASK 寄存器清零用于使能中断。
BASEPRI
作用:BASEPRI 有 32bit,但只有低 8 位[7:0]有效,也是可读可写的。BASEPRI 寄存器比起 PRIMASK 和 FAULTMASK 寄存器直接屏蔽掉大部分中断的方式,BASEPRI 寄存器的功能显得更加细腻BASEPRI 用于设置一个中断屏蔽的阈值,设置好 BASEPRI 后,中断优先级低于等于 BASEPRI 的中断就都会被屏蔽掉,FreeRTOS 就是使用 BASEPRI 寄存器来管理和屏蔽中断的,而不受 BASEPRI 设置的值管理的中断,则不受影响。