 Hello, in this part we will focus on mutexes. This exercise will demonstrate the basic features of mutex. In this part we will create a simple example with two tasks and one single mutex. So I'm starting with STM32Q by DE. You can use as well as STM32Q by MIX and your preferred tool chain. So I start new STM32 project. My microcontroller is STM32 L476RG but you can use any other STM32 device. So L476RG, this is my part. I will name my project 9 underscore mutex underscore basic. I will wait for pinout of my microcontroller. As I told you, in the project we will have two tasks. Task 1 and task 2 on equal priority and the one single mutex. And both tasks will perform some actions holding the mutex. Just to be sure that only one task is performing some action at, let's say, one moment. It can be used, for example, to have unique access to some communication peripheral. Okay, from hardware components we would need only the debug interface. So I go to system, core, sys and within debug I'm selecting trace asynchronous SW to have SWD and to have single wire output which is used for single wire trace. It is quite a convenient way to communicate between, let's say, the tasks or interrupts and the console within QPyD environment. Okay, the next point we would need to change is a time-based source which is used for HAL libraries. So this is the timer which is used for timeouts and delays within HAL functions. By default it is SysTik, but as SysTik will be used by operating system we will select other timer. Timer 6 is a good candidate because he doesn't have an input nor output channels. So it's a good choice. Then we need to enable the free R2S, so I go to middleware, free R2S and the interface I'm selecting CMCs version 2. So let's continue with this. The first point I would like to check is whether motexes are already enabled within the config parameters. Let me remind you that these config parameters and include parameters are stored within stm32config.h file which is generated automatically upon the creation of the project once we are using stm32QpyD or QBemix. Okay, my motexes are enabled, so use motexes are enabled and we can create tasks. We'll rename the default task into task1. So I double-click on it. I change its name to task1. For priority normal it will be the same and let's say the stack size 256 words and the entry function starts task1. I will create another task, so I'm coming back to tasks and queues, click add and task2 priority it will be normal 256 words as a stack size and start task2 as an entry function. That's it. So those are, let's say, our two tasks we would like to use within this exercise. Then we'll enable one motex, so I go to motex.stab and when this motex is sectioned I'm clicking add. I would keep the default name, so my motex01, I press OK. Those are, let's say, all operations within 3-year task configuration and in the configurator in general, so I generate the project. Okay, my project is generated. I can open main.cfile. If it's not done automatically, I can find it within core, source and main.cfile. And the next point would be the code manipulation, code modification. So our project and we'll focus on main.cfile. Within main.cfile, if I go below, I can see as usual the creation of operating system components. So in our case, those will be, let's say, two tasks, task1 and task2. And we can see as well the definitions and the handler declaration of our motex. Then going below, within main function, I can see the hardware initialization, then the initialization of the kernel. So in fact, a location of its heap memory area. And just after, I can see the creation of the motex. There is a typical function OSMutexNew. And the only argument is an address for the structure with the attributes. The visible attributes for us is the name, which we specified with configuration part. And the rest of it contains the pointer to the structure of the motex where it holds its configuration and parameters. If we go below, we can see the creation of both tasks and starting the scheduler. So the next point on our side would be coding of both tasks. So let's start from task1. We'll start with some longer delay. So sending our task to the block state for two seconds. Then we would like to acquire the motex. Because as I already mentioned at the beginning, in our application, we would like to hold to share the motex between those two tasks, task1 and task2. And during holding the motex, the particular task would perform some unique operation, which should not be done by the other task. Please remember that during the task code execution, we do not have the full control what part of the code would be executed when, let's say, the time given to the task. So what may happen that we will be preempted by other tasks, by the scheduler to within operation on some interface, shared interface, which should not be shared between the tasks. So sometimes it is important to really block the resource using motex in this case to be sure that the operations on this interface will be finalized by the given task before it will be given to the other task. This is the purpose of our exercise. So after our task will return to the run state from blocked state, it will try to collect the motex. So as motex acquire, so as you can see the name in convention is very similar to use and semaphores. So motex acquire and then we need motex scheduler and the timeout. So we will try to do it within one second. Then we will do sign of life and this, in fact, is simulating our unique access to the shared resources. In this case, this shared resource is, let's say, the instrumentation trace macrosol, so ITM interface, which is displaying messages on the console. So this is single wire trace, in fact. So this is the shared resource and after we perform this right operation on this interface, we can release the motex. So as motex release and again we need the handler and that's it. Okay, so this is task one, those are task one operations. Now let's go to task two and the only difference would be that there would be different sign of life. Okay, we need to specify this task action. So let me edit here. In my examples, I'm using ITM interface to send, let's say, simple characters, as you see. So this function would be like this, can be like this, you can use as well. For example, you want interface for this or some LED blinking if you have more LEDs. On Nucleo, I've got only one, so it would be quite difficult to use any other sign of life using one LED only. Okay, so this function could look like sent char and it would be a message and I would send as well a sign of new line. Okay, and we need a declaration. This section is quite nice because it's private function prototypes. Okay, so we are done with the coding. We can check whether the application will work like we expected. So I would build the code. In the meantime, I'm connecting the board as well and I can start a debug session. Okay, I click on the back icon to start a debug session. Within the debugger tab, I'm enabling the single wire viewer and I'm changing the core clock to 4 MHz, which is our case. And then I start a debug session. Okay, we will need the single wire viewer ITM data console. I've got it already here. In case you do not have it, please go to quick access, enter SWV and please select this line with this monitor icon over here. Once done it, you will need to configure it using this icon. Select enable port, let's say zero and start tracing by pressing this icon. Once done, I can just start code execution. And we can see execution of our code one by one. So we can see that tasks are executed one by one and in fact the access to the ITM interface is quite unique due to the mutex. So that's all for this exercise. In next one, we will change a bit the code and we will compare the behavior of the application by replacing mutex with the semaphore. So thank you for watching this video.