Priority inversion is a bug where the task with a high priority is blocked indirectly by a task with a lower priority that runs longer period than the high priority task. This example is a demonstration of the priority inversion using the mutex semaphore.
Code Example:
#include "bsp.h"
SemaphoreHandle_t xMutex; /* Mutex semaphore 1 */
static void Task_HP( void *pvParameters ); /* Task high priority function */
static void Task_LP( void *pvParameters ); /* Task low priority function */
int main( void )
{
HAL_Init();
SEGGER_SYSVIEW_Conf( );
SEGGER_SYSVIEW_Start( );
xMutex = xSemaphoreCreateMutex(); /* Create the Mutex Semaphore */
xTaskCreate( Task_HP, "Task_HP", 240, NULL, 2, NULL ); /* Register Task1 to turn on LEDs */
xTaskCreate( Task_LP, "Task_LP", 240, NULL, 1, NULL ); /* Register Task2 to turn off LEDs */
vTaskStartScheduler(); /* Init the Kernel */
}
void Task_HP( void *pvParameters )
{
for(;;)
{
xSemaphoreTake( xMutex, portMAX_DELAY ); /* High priority task take the mutex */
SEGGER_SYSVIEW_PrintfHost( "Task HP takes mutex" );
vTaskDelay(250); /* Duration of code protection */
SEGGER_SYSVIEW_PrintfHost( "Task HP gives mutex" );
xSemaphoreGive(xMutex); /* High priority task gives the mutex */
vTaskDelay(250);
}
}
void Task_LP( void *pvParameters )
{
for(;;)
{
xSemaphoreTake( xMutex, portMAX_DELAY ); /* Low priority task take the mutex */
SEGGER_SYSVIEW_PrintfHost( "Task LP takes mutex" );
vTaskDelay(1000); /* Duration of code protection */
SEGGER_SYSVIEW_PrintfHost( "Task LP gives mutex" );
xSemaphoreGive(xMutex); /* Low priority task gives the mutex */
vTaskDelay(250);
}
}
Two Tasks are registered in the application, Task_HP
is registered with a priority of 2, and Task_LP
is registered with a priority of 1.
This tasks take first the mutex semaphore and block it until the period elapsed, when Task_LP
runs the mutex is taken blocking the execution of the high priority task Task_HP
for 1000 ticks, causing that Task_HP
execute as a low priority task.
SystemView Output:
Observe in the terminal that task_LP ( Task low priority ) is executed blocking the execution of the task_HP ( Task high priority ), when Task_LP finished the Task_HP executes for just a brief period to after execute again the Task_LP blocking the other task, ignoring the task priority.
TimeLine:
Observe in the timeline the execution of Task, put attention to the start time of the "Task_LP", the task take the mutex blocking a part of the code, after a vtask_delay function is executed to simulate a long period execution of mutex protection. When time is elapsed the mutex is released and other task can use it. |
|
Observe that "Task_HP" runs again but is blocked for the mutex that is taken by the "Task_LP". |
|
When the "Task_LP" period elapsed, "Task_HP" takes the mutex semaphore for a short period, finishing soon its execution. |
|