freertos之中断优先级、任务优先级、任务调度

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]。
freertos之中断优先级、任务优先级、任务调度_第1张图片

优先级数字越小,优先级越大

Tips:

  • Reset、NMI、Hard Fault 优先级为负数,高于普通中断优先级,且优先级不可配置。
  • 对于初学者还有一个比较纠结的问题就是系统中断(比如:PendSV,SVC,SysTick)是不是一定比外部中断(比如 SPI,USART)要高,答案:不是的,它们是在同一个 NVIC 下面设置的。

1.2 中断优先级和任务优先级的区别

  1. 首先,这两者之间没有任何关系,不管中断的优先级是多少,中断的优先级永远高任何任务的优先级,即在执行的过程中,中断来了就开始执行中断服务程序。
  2. 对于STM32F103、F407来说,中断优先级数值越小,优先级就越高,而FreeRTOS的任务优先级是,任务优先级数值越小,任务优先级越低。

2.1 任务优先级说明

  • 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 个。
  • 只要芯片资源允许,可以配置任意多个同优先级任务。
  • FreeRTOS 中处于运行状态的任务永远是当前能够运行的最高优先级任务

Tips: 什么是时间片:时间片就是同一个优先级下可以有多个任务,每个任务轮流地享有相同的 CPU 时间, 享有 CPU 的时间我们叫时间片。

2.2 任务优先级分配

freertos之中断优先级、任务优先级、任务调度_第2张图片

  • IRQ 任务:IRQ 任务是指通过中断服务程序进行触发的任务,此类任务应该设置为所有任务里面优先级最高的。
  • 高优先级后台任务:比如按键检测,触摸检测,USB 消息处理,串口消息处理等,都可以归为这一类任务。
  • 低优先级的时间片调度任务:比如 emWin 的界面显示,LED 数码管的显示等不需要实时执行的都可以归为这一类任务。实际应用中用户不必拘泥于将这些任务都设置为优先级 1 的同优先级任务,可以设置多个优先级,只需注意这类任务不需要高实时性。
  • 空闲任务:空闲任务是系统任务。

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.1 任务调度 ---- 抢占式,时间片和合作式

FreeRTOS 操作系统支持的任务调度方式:抢占式,时间片和合作式

合作式调度主要用在资源有限的设备上面,现在已经很少使用了。

  • 抢占式调度:每个任务都有不同的优先级,任务会一直运行直到被高优先级任务抢占或者遇到阻塞式的 API 函数, 比如 vTaskDelay。
  • 时间片调度:每个任务都有相同的优先级,任务会运行固定的时间片个数或者遇到阻塞式的 API 函数,比如 vTaskDelay,才会执行同优先级任务之间的任务切换。

3.2 什么是调度器

调度器:调度器就是使用相关的调度算法来决定当前需要执行的任务。

  • 调度器可以区分就绪态任务和挂起任务(由于延迟,信号量等待,邮箱等待,事件组等待等原因而使得任务被挂起)。
  • 调度器可以选择就绪态中的一个任务,然后激活它(通过执行这个任务)。当前正在执行的任务是运行态的任务。
  • 不同调度器之间最大的区别就是如何分配就绪态任务间的完成时间。

Tips:嵌入式实时操作系统的核心就是调度器和任务切换,调度器的核心就是调度算法。

3.3 抢占式调度器

抢占式调度要掌握的最关键一点是:每个任务都被分配了不同的优先级,抢占式调度器会获得就绪列表中优先级最高的任务,并运行这个任务。

Tips:如果在 FreeRTOSConfig.h 中禁止使用时间片调度,那么每个任务必须配置不同的优先级。

  • 创建 3 个任务 Task1,Task2 和 Task3。
  • Task1 的优先级为 1,Task2 的优先级为 2,Task3 的优先级为 3。FreeRTOS 操作系统是设置的数值越小任务优先级越低,故 Task3 的优先级最高,Task1 的优先级最低。
    freertos之中断优先级、任务优先级、任务调度_第3张图片

3.4 时间片调度器

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

freertos之中断优先级、任务优先级、任务调度_第4张图片
说明

  • 创建 4 个同优先级任务 Task1,Task2,Task3 和 Task4。
  • 每个任务分配的时间片大小是 5 个系统时钟节拍。
  • 任务 Task3 在运行期间调用了阻塞式 API 函数,调用函数时,虽然 5 个系统时钟节拍的时间片大小还没有用完,此时依然会通过时间片调度切换到下一个任务 Task4。
  • 任务 Task4 运行够 5 个系统时钟节拍后,通过时间片调度切换到任务 Task1。

Tips:注意,没有用完的时间片不会再使用,下次任务 Task3 得到执行还是按照 5 个系统时钟节拍运行。

参考

  1. https://blog.openpilot.cc/archives/3142
  2. https://blog.csdn.net/nanjoh/article/details/94395765

你可能感兴趣的:(freertos,stm32)