FreeRTOS 中断优先级配置(重要)
NVIC 基础知识
对于 M3 和 M4 内核的 MCU,每个中断的优先级都是用寄存器中的 8 位设置的。
8 位的话就可以 设置 2^8 = 256 级中断,实际中用不了这么多,所以芯片厂商根据自己生产的芯片做出了调整。
比如 ST 的 STM32F1xx 和 F4xx 只使用了这个 8 位中的高四位[7:4],低四位取零,这样 2^4=16,只能表示 16 级中断嵌套。
STM32F1xx 和 F4xx 都是只使用了这个 8 位寄存器的高四位[7:4]

STM32 支持 5 种优先级分组,系统上电复位后,默认使用的是优先级分组 0,也就是没有抢占式优先级,只有子优先级
1.具有高抢占式优先级的中断可以在具有低抢占式优先级的中断服务程序执行过程中被响应,即中断嵌套,或者说高抢占式优先级的中断可以抢占低抢占式优先级的中断的执行。
2.在抢占式优先级相同的情况下,有几个子优先级不同的中断同时到来,那么高子优先级的中断优 先被响应。
3.在抢占式优先级相同的情况下,如果有低子优先级中断正在执行,高子优先级的中断要等待已被响应的低子优先级中断执行结束后才能得到响应,即子优先级不支持中断嵌套。
4. Reset、NMI、Hard Fault 优先级为负数,高于普通中断优先级,且优先级不可配置。
5. 系统中断(比如:PendSV,SVC,SysTick)是不是一 定比外部中断(比如 SPI,USART)要高?,答案:不是的,它们是在同一个 NVIC 下面设置的。
配置抢占优先级和子优先级,他们合并成的 4bit 数字的数值越小,优先级越高
使用 FreeRTOS 时如何配置外设 NVIC
官方强烈建议将 Cortex-M3 内核和 Cortex-M4 内核 的 NVIC 优先级分组设置为 4,
(注意:一旦初始化好 NVIC 的优先级分组后,切不可以在应用中再次更改。)
设置 NVIC 的优先级分组为 4 表示支持 0-15 级抢占优先级(注意,0-15 级是 16 个级别,包含 0 级),不支持子优先级
反映在 STM32 标准库的配置上就是如下:
FreeRTOS 配置选项中 NVIC 相关配置
◆ #define configPRIO_BITS 4
此宏定义用于配置 STM32 的 8 位优先级设置寄存器实际使用的位数。
◆ #define configLIBRARY_LOWEST_INTERRUPT_PRIORITY 0x0f
此宏定义是用来配置 FreeRTOS 用到的 SysTick 中断和 PendSV 中断的优先级。
在 NVIC 分组设置为 4 的情况下,此宏定义的范围就是 0-15,即专门配置抢占优先级。这里配置为了 0x0f,即 SysTick 和 PendSV 都是配置为了最低优先级,实际项目中也建议大家配置最低优先级即可。
◆ #define configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01
此宏定义比较重要,定义了受 FreeRTOS 管理的最高优先级中断。
简单的说就是允许用户在这个中断服务程序里面调用 FreeRTOS 的 API 的最高优先级。
设置 NVIC 的优先级分组为 4 的情况下。配置 此宏定义为 0x01 表示用户可以在抢占式优先级为1到 15 的中断里面调用 FreeRTOS 的 API 函数,抢占式优先级为 0 的中断里面是不允许调用的。
不受 FreeRTOS 管理中断的深入讨论
中断延迟时间是衡量 RTOS 实时操作系统的一项重要指标,那什么又是中断延迟呢?
从中断触发到执行中断服务程序的第一条指令这段时间就是中断延迟时间。
FreeRTOS 内核源码中有多处开关全局中断的地方,这些开关全局中断会加大中断延迟时间。
比如在源码的某个地方关闭了全局中断,但是此时有外部中断触发,这个中断的服务程序就需要等到再次开启全局中断后才可以得到执行。开关中断之间的时间越长,中断延迟时间就越大,这样极其影响系统的实时性。 如果这是一个紧急的中断事件,得不到及时执行的话,后果是可想而知的。
针对这种情况,FreeRTOS 就专门做了一种新的开关中断实现机制。
关闭中断时仅关闭受 FreeRTOS 管理的中断,不受 FreeRTOS 管理的中断不关闭,这些不受管理的中断都是高优先级的中断,用户可以在这些中断里面加入需要实时响应的程序。FreeRTOS 能够实现这种功能的奥秘就在于 FreeRTOS 开关中断 使用的是寄存器 basepri

