Operating system 从FreeRTOS列表定期分派任务

Operating system 从FreeRTOS列表定期分派任务,operating-system,embedded,dispatcher,freertos,taskscheduler,Operating System,Embedded,Dispatcher,Freertos,Taskscheduler,我正在使用FreeRTOS来分派由4个周期性任务组成的任务集。 所有任务都有相同的10个时间单位,但它们的发布时间不同。对于任务T1、T2、T3、T4,释放时间分别为10、3、5、0个时间单位。所有4个任务都存储在链表gll\u t*pTaskList中。应运行任务,例如:。, t=0 T4被释放,t=3 T2被释放,t=5 T3被释放,t=10 T1被释放,T4被再次执行,因为它在t=0时被释放,依此类推 但是,我的调度程序代码有两个问题: 1。问题在t=0时,只有T4准备就绪,但请注意,T1

我正在使用FreeRTOS来分派由4个周期性任务组成的任务集。 所有任务都有相同的10个时间单位,但它们的发布时间不同。对于任务T1、T2、T3、T4,释放时间分别为10、3、5、0个时间单位。所有4个任务都存储在链表
gll\u 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); 
}
void prvTaskSchedulerProcess(void*pvParameters){
...
uint32\u t uCurrentTickCount=0;
gll_t*pTaskList=(gll_t*)pvParameters;
WorkerTask\u t*pWorkerTask=NULL;
while(true){
对于(uint8\u t uIndex=0;uIndexsize;uIndex++){
pWorkerTask=gll_get(pTaskList,uIndex);
//检查任务是否准备好执行
如果((uCurrentTickCount%(pWorkerTask->uReleaseTime+pWorkerTask->uPeriod))==0){
//分派准备好的任务
vTaskResume(pWorkerTask->xHandle);
}
}
uCurrentTickCount++;
//休眠调度程序任务,以便其他任务可以运行
vTaskDelay(任务调度程序时间*调度程序输出频率);
}
}


使用额外的标志似乎是一个简单的解决方案。然而,我被告知引入标志变量并不是最好的解决方案,因为它会降低代码的可读性和可维护性。因此,我希望避免使用它们。如果不使用额外的标志(可能会更正我的if语句条件),如何实现正确的任务分派?

要解决问题2,请使用以下条件,而不是现有的条件

if ((uCurrentTickCount % pWorkerTask->uPeriod) == pWorkerTask->uReleaseTime)
要解决问题1(和问题2),请使用以下条件

if ((uCurrentTickCount >= pWorkerTask->uReleaseTime) &&
    ((uCurrentTickCount % pWorkerTask->uPeriod) == (pWorkerTask->uReleaseTime % pWorker->uPeriod)))

要解决问题2,请使用以下条件,而不是现有条件

if ((uCurrentTickCount % pWorkerTask->uPeriod) == pWorkerTask->uReleaseTime)
要解决问题1(和问题2),请使用以下条件

if ((uCurrentTickCount >= pWorkerTask->uReleaseTime) &&
    ((uCurrentTickCount % pWorkerTask->uPeriod) == (pWorkerTask->uReleaseTime % pWorker->uPeriod)))

注意:以这种方式使用vTaskResume()具有固有的危险性,如果您正在恢复的任务没有完成之前的操作并再次挂起,则这种危险性微乎其微。请参阅API文档以获得更全面的解释

注意,如果您正在恢复的任务没有完成其先前的操作并再次暂停,则以这种方式使用vTaskResume()具有固有的危险性。请参阅API文档以获得更全面的解释

我不太清楚您的发布时间。这是否意味着任务在T1(t)=10、T2(t)=3、T3(t)=5、T4(t)=0时仅释放一次?在这种情况下,T1和T4不会同时释放。或者是周期性任务,其发布周期为T1=[0,10,20,30]、T2=[0,3,6…]、T3=[0,5,10,15…]、T4=[此处?]?。在这种情况下,T4何时释放?所有任务都会以t=10的周期周期性地释放,但它们的释放时间不同。此处任务的释放时间指任务的第一个作业准备好执行的时间。例如,任务T2在t=3时具有释放时间,因此它不能在t<3时被释放,一旦t=3,它就每隔10个时间单位周期性地执行一次,例如T2={3,13,23,33,…}。类似地,其他任务的作业在以下位置准备好执行:T1={10,20,30,40,…},T3={5,15,25,35,…},T4={0,10,20,30,…}。我不太清楚您的发布时间。这是否意味着任务在T1(t)=10、T2(t)=3、T3(t)=5、T4(t)=0时仅释放一次?在这种情况下,T1和T4不会同时释放。或者是周期性任务,其发布周期为T1=[0,10,20,30]、T2=[0,3,6…]、T3=[0,5,10,15…]、T4=[此处?]?。在这种情况下,T4何时释放?所有任务都会以t=10的周期周期性地释放,但它们的释放时间不同。此处任务的释放时间指任务的第一个作业准备好执行的时间。例如,任务T2在t=3时具有释放时间,因此它不能在t<3时被释放,一旦t=3,它就每隔10个时间单位周期性地执行一次,例如T2={3,13,23,33,…}。类似地,其他任务的作业在以下位置准备好执行:T1={10,20,30,40,…},T3={5,15,25,35,…},T4={0,10,20,30,…}。非常感谢,这正是我要找的。非常感谢,这正是我要找的。我在其他任务中使用
vTaskSuspend
暂停任务,并使用任务调度器的函数
vTaskResume
来恢复它们,在我的例子中,这只是另一个优先级最高的任务。那么,我是否需要在代码中手动检查任务是否已暂停?例如:
eTaskState currentTaskState=eTaskGetState(pHighestPrirorityTaskBlockedBySemaphore->xHandle);如果(currentTaskState!=eRunning){vTaskResume(pWorkerTask->xHandle);}
我在其他任务中使用
vTaskSuspend
挂起任务,并使用任务调度器中的函数
vTaskResume
恢复任务,在我的情况下,这只是另一个优先级最高的任务。那么,我是否需要在代码中手动检查任务是否已暂停?例如:
eTaskState currentTaskState=eTaskGetState(pHighestPrirorityTaskBlockedBySemaphore->xHandle);if(currentTaskState!=eRunning){vTaskResume(pWorkerTask->xHandle);}