I created three tasks with 1ms, 5ms and 10ms
Priorities
1st scenario :
1ms - 1st task has highest priority
5ms - 2nd Priority
10ms - 3rd priority
Tasks aren’t switching after 1ms task, only 1ms task is running and remaining tasks aren’t running
2nd scenario:
I kept all the tasks as same priority that time my tasks are running like sequential order the way defined the tasks in code
1st iteration:
1ms - Running
5ms - Running
10ms - Running
At 2nd iteration:
5ms task running first
1ms task running 5 times
and jump to 10ms
I want to run the tasks 1ms 5ms 10ms and again 1ms 5ms 10ms and so on
Does any one help me out what is the issue and how to resolve
Regarding your first scenario, if the 1 ms task has the highest priority and calls vTaskDelay(pdMS_TO_TICKS(1)), the scheduler moves it to the blocked state for 1ms (which is equal to 1 tick as you mentioned). When the next tick interrupt occurs, the 1 ms delay expires, and the task becomes Ready again without allowing enough time for the 5ms task to run. Since it’s the highest priority task in the system, the scheduler chooses it to run over all other lower-priority tasks. This cycle continues, the task delays, becomes ready on the next tick, and runs again, leaving no CPU time for the 5 ms and 10 ms tasks. They remain starved unless the 1 ms task blocks for longer or yields voluntarily.
To solve your issue you can implement a high-priority master timer-driven task that activates other tasks on the designated time and let the other tasks to be of the same priority (e.g. master task is 3 and all other tasks are 2). In the master task, maintain a tick counter or phase and notify only one task at a time, per 1 ms tick, in the desired sequence. This ensures that after the master task finishes, only the designated task will be in the ready state and will be scheduled to run. This design has a drawback that every task will have to wait at least 3ms to be rescheduled. Also, with this approach you won’t be able to run the tasks in the sequence of 1ms->5ms->10ms because while the second task is blocked for 5ms or the third task is blocked for 10ms, the first task will get a chance to run multiple times. If you want to synchronise the tasks to run one after another you will need to add some task synchronisation mechanisms (ex. Semaphores) to block the first task from running once again while the second and third task haven’t ran yet.
void vMasterTask(void *pvParameters)
{
TickType_t xLastWakeTime = xTaskGetTickCount();
uint32_t ulPhase = 0;
uint32_t ulTickCount = 0;
for (;;)
{
vTaskDelayUntil(&xLastWakeTime, pdMS_TO_TICKS(1));
ulTickCount++;
switch (ulPhase % 3)
{
case 0:
xTaskNotifyGive(task1msHandle);
break;
case 1:
if (ulTickCount % 5 == 0)
{
xTaskNotifyGive(task5msHandle);
}
break;
case 2:
if (ulTickCount % 10 == 0)
{
xTaskNotifyGive(task10msHandle);
}
break;
}
ulPhase++;
}
}
void addTask(void *pvParameters)
{
for (;;)
{
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
/* wait for the mutex to be unlocked by the third task here */
result3 = add_variable - 5;
add_variable--;
}
}
One big thing to note is that vTaskDelayUntil has a significant difference from vTaskDelay, in that vTaskDelay measures from “now”, (or at least the beginning of the current tick) while vTaskDelayUntil measures from the last time the task was scheduled to wake. This means that a loop with vTaskDelayUntil(&last, 2) will wake you up every other tick, even if it took you more than a tick to get back to that delay point, while vTaskDelay in that case would measure from the point the vTaskDelay call was made.
Thus, if the goal is repetitive operations at a long term stable rate, you want to use vTaskDelayUntil instead of vTaskDelay. Note, you are still subject for each loop to possible be “late” if higher priority tasks delay you by running when you want to run.
You also often want to be using xTaskDelayUntil and check the return value, which will tell you if you have been delayed so much that you started the delay already late for the wakeup call, so you can decide if you want to skip some of the cycles, or if you want to try to catch up.