Hello! Within this part we will focus on changing priorities from the user code. We can continue from exercise from previous lab. Just to those of you who started with us just now, we are using STM32Cube IDE with Nucleo L476RG board, but you can select the different STM32-based hardware. I will just open the exercise I used in the previous part, but I would comment it such a way so you can create it on your side. So let's start from Cubemix perspective, so the configuration of the pinouts. This is our STM32L476RG. You can see already some pins are visible here. Those would be visible if you select the system core sys. And then within this, please select within the debug trace asynchronous SW. It will give you both SWD interface lines and one additional line single wire output, which is used for a single wire trace. Then I have changed as well the time base source from default SysTick to Timer 6. This time base is used by the HAL library and to organize the timeouts and delays. And Timer 6 is my chosen timer because it do not have NM input nor output channels. So this is why I selected this one. There are no other peripherals used here. There is a default clock configuration, so the MSI 4MHz SysSystem clock without any PLL. And additionally, within middleware, I have enabled a three-year-ties inversion using CMC's version 2. From this, what I need to do now, I need to enable functions which allow me to modify the priorities. Those are VTASC priority set. This is the name of the function within three-year-ties API. It is enabled, so it will be included into the three-year-ties code. And UX task priority get function, which allows us to check what is the priority level of the task. It is enabled again, so we can continue with our coding. So let's have a look on the tasks and queues. In my example, I got already two tasks, task 1 and task 2. Task 1 has higher priority, and then task 2. The difference is 2 between those two. What I will do now, I will just increase the stack size just to be in line with our slides. So I double-click on task 1 and I change 128 to 256 words. I keep the entry function start task 1, and the same I will do with task 2, so 256. And yes, one moment, 256. Okay, we've got two tasks. In case you need to create one, you can use this add button, and then in this case you can add a new task. So this is our target set of tasks. We do not need any other components, so this is the time to generate the project. For this, I would use this device configuration tool generator. So I just click on it and it will take some time. And we can analyze briefly main.c file within our project. Coming below, we can see both. This is our main.c file. Below, within the private variables section, I can see both tasks definitions. So task 1 has OS priority normal 2, and the task 2 OS priority normal. We can briefly have a look what is the numeric number. So OS priority normal 2 is 26, while priority normal is 24. The stack size given in words is 256 in both cases, so in bytes it will be one kilobyte. Then we've got two, let's say the main function, and within this, we've got the hardware initialization, and then below there is a creation of both tasks. Then after, we are starting the scheduler. And then after this, we are just executing code from both tasks. Task 1 and task 2. If we go below within our tasks function bodies, we need to modify the code. What we would like to do is to increase the priority of task 2 within function body of task 1. It will be increased by one within each iteration. And within task 2, which has lower priority at the beginning, we will decrease the priority by 2. So we will start with task 1, which has let's say higher priority. So at the beginning, we need to declare the OS pure priority underscore t value, which would hold the priority level of our task 2. So the first thing is to priority equal os thread get priority control space. Yes, and task to handle. Yeah. Then the second operation would be sign of life of our task 1. So we will use task action with one as an argument. Just to let you know, in our example, we are using this task action, the simple function without any return value, which is sending via itm instrumentation trace macrosol tools to characters. The first one is message we just passed. So in our case, it would be one. And then the sign of new line. So we should receive line by line messages from both tasks. So this is our sign of life. And then we will modify the priority of our task 2. So OS threat set priorities control space set priority again, handler to and the priority will use this variable and will increase it by one. And the end, we will keep our task busy using how delay not always delay due to the fact that if we use how delay for one second, it would mean that we will keep our task busy for one second being in a run state. It is a task with higher priority. So it will be always selected by the scheduler till the moment the task 2 will have the equal priority than than ours. If we would use OS delay instead, we would send our task to blocked state. And in this case, task 2 will be executed will would be selected by the scheduler for execution. And it will be quite hard for us to check when we've got the situation when both tasks had have the same priority. This is why we selected here how delay, which is not the best practice in a coding. To be honest, there is one missing point here as well. It is a return value of this function just to be sure whether the function has been executed correctly or not. This function is returning OS status underscore T value, which inform us whether execution was correct or not. Any negative value, which is returning by this function means that it was not successful. And we should have a look what is the reason. In this case, we will simplify it. We will try to focus on it, let's say further exercises, but it is good to remember. Let's continue with task 2 execution. So here we will, in fact, we will modify as well the priority of this particular task, so task 2. So we need again this OS priority underscore T value as well. It is local one, so we can name it the same way. And then within the function body, before we will, let's say, send something over SWO, we will read our priority. So priority equal to OS thread. Get priority, control space. It's a very nice feature. And here we've got two. In fact, we can select one of two handlers, handler to task 1 or task 2. If you would use similar function within 3R2S API, it would be enough to use here null value. And for those of you who are used to, let's say use null argument within, let's say, functions once you are operating on the task directly, there is a bad surprise, bad news. Within CMC's OS, null argument is not valid anymore. So once you would use null here instead of the direct handler name, you would land into, you would, let's say, receive the negative value out of this, so OS argument error. Let's try to open it. This function is within CMC's OS functionality. So let's have a look. CMC's OS.c file. And please have a look. Once the handler is null, we are coming back from this function with OS priority error, which is minus one. So we need to specify really the handler. This is why I would use the handler over here. And it will be stored within this priority variable. Then I would give the sign of life. And after this, I would modify the priority. So OS thread set the priority, priority set handler to and priority. In this case, we would decrease it by two. And after this, we will not use any delay because it makes no sense. Okay, that's all for the code modification. Let's compile it. Okay, there are no errors, no warnings, so we can start a debug session. Okay, let's continue with a debug session. So I click on this back icon. My board is already connected. Okay, before I will start that application, I will open the SWV ITM data console. In case you are starting with us at this moment, you can find this console using this search. So SWV, this is this one, SWV ITM data console. Once it is selected, you should see below on the screen to configure it, press this button, select port zero, and then just start tracing. After this, you can run an application. So I started and I can see it is working as expected. I would pause for a moment and I try to comment it. So please have a look. Task one, as I said, had higher priority than task two, is executing and within its function body, it is increasing the priority of task two by one. So we can see two executions of task one, and then there is a situation where both tasks have the same priority. So task two is executing once. It is decreasing its own priority by two. So again, it is giving the space for task one only. So we can see two executions of task one, which increases the priority of task two again to the same level, and then task two can execute once. And the situation repeats. So it is according to our expectations. I'm terminating the debug session and we can continue with next parts. Thank you for your attention.