Date: marzo 27, 2025
Author: Guillermo Garcia
Categories: RTOS Tags: FreeRTOS
Mutexe in FreeRTOS managing shared resources among multiple tasks is crucial. Mutexes (short for mutual exclusion) provide a mechanism to ensure that only one task accesses a shared resource at a time, preventing race conditions and ensuring data integrity. In this article, we will explore the concept of mutexes in FreeRTOS.
Table of Contents
A mutex is a type of binary semaphore that includes a priority inheritance mechanism. It allows a task to lock a resource, preventing other tasks from accessing it until the mutex is released. Unlike binary semaphores, mutexes help mitigate priority inversion problems, making them a preferred choice for resource management.
FreeRTOS provides APIs to create and use mutexes efficiently. Below is an example demonstrating the use of a mutex to protect a shared resource.
Mutexes are taken using xSemaphoreTake(), and given using xSemaphoreGive().
xSemaphoreTakeRecursive()
and xSemaphoreGiveRecursive()
can only be used on mutexes created using xSemaphoreCreateRecursiveMutex().
Mutexes and binary semaphores are very similar but have some subtle differences: Mutexes include a priority inheritance mechanism, binary semaphores do not. This makes binary semaphores the better choice for implementing synchronisation (between tasks or between tasks and an interrupt), and mutexes the better choice for implementing simple mutual exclusion.
Creates a mutex, and returns a handle by which the created mutex can be referenced. Mutexes cannot be used in interrupt service routines.
#include "FreeRTOS.h" #include "task.h" #include "semphr.h" SemaphoreHandle_t Mutex; void vATask( void * pvParameters ) { /* Create a mutex type semaphore. */ Mutex = xSemaphoreCreateMutex(); if( Mutex!= NULL ) { /* The Mutex was created successfully and can be used. */ } }
Priority inversion is a freak 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.
#include "Mutex.h" /* Mutex semaphore 1 */ SemaphoreHandle_t xMutex; void Task_HP( void *pvParameters ) { while(1) { /* High priority task take the mutex */ xSemaphoreTake( xMutex, portMAX_DELAY ); SEGGER_SYSVIEW_PrintfHost( "Task HP takes mutex" ); vTaskDelay(250); SEGGER_SYSVIEW_PrintfHost( "Task HP gives mutex" ); /* High priority task gives the mutex */ xSemaphoreGive(xMutex); vTaskDelay(250); } } void Task_LP( void *pvParameters ) { while(1) { /* Low priority task take the mutex */ xSemaphoreTake( xMutex, portMAX_DELAY ); SEGGER_SYSVIEW_PrintfHost( "Task LP takes mutex" ); vTaskDelay(1000); SEGGER_SYSVIEW_PrintfHost( "Task LP gives mutex" ); /* Low priority task gives the mutex */ xSemaphoreGive(xMutex); vTaskDelay(250); } } void Mutual_Exclusion(void) { /* Create the Mutex Semaphore */ xMutex = xSemaphoreCreateMutex(); /* Create tasks */ xTaskCreate(Task_HP, "Task_HP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+2, NULL); xTaskCreate(Task_LP, "Task_LP", configMINIMAL_STACK_SIZE, NULL, tskIDLE_PRIORITY+1, NULL); }
The possible sequence of execution depicted shows the higher priority Task 2 having to wait for the lower priority Task 1 to give up control of the mutex. A higher priority task being delayed by a lower priority task in this manner is called priority inversion. This undesirable behavior would be exaggerated further if a medium priority task started to execute while the high priority task was waiting for the semaphore the result would be a high priority task waiting for a low priority task without the low priority task even being able to execute.
The LP task take a mutex before begin preempted by the HP task.
So the HP task attempts to take the mutex but can’t because it is still being held by the LP task. The HP task enters the Blocked state to wait for the mutex to become available.
The LP task continues to execute, but gets preempted by the MP task before it gives the mutex back.
Mutexes in FreeRTOS are essential for ensuring mutual exclusion and preventing race conditions in embedded systems. By implementing mutexes correctly, FreeRTOS applications can manage shared resources efficiently while maintaining system responsiveness and stability. The most notable difference between a Semaphore and a Mutex is that the Mutex prevents priority inversion.
Deja una respuesta