Периодически отправляя задачи из списка FreeRTOS - PullRequest
0 голосов
/ 04 января 2019

Я использую FreeRTOS для отправки набора задач из 4 периодических задач. Все задачи имеют одинаковый период в 10 единиц времени, но они отличаются по времени выпуска. Время выпуска составляет 10,3,5,0 единиц времени для задач T1, T2, T3, T4 соответственно. Все 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, согласно моему оператору if для T1 у меня есть 0 % (10 + 10) == 0, и T1 освобождается, даже если он не готов. Я мог бы ввести логическое значение, которое сообщает, была ли задача выпущена, но есть ли более разумный способ сделать это без введения дополнительных переменных?

2. Задача При t = 26 ни одна задача не готова, однако задача T2 освобождается. Согласно моему заявлению if для T2 у меня есть 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); 
}

}

Использование дополнительных флагов кажется простым решением. Однако мне сказали, что введение переменных флагов - не лучшее решение, потому что делает код менее читаемым и обслуживаемым. Таким образом, я хочу избежать их использования. Каким образом будет достигнута правильная диспетчеризация задачи без использования дополнительных флагов (возможно, исправляя условие my if)?

Ответы [ 2 ]

0 голосов
/ 04 января 2019

Обратите внимание, что использование vTaskResume () таким образом опасно по своей природе, если есть даже малейший шанс, что задача, которую вы возобновляете, не завершила свои предыдущие действия и не приостановила себя снова.См. API документы для более полного объяснения https://www.freertos.org/taskresumefromisr.html

0 голосов
/ 04 января 2019

Чтобы исправить проблему 2, используйте следующее условие вместо того, что у вас есть.

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

Чтобы исправить проблему 1 (и проблему 2), используйте следующее условие.

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