1.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,有个重要的知识点就是优先级分组,抢占优先级和子优先级。
STM32F1xx 和 F4xx 都是只使用了这个 8 位寄存器的高四位[7:4]。

Reset、NMI、Hard Fault 优先级为负数,高于普通中断优先级,且优先级不可配置。
对于初学者还有一个比较纠结的问题就是系统中断(比如:PendSV,SVC,SysTick)是不是一
定比外部中断(比如 SPI,USART)要高,答案:不是的,它们是在同一个 NVIC 下面设置的。
1.2 使用 FreeRTOS 时如何配置外设 NVIC
FreeRTOS中NVIC 优先级分组设置为 4,这 样中断优先级的管理将非常方便。
设置 NVIC 的优先级分组为 4
抢占优先级可配置范围是 0-15,那么数值越小, 抢占优先级的级别越高,即 0 代表最高优先级,15 代表最低优先级。
1.3 FreeRTOS 配置选项中 NVIC 相关配置
1.4 不受 FreeRTOS 管理中的的深入讨论
primask | 这是个只有 1 个 bit 的寄存器。 在它被置 1 后,就关掉所有可屏蔽的异常,只剩下 NMI 和硬 fault 可以响应。它的缺省值是 0,表示没有关中断。 |
faultmask | 这是个只有 1 个 bit 的寄存器。当它置 1 时,只有 NMI 才能响应,所有其它的异 常,甚至是硬 fault,也通通闭嘴。它的缺省值也是 0,表示没有关异常。 |
basepri | 这个寄存器最多有 9 位(由表达优先级的位数决定)。它定义了被屏蔽优先级的阈值。 当它被设成某个值后,所有优先级号大于等于此值的中断都被关(优先级号越大,优 先级越低)。但若被设成 0,则不关闭任何中断, 0 也是缺省值。 |
2.1任务优先级说明
freertos中,数字越大,优先级越高。与stm32的nvic相反。
- FreeRTOS 中任务的最高优先级是configMAX_PRIORITIES
- 用户实际可以使用的优先级范围是 0 到 configMAX_PRIORITIES – 1
- 用户配置任务的优先级数值越小,那么此任务的优先级越低,空闲任务的优先级是 0。
- 建议用户配置宏定义 configMAX_PRIORITIES 的最大值不要超过 32,
- 通用方式,没有优化—配置宏定义 configUSE_PORT_OPTIMISED_TASK_SELECTION 为 0
- 所有平台的移植文件都可以配置为 0,因为这是通用方式。
- 纯 C 编写,比专用方式效率低。
- 可用的优先级数量不限制。
- 专用方式,进行优化—配置宏定义 configUSE_PORT_OPTIMISED_TASK_SELECTION 为为 1
- 部分平台支持。
- 这些平台架构有专用的汇编指令可以加速算法执行速度。
- 比通用方式高效。
- 有最大优先级数限制,通常限制为 32 个。
- 通用方式,没有优化—配置宏定义 configUSE_PORT_OPTIMISED_TASK_SELECTION 为 0
- 只要芯片资源允许,可以配置任意多个同优先级任务。
- FreeRTOS 中处于运行状态的任务永远是当前能够运行的最高优先级任务
什么是时间片:时间片就是同一个优先级下可以有多个任务,每个任务轮流地享有相同的 CPU 时间, 享有 CPU 的时间我们叫时间片。
2.2任务优先级分配

- IRQ 任务:IRQ 任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先 级最高的。
- 高优先级后台任务:比如按键检测,触摸检测,USB 消息处理,串口消息处理等,都可以归为这一类 任务。
- 低优先级的时间片调度任务:比如 emWin 的界面显示,LED 数码管的显示等不需要实时执行的都可 以归为这一类任务。实际应用中用户不必拘泥于将这些任务都设置为优先级 1 的同优先级任务,可以 设置多个优先级,只需注意这类任务不需要高实时性。
- 空闲任务:空闲任务是系统任务。
对于 STM32F103 来说,中断优先级的数值越小,优先级越高。
而 FreeRTOS 的任务优先级是,任务优先级数值越小,任务优先级越低。
2.3任务优先级修改
FreeRTOS 的任务优先级修改:vTaskPrioritySet (TaskHandle_t xTask, UBaseType_t uxNewPriority)
- 第 1 个参数是任务句柄,用于区分不同的任务。
- 第 2 个参数是给任务配置的新优先级
2.4任务优先级获取
FreeRTOS 的任务优先级获取:vTaskPriorityGet ( TaskHandle_t xTask )
- 第 1 个参数是任务句柄,用于区分不同的任务。
configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY 0x01
为 0x01 表示用户可以在抢 占式优先级为 1 到 15 的中断里面调用 FreeRTOS 的 API 函数,抢占式优先级为 0 的中断里面是 不允许调用的。
3,任务调度—抢占式,时间片和合作式
3.1
FreeRTOS 操作系统支持的任务调度方式:抢占式,时间片和合作式
说合作式调度主要用在资源有限的设备上面,现在已经很少使用了。
- 抢占式调度:每个任务都有不同的优先级,任务会一直运行直到被高优先级任务抢占或者遇到阻塞式的 API 函数, 比如 vTaskDelay。
- 时间片调度:每个任务都有相同的优先级,任务会运行固定的时间片个数或者遇到阻塞式的 API 函数,比如 vTaskDelay,才会执行同优先级任务之间的任务切换。
3.2什么是调度器
调度器:调度器就是使用相关的调度算法来决定当前需要执行的任务。
- 调度器可以区分就绪态任务和挂起任务(由于延迟,信号量等待,邮箱等待,事件组等待等原因而使 得任务被挂起)。
- 调度器可以选择就绪态中的一个任务,然后激活它(通过执行这个任务)。当前正在执行的任务是运 行态的任务。
- 不同调度器之间最大的区别就是如何分配就绪态任务间的完成时间
嵌入式实时操作系统的核心就是调度器和任务切换,调度器的核心就是调度算法。
3.3抢占式调度器
抢占式调度要掌握的最关键一点是:每个任务都被分配了不同的优先级,抢占式调度 器会获得就绪列表中优先级最高的任务,并运行这个任务。
如果在 FreeRTOSConfig.h 中禁止使用时间片调度,那么每个任务必须配 置不同的优先级。
例子:
- 创建 3 个任务 Task1,Task2 和 Task3。
- Task1 的优先级为 1,Task2 的优先级为 2,Task3 的优先级为 3。FreeRTOS 操作系统是设置的数值 越小任务优先级越低,故 Task3 的优先级最高,Task1 的优先级最低。

3.4 时间片调度器
- 最常用的的时间片调度算法就是 Round-robin 调度算法,
- 时间片调度适合用于不要求任务实时响应的情况。
- 只有同优先级任务才会使用时间片调度
- 使能#define configUSE_TIME_SLICING 1

说明:
- 创建 4 个同优先级任务 Task1,Task2,Task3 和 Task4。
- 每个任务分配的时间片大小是 5 个系统时钟节拍。
- 任务 Task3 在运行期间调用了阻塞式 API 函数,调用函数时,虽然 5 个系统时钟节拍的时间片大小 还没有用完,此时依然会通过时间片调度切换到下一个任务 Task4。(注意,没有用完的时间片不会 再使用,下次任务 Task3 得到执行还是按照 5 个系统时钟节拍运行)
- 任务 Task4 运行够 5 个系统时钟节拍后,通过时间片调度切换到任务 Task1
本文地址: freertos学习笔记四之中断优先级,任务优先级,任务调度