我在我的一个项目中使用 FreeRTOS,我正在阅读文档,但有些东西我无法理解。 我知道上下文切换是在触发滴答中断时发生的,因此调度程序会执行其工作并取消阻塞正在等待事件的任务并选择处于就绪状态的更高优先级任务。但是当一个任务在 tick 中断之前阻塞时会发生什么?文档似乎暗示上下文切换会立即发生(例如,两个具有不同优先级的任务各自调用 vTaskDelay() 以释放 CPU 时间片)。它是如何发生的?我进行了搜索,但找不到我的问题的任何答案。
编辑 在我的 FreeRTOS (SAMD21 Cortex-M0+) 端口中使用了 portYIELD() 宏,它只是请求 SVCall 异常,所以这是用于执行上下文切换的机制(除了来自在节拍中断上运行的调度程序)?
最佳答案
有关于 taskYIELD
的文档.此函数可用于请求上下文切换,因此无需等待滴答。上下文切换是特权操作,因此通常由软件中断来完成。在您的情况下,通过 PendSV 和 SVCall。
如果所有任务都被阻止(例如通过 vTaskDelay
),则 FreeRTOS 正在运行 Idle Task . vTaskDelay
在内部使用 portYIELD
请求上下文切换,因为没有办法继续当前任务。
你还需要一些关于Preemptive multitasking的知识了解该模式下的 FreeRTOS。
编辑 2016-01-29:
- 调用延迟函数导致在内部调用
taskYIELD
/portYIELD
。因此,您当前的任务被阻止,并且 FreeRTOS 重新安排到最高优先级的任务,可以运行(也没有被阻止)或空闲任务,如果没有任务可以运行。 - 打电话,例如
xQueueReceive
有两种可能性。队列中有一些元素,所以它被弹出。队列中没有元素,所以任务切换到blocked state并且为您调用了 YIELD,因此 FreeRTOS 重新安排了另一项任务。 - 打电话,例如
xQueueSend
有两种可能性。队列中没有空间,因此任务将被阻塞,直到有一些空间为止。至少有一个空闲元素,因此您可以将其插入队列。
从队列接收元素或向队列发送元素可以唤醒其他更高优先级的任务,即正在做相反但当前被阻塞。 FreeRTOS 将立即重新安排。
这也可以通过中断处理程序完成。您可以有处理程序任务,它正在等待某个队列。从中断中,您将一些元素放入队列。中断结束后,FreeRTOS 重新调度到等待该队列的任务。在该任务上具有足够高的优先级只是先决条件。这有好处,你在中断中没有做太多 - 只是一些清理并将项目发送到队列 - 这是短期操作。
处理中断也可以通过 xTimerPendFunctionCallFromISR
完成,这是处理中断的另一种有趣方式。
另请阅读 FreeRTOS fundamentals .关于它的章节有好几章,读起来很有趣。
关于c - FreeRTOS 上下文切换,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41898581/