FreeRTOS Mutual Exclusion – Mutex

Keywords: Embedded systems, ARM, FreeRTOS, Semaphore, Tasks Mutual Exclusion, Mutex

Code Link: Tutorial Source Code Github – Keil

As discussed in the introductory tutorial Mutexes are almost similar to Binary Semaphore with the exception of resource ownership. In Mutex Tasks owns a resource and can’t be taken even by high priority Tasks. Whereas binary semaphores are the better choice for implementing synchronisation (between tasks or between tasks and an interrupt), mutexes are the better choice for implementing simple mutual exclusion (hence ‘MUT’ual ‘EX’clusion).

Embedded Systems are normally resource limited and non-expandable. A common example is the use of UART. There may be multiple independent software parts writing to a single UART. UART is normally used to transmit ASCII characters. If multiple parts of software parts are writing to the same UART, the output on the serial window will display all the strings mix up. As an example, the following videos shows how to freeRTOS Tasks are writing string simultaneously to serial debug window.

* Task1 Prints: “Message From Task-1: FreeRTOS Task-1 Running…
* Task2 Prints: “Message From Task-2: FreeRTOS Task-2 Running…

As can be seen while the one task has not yet finished writing to serial port, the context switch preempt the first task and runs the second task resulting into mixing of two strings.

To solve these situation where a common resource is required to be used by one process (independent of priority) at a time until completion, Mutex (Mutual-Exclusion) is best suited.

Tutorial Scenario:

In this tutorial two freeRTOS Tasks writes messages to the same serial debug port of STM32F4-Discovery. Each Task before using the debug serial port, locks the resource (debug serial port) via an earlier created Mutex and once the Task is finished writing to the debug serial port, it unlock the resource to be used by other Task.

Follow are the tutorial steps.

Steps:

1. The first step is to create a Mutex via xSemaphoreCreateMutex() to be used later by tutorial Tasks.

mutexHandle = xSemaphoreCreateMutex();

Where mutexHandle is Mutex handle declared globally and used to reference Mutex later in code.

/*
  Mutex Handle
*/
SemaphoreHandle_t mutexHandle;

xSemaphoreCreateMutex() is already explained in the introductory tutorial.

Once the mutex creation is successful, two freeRTOS tasks are created (vTask1, vTask2) and Scheduler is started else an error message is sent to the debug port.

if (mutexHandle != NULL ) {

  xTaskCreate (vTask1, "T1", 200, NULL, 1, NULL);

  xTaskCreate (vTask2, "T2", 200, NULL, 1, NULL);

  vTaskStartScheduler();
    
}else {
    
  printf ("failed to create Mutex!\n");
  while (1);
}

Note: If you don’t know how freeRTOS tasks are created, we have a dedicated tutorial for freeRTOS Tasks. Link to the tutorial is given bellow.

2. Next step is to define Task Functions i.e. vTask1 and vTask2 for the tasks created in the first step. Both are similar. only vTask1 definition is given bellow.

void vTask1(void * pvParams) {

  volatile unsigned int i = 0;

  for (;;) {
    
    xSemaphoreTake(mutexHandle, portMAX_DELAY); 
    
    printf("Message From Task-1: FreeRTOS Task-1 Running...\n");

    xSemaphoreGive( mutexHandle );    
    
    /*Dummy Delay - Lazy work */
    for (i =0; i < 200000; ++i);
  }
}

Note: As mentioned in the introductory tutorial both xSemaphoreTake() and xSemaphoreGive() APIs are used for both Semaphore and Mutexes.

xSemaphoreTake(mutexHandle, portMAX_DELAY) tries to Lock the the Mutex mutexHandle. If mutex is not available, the Task will be sent to Block State for indefinite time. Once the Mutex is available, it locks it and print message to debug serial port. and once printing completes, the mutex is released/unlocked to be used by other tasks. Once the mutex is locked, no other task can interrupt the printf operation. The dummy delay via for (i =0; i < 200000; ++i); is given to slow down the rate at which the messages are displayed on debug window.

The following videos demonstrate the message sent from freeRTOS tasks to debug serial window. As the difference can be clearly seen between the video present earlier in this tutorial and the bellow video. In the bellow video no message interfere with each other.

For complete source code refer to Github link given at the start of this tutorial.

Note: We have routed printf messages to ST-Link debugger via ARM-ITM. There is a dedicated tutorial on how to redirect printf messages to debugger. Link to the tutorial is given bellow.

Click the full screen button for more clear view.

References:

[1] – FreeRTOS Official Website



298 thoughts on “FreeRTOS Mutual Exclusion – Mutex”

Leave a Reply

Your email address will not be published. Required fields are marked *