FreeRTOS上下文切换

时间:2017-01-27 16:27:02

标签: c freertos

我正在使用FreeRTOS进行我的项目,而我正在阅读文档,而且我无法理解。 我知道上下文切换是在触发tick中断时发生的,因此调度程序执行其工作并取消阻塞等待事件的任务并选择处于就绪状态的更高优先级任务。但是当任务在嘀嗒中断之前阻塞时会发生什么?文档似乎暗示上下文切换立即进行(例如,两个具有不同优先级的任务,每个调用vTaskDelay()以释放CPU时间片)。怎么会发生?我搜索过但我找不到任何问题的答案。

在我的FreeRTOS端口(SAMD21 Cortex-M0 +)中

编辑,使用了portYIELD()宏来简单地请求SVCall异常,因此这是用于执行上下文切换的机制(除此之外)来自在节拍中断上运行的调度程序)?

4 个答案:

答案 0 :(得分:3)

有关于taskYIELD的文档。此函数可用于请求上下文切换,因此无需等待勾选。上下文切换是特权操作,因此通常由软件中断完成。在你的情况下由PendSV和SVCall。

如果所有任务都被阻止(例如vTaskDelay),则FreeRTOS正在运行Idle TaskvTaskDelay在内部使用portYIELD请求上下文切换,因为无法继续当前任务。

您还需要了解Preemptive multitasking如何在该模式下了解FreeRTOS。

修改2016-01-29:

  • 调用延迟功能会导致内部调用taskYIELD / portYIELD。因此,当前任务被阻止,FreeRTOS重新安排到最高优先级任务,可以运行(也不会被阻止),或者如果没有任务可以运行,则可以运行到空闲任务。
  • 致电,例如xQueueReceive可以有两种可能性。队列中有一些元素,因此它是POPed。队列中没有元素,因此任务切换到blocked state并为您调用YIELD,因此FreeRTOS会重新编译为另一个任务。
  • 致电,例如xQueueSend可以有两种可能性。队列中没有空间,因此任务被阻止,直到有一些空间。至少有一个免费元素,因此您可以推送到队列。

从队列接收元素或将元素发送到队列可以唤醒其他更高优先级的任务,即执行oposite但当前被阻止。 FreeRTOS会立即重新安排。

这也可以从中断处理程序完成。您可以拥有处理程序任务,即在某个队列上等待。从中断中,您将一些元素放入队列。中断结束后,FreeRTOS重新安排到等待该队列的任务。只有先决条件才能对该任务有足够的高优先级。这样做有好处,你在中断方面做得不多 - 只需要清理并将项目发送到队列 - 这是一个简短的操作。 处理中断也可以由xTimerPendFunctionCallFromISR完成,这是另一种处理中断的有效方法。

另请阅读FreeRTOS fundamentals。关于它有几个章节,这是有趣的阅读。

答案 1 :(得分:1)

每当一个OS调用,例如TaskDelay或将项目发送到队列或释放资源时,如果另一个任何其他任务准备好运行,操作系统就会运行,如果准备好运行更高优先级的任务,它将预先运行排除当前任务。基本上任何准备运行的最高优先级任务都将运行。时间分片仅在两个或更多具有相同和最高优先级的任务准备好运行时发生。

是的,中断运行。在皮质-m上,PENDSV中断执行上下文切换。

答案 2 :(得分:1)

当你正在运行的任务阻止时,你是在问你要做什么来切换到另一个任务?或者您在询问上下文切换的执行机制?它真的不太清楚。

如果您在一个任务阻止时询问如何切换到另一个任务,那么答案就是什么,这是RTOS为您做的基本原理。例如,如果调用vTaskDelay()或指定阻塞时间的xQueueReceive(),则任务进入阻塞状态。当任务被阻止时,它无法运行,因此RTOS中的调度算法选择要运行的下一个任务并启动该任务的运行。

答案 3 :(得分:0)

晚会晚了。 我相信在xQueueReceive内部会调用一个隐式taskYield。

在一个ISR内部,对xQueueSend的调用不会调用taskYield。必须显式调用它(在函数末尾&)。这使ISR可以控制是否进行上下文切换。 因此,如果某个任务在xQueueReceive上被阻止,并因此在Idle任务中说了,则将一个ISR称为执行一个xQueueSendFromISR。如果未调用taskYield,它将返回到空闲任务,直到下一个计时器计时。即使xQueueReceive可以取消阻止。 如果在ISR中调用taskYield,则将调用调度程序,并且xQueueReceive将在ISR之后立即取消阻塞并可能运行。