operating-system - 从列表 FreeRTOS 定期调度任务
问题描述
我正在使用 FreeRTOS 调度 4 个定期任务的任务集。所有任务都有相同的 10 个时间单位,但它们的发布时间不同。任务 T1、T2、T3、T4 的发布时间分别为 10、3、5、0 个时间单位。所有 4 个任务都存储在链表中gll_t* pTaskList
。任务应该运行,例如,t=0 T4 被释放,t=3 T2 被释放,t=5 T3 被释放,t=10 T1 被释放,T4 在 t = 0 被释放后再次执行,依此类推。 ..
但是,我的调度程序代码有两个问题:
1. 问题在 t=0 时,只有 T4 准备好,但请注意 T1 的发布时间为 10,根据我对 T1 的 if 语句,我有0 % (10 + 10) == 0
,即使 T1 还没有准备好,它也会被释放。我可以引入一个布尔值来告诉任务是否已被释放,但是有没有更聪明的方法来做到这一点而不引入额外的变量?
2. 问题在 t=26,没有任务准备好,但是,任务 T2 被释放。根据我对 T2 的 if 语句,我有26 % (3 + 10) == 0
.
void prvTaskSchedulerProcess(void *pvParameters) {
...
uint32_t uCurrentTickCount = 0;
gll_t* pTaskList = (gll_t*) pvParameters;
WorkerTask_t* pWorkerTask = NULL;
while (true) {
for (uint8_t uIndex = 0; uIndex < pTaskList->size; uIndex++) {
pWorkerTask = gll_get(pTaskList, uIndex);
// Check if the task is ready to be executed
if ( (uCurrentTickCount % (pWorkerTask->uReleaseTime + pWorkerTask->uPeriod) ) == 0) ){
// Dispatch the ready task
vTaskResume(pWorkerTask->xHandle);
}
}
uCurrentTickCount++;
// Sleep the scheduler task, so the other tasks can run
vTaskDelay(TASK_SCHEDULER_TICK_TIME * SCHEDULER_OUTPUT_FREQUENCY_MS);
}
}
使用额外的标志似乎是一个简单的解决方案。但是有人告诉我,引入标志变量并不是最好的解决方案,因为它会降低代码的可读性和可维护性。因此,我想避免使用它们。如果不使用额外的标志(可能更正我的 if 语句条件),如何实现正确的任务调度?
解决方案
请注意,如果您正在恢复的任务没有完成之前的操作并再次挂起,那么以这种方式使用 vTaskResume() 本身就很危险。有关更完整的解释,请参阅 API 文档https://www.freertos.org/taskresumefromisr.html
推荐阅读
- javascript - 用锚标记替换http链接
- node.js - 授权GAE服务器访问Cloud SQL Instance
- java - 如何通过命令提示符安装java
- rest - Restsharp 比 HTTPClient 好在哪里?
- node.js - nodejs app exited with code 0 when docker-compose up
- java - How to implement Parcelable
- c++ - Does any of current C++ compilers ever emit "rep movsb/w/d"?
- kubernetes - GKE Kubernetes 持久卷
- javascript - How I can use a WebSocket connection with Socket.io events and a Koa rest api?
- c# - 更新文档中的对象时,它会转换为字符串