operating-systemembeddedscheduled-tasksdispatcherfreertos

Dispatching Tasks periodically from a List FreeRTOS


I am using FreeRTOS to dispatch task set of 4 periodical tasks. All tasks have the same period of 10 time units, but they differ in their release times. Release times are 10,3,5,0 time units for tasks T1,T2,T3,T4 respectively. All 4 tasks are stored inside the linked list gll_t* pTaskList. Tasks should run e.g., t=0 T4 is released, t=3 T2 is released, t=5 T3 is released, t=10 T1 is relased and T4 is executed again since it was released at t = 0, and so on...

However I have two problems with my dispatcher code:

1. Problem At t=0, only T4 is ready, but note that T1 has release time at 10, According to my if statement for T1 I have 0 % (10 + 10) == 0 , and T1 gets released even though it's not ready. I could introduce a boolean that tells whether a task has been released, but is there a smarter way to do it without introducing extra variables?

2. Problem At t=26, no tasks are ready, however, task T2 gets released. According to my if statement for T2 I have 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); 
}
}

Using extra flags seems like a simple solution. However I was told that introducing flags variables is not best solution, because it makes code less readable and maintainable. Thus, I want to avoid using them. How would the correct task dispatching be achieved without using the extra flags (possibly correcting my if statement condition)?


Solution

  • To fix problem 2, use the following condition instead of what you have.

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

    To fix problem 1 (and problem 2), use the following condition.

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