 Hello, in this part we'll practice a bit mutexes using CMC's OS version 2 and freeRTOS. It's time to do some practice. We'll prepare a simple example where we will have two tasks, task1 and task2, with the same priority and those tasks can send some messages over ITM interface. So we will use our task action function, which has been used in previous exercises. There will be three operations within each task function body. The first one is wait for mutex, then once the mutex is taken the task will perform some right operation over ITM interface and then at the end it will release the mutex to allow the next task to do these actions. Let's start from stm32cubemix or stm32cubedie configurations. Please go to freeRTOS configuration tab and select task and kills. Create two tasks within task list. We need to have two tasks, task1 and task2 with the same priority level. It can be OS priority normal, the same stack size and function names like start task1 and start task2. Then please select config parameters tab and enable use mutexes. In the next step, please select mutexes tab, click on add button under mutexes section and create a mutex, keeping all the settings in default value. After this, please click OK. After this process, you should see the single mutex within mutexes list. Further, please generate the project in Cubemix, it's enough to press CTRL-S and open main.cfile. Within main.cfile we can notice that there are three operating system components placed within private variable sections, two handlers of the tasks and one handler of the mutex. Within main function, after hardware initialization, there is a new section, create the mutexes where the mutex is created. Going further, within main.cfile, please locate start task1 function and place the following code within its endless loop area. At the beginning, the line OS delay with argument 2000 to not spam the single wire viewer, this line will send the task for two seconds to blocked state. As a result, we will see one on the single wire viewer each two seconds. The next line is OS mutex acquire with two arguments. The first one is a mutex handler and the second one is a timeout set to 1000 milliseconds. This function will wait for mutex for maximum one second being in a blocked state. The third function is a task underscore action, which is sending one over the single wire viewer. The last line within this endless loop is OS mutex release with handler to our mutex as only argument. This will release mutex to other task. Similar code, please locate within an endless loop of start task 2, but with different argument for task action function. After those operations, please build a code, start debug session, run single wire viewer, ITM viewer and run the code. As a result, we may expect the similar view like in the picture. Both tasks one by one are taking mutex, performing connection, displaying the single digit and releasing the mutex. In our next example, we will test mutex biggest advantage, the priority inheritance and we will compare it to binary semaphore. To do this, we will simulate the following situation. We will add task 3, which will send some data over SWO. This task will not fight for the mutex and then within task 1 inside the area where the task holds the mutex, we will decrease its priority after third iteration so the scheduler should switch the context from task 1 to task 2 or task 3, which will have the higher priority. Please notice that task 1 will not manage release of the mutex before. Despite of this, task 2 will manage to collect the mutex as scheduler will rise temporarily the priority of task 1 to allow mutex release. It would be our priority inheritance mechanism. After this operation, we can see only task 2 and task 3 being active. Let's have a look on practical implementation. We can continue with the same exercise by adding task 3, the same parameters like task 1 and task 2, and line binary semaphore with default settings. This binary semaphore will be used further in this exercise. After those operations, please generate the project and open main.c file. We'll start with start task 1 function body processing. We need a local variable idx, which will be defined before endless loop. Then within the loop, we'll try to get the mutex using function osmutexacquire. As a timeout argument, we'll use oswhiteforever to block this task till it receives the mutex. Then there is a classical action of the task using task action function, which is in our case sending 1 over swo interface. Then we are waiting for 4th occurrence of this loop, when we will decrease the priority of this task to ospriority low level. It will result in a context switch from task 1 to task 2 or task 3, as those two tasks have higher priority set to ospriority normal. In the next line, there is a simple increase of idx. At the end of this loop, we can see release of the mutex and then just after the delay of 500 milliseconds to not spam the single wire viewer. Within start task 3, a function body of mute task 3, there will be a task action, which will send 3 over swo and after this, we'll have half delay with argument 500. Then we'll keep our start task 2 function body as an previous example without any modifications. After those operations, please build a project, start the debug session, start switm viewer and run the code. This is an expected result. At the beginning, I mean first three iterations, we can see execution of task 3, then task 1 and then task 2. In 4th operation, we can see still task 1, as operating system is performing priority inheritance by temporary increase of its priority to level of task 2, so task 1 can release the mutex. After this, we can see only task 2 and task 3 execution, as task 1 has a lower priority and there is no situation where both tasks, so task 2 and task 3, are in a blocked state. So for example by calling osdelay. Now let's have a look how the same application will work if we will change mutex into binary semaphore. The only modifications needed here are within start task 1 and start task 2 functions by replacement osmutexacquire with ossemaphoreacquire function and osmutexrelease with ossemaphorerelease functions. The same operations we should do within start task 2 function body, there is no change within start task 3 function. After all of the modifications, please build the project, start debug session, run swvitm viewer and run the code. What is the effect? We can see three complete iterations of task 3, task 1, task 2, but during the fourth one, once we lowered the priority of task 1, it is just after it performs its action, so we can see this fourth one on the output. Both tasks, I mean task 1 and task 2 are blocked. Task 1 is blocked due to the fact that it has lower priority than other tasks and task 2 is blocked because it is waiting for the semaphore already taken by task 1. Task 3 can operate without any problem as it is the only one in ready state because it is not waiting for the semaphore. Thank you for watching this video.