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