Hello.
I noticed strange behavior when debugging the system I am analyzing. The system has three periodic tasks:
“Task-1”, with 10 milliseconds of periodicity. High priority.
“Task-2”, with 10 milliseconds of periodicity. Medium priority.
“Task-3” with 10 milliseconds of periodicity. Low priority.
The content of the three tasks is just a critical section, a critical section that is shared. The inversion of priorities occurs frequently, and I am forcing this situation to see how the system behaves temporally. The Systick has a period of 1ms.
From what I read about FreeRTOS, in Cortex-M the context change of a task is done through a pending bit, which in the scenario of periodic tasks can be activated through:
-
Tick timer handler finds a task with the highest priority in the ready queue and sets the pending context switch bit;
-
In the “vDelayTaskUntil” function, which waits for the next activation;
-
When a semaphore is busy and the task that tries to acquire it.
That said, I found this behavior:
Sometimes, while the high priority task is within the semaphore, the context switching takes place for itself, as explained below.
As noted, task-1 does a context switch for itself.
Do you know how to tell me why this happens?
Thank you.
Edit:
Attaching the code of test:
Task-1:
void vTask1_handler(void *params) {
TickType_t xLastWakeTime;
const TickType_t xFrequency = 10;
xLastWakeTime = xTaskGetTickCount();
int i = 0, to =0;
for (;;) {
vTaskDelayUntil(&xLastWakeTime, xFrequency);
to = DWT->CYCCNT;
for (i = 0; i < to % 500; i++);
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
to = DWT->CYCCNT;
for (i = 0; i < to % 5000; i++);
xSemaphoreGive(xSemaphore);
}
}
Task-2:
void vTask2_handler(void *params) {
TickType_t xLastWakeTime;
const TickType_t xFrequency = 10;
xLastWakeTime = xTaskGetTickCount();
int i = 0, to = 0;
for (;;) {
vTaskDelayUntil(&xLastWakeTime, xFrequency);
to = DWT->CYCCNT;
for (i = 0; i < to % 200; i++);
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
to = DWT->CYCCNT;
for (i = 0; i < to % 10000; i++);
xSemaphoreGive(xSemaphore);
}
}
Task-3:
void vTask3_handler(void *params) {
TickType_t xLastWakeTime;
const TickType_t xFrequency = 10;
xLastWakeTime = xTaskGetTickCount();
int i = 0, to=0;
for (;;) {
vTaskDelayUntil(&xLastWakeTime, xFrequency);
to = DWT->CYCCNT;
for (i = 0; i < to % 200; i++);
if (xSemaphoreTake(xSemaphore, portMAX_DELAY) == pdTRUE) {
to = DWT->CYCCNT;
for (i = 0; i < to % 10000; i++);
xSemaphoreGive(xSemaphore);
}
}