FreeRTOS的任务
使用 RTOS 的实时应用程序可以被构建为一组独立的任务。每个任务在自己的上下文中执行,不依赖于系统内的其他任务或 RTOS 调度器本身。在任何时间点,应用程序中只能执行一个任务,实时 RTOS 调度器负责决定所要执行的任务。因此, RTOS 调度器可以在应用程序执行时重复启停每个任务(将任务调入或调出)。由于任务不了解 RTOS 调度器活动,因此实时 RTOS 调度器负责确保任务调入时的处理器上下文(寄存器值、堆栈内容等)与任务调出时的处理器上下文完全相同。为实现这一点,每个任务都分配有自己的堆栈。当任务调出时,执行上下文被保存到该任务的堆栈中,以便以后再调入相同的任务时可以准确地恢复其执行上下文。
简而言之, RTOS 任务的调入与调出就是对处理器上下文的保存与恢复。任务调度主要是三个关键词:固定优先级,抢占式,时间片轮询。
任务状态
- 运行 当任务实际执行时,它被称为处于运行状态。任务当前正在使用处理器。如果运行RTOS的处理器只有一个内核,那么在任何给定时间内都只能有一个任务处于运行状态。
- 准备就绪 准备就绪任务指那些能够执行(它们不处于阻塞或挂起状态),但目前没有执行的任务,因为同等或更高优先级的不同任务已经处于运行状态。
- 阻塞
如果任务当前正在等待时间或外部事件,则该任务被认为处于阻塞状态。 例如,如果一个任务调用
vTaskDelay()
,它将被阻塞(被置于阻塞状态),直到延迟结束-一个时间事件。 任务也可以通过阻塞来等待队列、信号量、事件组、通知等事件。处于阻塞状态的任务通常有一个"超时"期, 超时后任务将被超时,并被解除阻塞,即使该任务所等待的事件没有发生。 阻塞状态下的任务不使用任何处理时间,不能被选择进入运行状态。 - 挂起
与"阻塞"状态下的任务一样,"挂起"状态下的任务不能被选择进入运行状态,但处于挂起状态的任务没有超时。相反,任务只有在分别通过
vTaskSuspend()
和xTaskResume()
API调用明确命令时才会进入或退出挂起状态。
任务优先级
优先级分配从0
到configMAX_PRIORITIES - 1
。
数字越小优先级越低。
多个任务可以公用同一个优先级。
任务调度
单核(默认调度)
FreeRTOS 默认使用固定优先级的抢占式调度策略,对同等优先级的任务执行时间片轮询调度:
- 固定优先级:指调度器不会永久更改任务的优先级,尽管它可能会因优先级继承而暂时提高任务的优先级。
- 抢占式:调度器始终运行优先级最高且可运行的 RTOS 任务,无论任务何时能够运行。
- 时间片轮询:调度器会在每个 tick 中断( RTOS 用来衡量时间的周期性中断)上在同等优先级任务之间进行切换, tick 中断之间的时间构成一个时间片。
优先级继承是为了防止优先级反转现象采取的一种优化机制。 如低优先级任务获取了高优先级任务需要的资源,会提升低优先级任务的优先级。
优先级反转低优先级任务占据了高优先级任务的资源(信号量等),出现系统一直运行中等优先级任务的一种不合理现象。
configUSE_PREEMPTION = 0
:关闭抢占configUSE_TIME_SLICING = 0
:关闭时间片切换
非对称多核(AMP调度)
每个核心各自运行自己的FreeRTOS,互不影响。
使用 FreeRTOS 的非对称多处理 (AMP) 是指多核设备的每个核心都单独运行自己的 FreeRTOS 实例。这些 核心并不都需要具有相同架构,但如果 FreeRTOS 实例之间需要进行通信,则需要共享一些内存。
每个核心都会运行自己的 FreeRTOS 实例, 因此任何给定核心上的调度算法与上文的单核系统调度算法完全相同 。您可以使用流缓冲区或消息缓冲区作为核间通信原语, 这样一来,一个核心上的任务可以进入“阻塞”状态, 以等待另一个核心发来的数据或事件。
对称多核(SMP调度)
由FreeRTOS来调度,将不同任务分配到不同的核心。
使用 FreeRTOS 的对称多处理 (SMP) 是指 一个 FreeRTOS 实例可以跨多个处理器核心调度 RTOS 任务。由于只有一个 FreeRTOS 实例在运行,一次只能使用 FreeRTOS 的一个端口, 因此每个核心必须具有相同的处理器架构并共用相同的内存空间。
FreeRTOS SMP 调度策略使用与单核调度策略相同的算法,但与单核和 AMP 场景不同的是,SMP 在任何给定时间都会导致多个任务处于运行状态 (每个核心上都有一个运行状态的任务)。这意味着,只有缺乏可运行的高优先级任务时,才会运行低优先级任务的假设不再成立。要想了解其中的原因,请考虑一下,若起初只有一个高优先级任务和两个中等优先级任务处于”就绪“状态,SMP 调度器会如何选择在双核微控制器上运行的任务。调度器需要选择两个任务,每个核心对应一个任务。首先,高优先级任务是指可运行的最高优先级任务,因此会选择将它用于第一个核心。这样就剩下了两个中等优先级的任务作为可运行的最高优先级任务,因此会将它们用于第二个核心。结果是高优先级和中等优先级的任务同时运行。