【问题标题】:FreeRTOS context switchingFreeRTOS 上下文切换
【发布时间】:2017-06-13 09:46:11
【问题描述】:

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

EDIT 在我的 FreeRTOS (SAMD21 Cortex-M0+) 端口中,portYIELD() 宏用于简单地请求 SVCall 异常,所以这是用于执行上下文切换的机制(除了来自在滴答中断上运行的调度程序)?

【问题讨论】:

  • 不确定您要问的确切内容,但如果线程在时间片结束之前放弃处理器,则 RTOS 应立即运行调度程序。
  • @FiddlingBits 是的,这就是我想的,但在文档中没有任何痕迹。它只讨论了在每个周期性滴答上运行的 ISR,但是在滴答之间发生的上下文切换呢?调度程序是否接管并执行上下文切换?如果是这样,是否会触发中断(软件)以执行此操作?
  • 最新的 M0 端口不再使用 SVC。但是我希望 SVC 中断会触发 PendSV 中断来进行实际的上下文切换。

标签: c freertos


【解决方案1】:

聚会有点晚了。 我相信在 xQueueReceive 中调用了一个隐式 taskYield。

在 ISR 中,对 xQueueSend 的调用不会调用 taskYield。必须显式调用它(& 在函数末尾)。这让 ISR 可以控制是否进行上下文切换。 因此,如果任务在 xQueueReceive 上被阻塞并因此处于空闲任务中,并且 ISR 被称为执行 xQueueSendFromISR。如果没有调用 taskYield,它将返回空闲任务,直到下一个计时器滴答。即使 xQueueReceive 可以解除阻塞。 如果在 ISR 中调用 taskYield,则会调用调度程序,并且 xQueueReceive 将解除阻塞并在 ISR 之后立即运行。

【讨论】:

    【解决方案2】:

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

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

    您还需要一些关于 Preemptive multitasking 的知识才能了解该模式下的 FreeRTOS。

    编辑 2016-01-29:

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

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

    这也可以从中断处理程序中完成。您可以有处理程序任务,即在某个队列上等待。从中断中,您将一些元素放入队列。中断结束后,FreeRTOS 重新调度到该队列中等待的任务。只有先决条件才能对该任务具有足够高的优先级。这有好处,您在中断中没有做太多事情 - 只是一些清理并将项目发送到队列 - 这是短暂的操作。 xTimerPendFunctionCallFromISR也可以处理中断,这是另一种有趣的中断处理方式。

    也请阅读FreeRTOS fundamentals。关于它的章节有好几章,读起来很有趣。

    【讨论】:

    • 如果一个任务阻塞你不需要调用taskYIELD()。如果任务被阻止,你怎么能?
    • 如果一个任务阻塞,没有办法从任务中调用某些东西,因为它被阻塞了。 RTOS 没有运行被阻止的任务。
    【解决方案3】:

    当当前正在运行的任务阻塞时,您是否在问您必须做什么才能切换到另一个任务?或者您是在询问如何执行上下文切换的机制?实在不清楚。

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

    【讨论】:

    【解决方案4】:

    每当发生诸如 TaskDelay 之类的 OS 调用或将项目发送到队列或释放资源时,如果另一个任何其他任务准备好运行,则 OS 会运行,如果更高优先级的任务准备好运行,它将预先清空当前任务。基本上任何准备运行的最高优先级任务都会运行。只有当两个或多个相同且最高优先级的任务准备好运行时,才会发生时间片。

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

    【讨论】:

    • 好的,所以如果我调用 vTaskDelay(),当前任务会调用 taskYield() 并触发(软件)中断,让调度程序完成其工作。如果我将一个项目放入队列中(或提供二进制信号量或另一个同步事件),内核会检查是否有其他更高优先级的任务正在等待该队列?在所有这些情况下,是不是每次调用的函数都会执行检查并最终触发中断?
    • 我认为这非常正确。调用的函数调用调度程序并完成它的工作。外部中断也可以进行操作系统调用,从而导致另一个任务准备就绪。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-03-25
    • 2011-07-05
    • 2017-08-11
    • 2021-12-22
    • 2015-09-07
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多