uCOS 这种使用的是 primask

比如配置寄存器 basepri 的数值为 16,所有优先级数值大于等于 16 的中断都会被关闭,优先级数值小于 16 的中断不会被关闭。对寄存器 basepri 寄存器 赋值 0,那么被关闭的中断会被打开。这个就是 FreeRTOS 开关中断的实现方案。
FreeRTOS 任务优先级修改及其分配方案
下面对 FreeRTOS 优先级相关的几个重要知识点进行下说明,这些知识点在以后的使用中务必要掌握牢固。
◆ FreeRTOS 中任务的最高优先级是通过 FreeRTOSConfig.h 文件中的 configMAX_PRIORITIES 进行配置的,用户实际可以使用的优先级范围是 0 到 configMAX_PRIORITIES – 1。
比如我们配置此宏定义为 5,那么用户可以使用的优先级号是 0,1,2,3,4,不包含 5。
◆ 用户配置任务的优先级数值越小,那么此任务的优先级越低,空闲任务的优先级是 0。
◆ 建议用户配置宏定义 configMAX_PRIORITIES 的最大值不要超过 32,即用户任务可以使用的优先级范围是0到31。
◆ 如果用户在 FreeRTOSConfig.h 文件中配置宏定义 configUSE_TIME_SLICING 为 1,或者没有配置此宏定义,时间片调度都是使能的。
另外,只要芯片资源允许,可以配置任意多个同优先级任务。
(备注:没有定义 configUSE_TIME_SLICING,也能使用时间片调度是因为此宏定义默认已经在 FreeRTOS.h 文件中使能)
◆ FreeRTOS 中处于运行状态的任务永远是当前能够运行的最高优先级任务。
任务优先级分配方案

◆ IRQ 任务:IRQ 任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先级最高的。
◆ 高优先级后台任务:比如按键检测,触摸检测,USB 消息处理,串口消息处理等,都可以归为这一类任务。
◆ 低优先级的时间片调度任务:比如 LED 数码管的显示等不需要实时执行的都可以归为这一类任务。
实际应用中用户不必拘泥于将这些任务都设置为同优先级任务,可以设置多个优先级,只需注意这类任务不需要高实时性。
◆ 空闲任务:空闲任务是系统任务。
◆ 特别注意:IRQ 任务和高优先级任务必须设置为阻塞式(调用消息等待或者延迟等函数即可),只有这样,高优先级任务才会释放 CPU 的使用权,从而低优先级任务才有机会得到执行。
这里的优先级分配方案是推荐的一种方式,实际项目也可以不采用这种方法。调试出适合项目需求的才是最好的。
中断优先级和任务优先级区别
简单的说,两者之间没有任何关系,不管中断的优先级是多少,中断的优先级永远高于任何任务的优先级,即任务在执行的过程中,中断来了就开始执行中断服务程序。 另外对于 STM32F103,F407 和 F429 来说,中断优先级的数值越小,优先级越高。而 FreeRTOS 的任务优先级是,任务优先级数值越小,任务优先级越低。
任务优先级修改
◆ vTaskPrioritySet ()
◆ 第 1 个参数是任务句柄,用于区分不同的任务。
◆ 第 2 个参数是给任务配置的新优先级。
使用这个函数要注意以下问题:
1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskPrioritySet 1
2. 如果第二个参数里面填的是 NULL,即数值 0 的话,那么配置的就是当前正在执行的任务。
3. 如果被修改的任务的优先级,修改后高于正在执行的任务,将执行任务切换,切换到修改好的高优先级任务。
4. 第二个参数数值不可大于等于 FreeRTOSConfig.h 文件中的宏定义:
#define configMAX_PRIORITIES 配置的数值。
任务优先级获取
vTaskPriorityGet ()
使用这个函数要注意以下问题:
1. 使用此函数需要在 FreeRTOSConfig.h 配置文件中配置如下宏定义为 1
#define INCLUDE_vTaskPriorityGet 1
2. 如果第二个参数里面填的是 NULL,即数值 0 的话,那么获取的优先级就是当前正在执行的任务。