1 、NVIC 基 础 知 识
NVIC 的全称是 Nested vectored interrupt controller,即嵌套向量中断控制器。
对于 M3 和 M4 内核的 MCU,每个中断的优先级都是用寄存器中的 8 位来设置的。8 位的话就可以设置 2^8 = 256 级中断,实际中用不了这么多,所以芯片厂商根据自己生产的芯片做出了调整。比如 ST的 STM32F1xx 和 F4xx 只使用了这个 8 位中的高四位[7:4],低四位取零,这样 2^4=16,只能表示 16级中断嵌套。
对于这个 NVIC,有个重要的知识点就是优先级分组,抢占优先级和子优先级,下面就以 STM32 为例进行介绍,STM32F1xx 和 F4xx 都是只使用了这个 8 位寄存器的高四位[7:4]。
从上面的表格可以看出,STM32 支持 5 种优先级分组,系统上电复位后,默认使用的是优先级分组0,也就是没有抢占式优先级,只有子优先级,关于这个抢占优先级和这个子优先级有几点一定要说清楚。
另外特别注意一点,配置抢占优先级和子优先级,他们合并成的4bit 数字的数值越小,优先级越高,这一点千万不要搞错了。
2、 使用 FreeRTOS 时 如 何 配 置 外设 NVIC
强烈推荐用户将 Cortex-M3 内核的 STM32F103 和 Cortex-M4 内核的 STM32F407 以及STM32F429 的 NVIC 优先级分组设置为 4,即:NVIC_PriorityGroupConfig(NVIC_PriorityGroup_4);这样中断优先级的管理将非常方便。这个也是官方强烈建议的。此函数在 bsp_Init 中第一个被调用:
(注意:一旦初始化好 NVIC 的优先级分组后,切不可以在应用中再次更改。)
设置 NVIC 的优先级分组为 4 表示支持 0-15 级抢占优先级(注意,0-15 级是 16 个级别,包含 0 级),不支持子优先级。反映在 STM32 标准库的配置上就是如下:
在这里继续强调下这一点,在 NVIC 分组为 4 的情况下,抢占优先级可配置范围是 0-15,那么数值越小,抢占优先级的级别越高,即 0 代表最高优先级,15 代表最低优先级。
3 、FreeRTOS 配 置 选 项 中 NVIC 相 关 配 置
FreeRTOSConfig.h 配置文件中设置到 NVIC 中断的有如下几个选项:
4 、不受 FreeRTOS 管 理 中 断 的 深 入 讨 论
讲解不受 FreeRTOS 管理的中断之前要说一个小知识点----中断延迟。中断延迟时间是衡量 RTOS 实时操作系统的一项重要指标,那什么又是中断延迟呢?从中断触发到执行中断服务程序的第一条指令这段时间就是中断延迟时间。
FreeRTOS 内核源码中有多处开关全局中断的地方,这些开关全局中断会加大中断延迟时间。比如在源码的某个地方关闭了全局中断,但是此时有外部中断触发,这个中断的服务程序就需要等到再次开启全局中断后才可以得到执行。开关中断之间的时间越长,中断延迟时间就越大,这样极其影响系统的实时性。如果这是一个紧急的中断事件,得不到及时执行的话,后果是可想而知的。
针对这种情况,FreeRTOS 就专门做了一种新的开关中断实现机制。关闭中断时仅关闭受 FreeRTOS管理的中断,不受 FreeRTOS 管理的中断不关闭,这些不受管理的中断都是高优先级的中断,用户可以在这些中断里面加入需要实时响应的程序。FreeRTOS 能够实现这种功能的奥秘就在于 FreeRTOS 开关中断使用的是寄存器 basepri,而像 uCOS 这种使用的是 primask,详情请看下面整理的表格:
对寄存器 basepri 我们举一个例子,帮助大家理解,比我们配置寄存器 basepri 的数值为 16,所有优先级数值大于等于 16 的中断都会被关闭,优先级数值小于 16 的中断不会被关闭。对寄存器 basepri 寄存器赋值 0,那么被关闭的中断会被打开。这个就是 FreeRTOS 开关中断的实现方案。