 Manipulating on the priorities of the tasks. Okay, let's do some practice. So now we prepare the priority change lab. To do this, we need to include two components within 3R2S config. So vTaskPrioritySet and uxTaskPriorityGet to have the possibility of usage both functions to set and to get the priority of the task. And here is the illustration of the final effect we would like to achieve within our exercise. We will reuse the previously used exercise with two tasks, task one and task two. In our case, task one will have higher priority than task two. We will have as well the idle task with priority lowest possible, so the priority zero. And within the task one, we will increase the priority of task two. We will increase the priority of task two by one. And then within the task two function, we will decrease its own priority by two. So in fact, the situation should be the following. Task one should be executed as only one, then SysTick will not change the context because the task one will be the only one on the highest OS priority level two. So after first execution of task one, task two will have the increased priority just below the task one, but still below. So the second time slice task one would be still executed. And again, it will increase the priority of task two by one. So at the second time slice before the third time slice, so the second occurrence of SysTick, both tasks will have the same priority, so OS priority normal two. So the scheduler will select task two for the execution. And within this code execution, task two will decrease its own priority by two. So it will land to the level of OS priority normal, for example. And after this operation, scheduler will notice that priority level of this task is not enough to be, let's say, fully executed. So it will move this task to the ready state on the list with ready tasks. And it will switch the context to the task one, which has the highest priority, OS priority normal two. And task one will continue the execution. So it is, let's say, our target for the application. As I told you, let's use the previously done exercise will just do some slight modification and try to have this effect on our boards. Let's have a closer look on the function, which is used to get it the priority of the task. So within CMC's OS P2, we've got the function OS treat get priority, which is returning the value of the priority of the given task, which is an argument. This function is calling UX task priority get or UX task priority get from ISR, depending whether we are calling this get priority function from the task or from the interrupt. And this is, again, let me highlight it. This is one of the advantages of CMC's OS API. You don't need to select by yourself the proper function, whether it is function to be called from the task or from the interrupt. It is the recognition whether the, let's say, there is, we are in the task or we are in the interrupt is done automatically by the function itself. So this is one of the advantages of CMC's OS API. Okay, coming back to this task priority get function. So the FreeR2S API is performing the following list of operations. As the priority is one of the key components concerning the tasks and the operating system, the scheduler general, it is important to freeze all the operations of the FreeR2S for the time we read the information about the priority of the task. This is why at the beginning we are entering into the critical section to avoid any parallel operation on operating system or change of the priorities. For this we are using the macro task enter critical, in case we are executing it from the treat mode, so from the task, or port set interrupt mask from ISR, in case we are executing this code from the interrupt procedure. Then the second step is to read the priority value from task control block of the given task, for this the function prvget tcb from handle is used, and then we are extracting the priority value from this task control block structure. This is UX priority field. At the end we are exiting from the critical section, using task exit critical, or port clear interrupt mask from ISR, depending whether we are executing the code from the application, so from the task, or from the interrupt. Let's have a closer look on the function dedicated to set the priority for the given task. Within cmcsOS API v2 we've got a dedicated function called OS treat set priority, which is calling vtask priority set from FreeR2S API. This is not a not to say obligatory function within the FreeR2S, this is why we need to include vtask priority set within the configuration file of FreeR2S, before we use this function. vtask priority set is defined within tasks.cfile, you can see the body of this function there, and is performing the following list of operations. First we are entering into the critical section to avoid any parallel operations on the operating system, and for this we are using the APIs using the macro defunction task enter critical, and from this moment all the interrupts related to operating system, so the interrupts related to systhic, to pentSV, and all of the interrupts which are allowed to execute the operating system functions are stopped, are frozen, are masked, using base pre-register. So after this we can perform some operations on the priority of a given task. It is really important to have the rest of the operating system frozen at the moment, just to be sure that there is only one place where we are doing the modifications on the operating system, there would be no competition here. So once we are in this safe condition we can check whether the task should not be moved to the different task list due to the new priority. Because it may happen that once we increase the priority of the task, the task could be moved from one list to the other. It's rather opposite, it's rather the situation where for example our running task has the priority quite high, and then using this priority set we are decreasing the priority of the task, and after this operation it will happen that the task we are just modifying will land into the ready list but much below that the currently let's say executed level. So in this case a scheduler is really checking whether such a situation will take place and it is planning to switch the context in case of such a situation. At the end we are exiting the critical section using task exit critical to unfreeze all the interrupts related to the operating system and resume the operating system execution. So after this operation it might happen that our task which we modified the priority would be removed from the running state and the new task from the ready list would be selected by the scheduler. Let's start from STM32QBMX or the QBMX perspective with an STM32QPE IDE. We will use the previously generated code with two tasks task one and task two. We will do some slight modifications within those settings. So the first point is to increase the stack size of both tasks to 256 just to be sure that the new functionality we will just add would be handled within the stack size we just specified. And the second very important point is to enable two functions within the include parameters. So vtask priority get and ux task priority set. The enabling of those two components should be done within the include parameters tab of QBMX free RTS configuration. We will do only those two modifications and we will generate the code for Qube IDE or for the selected tool chain. One comment regarding the stack size. In case you will select two small stack size for the task the effect can be the following that you may face the hard fault handler within the code execution. It is a sign that something wrong happened within let's say the free RTS execution and most probably there is a problem with the memory allocation. So once you will land within the hard fault handler while you are running the free RTS application one of the first thing which needs to be checked is let's say the stack size for the tasks and for the other components. Of course it is much better to use some stack overflow protection for all of the components which we will discuss within the advanced topics but if you are not using those please check manually once you land in the some faults whether the memory allocation is correct and you've got let's say the correct settings for the memories for the tasks and for the other components. After the code generation let's open main.c file and let's modify start task one and start task two functions. Let's start from start task one. Within this function we need to modify to increase the priority of the second task by one. So in this case we will use the initialization part of this function. So as you can see on the screen it is user code begin5 and I would declare here the local variable it is os priority underscore t type called priority it will be used to store the priority of our task two. Then within the infinite loop I would read the current priority of a task two using its handle. So I would keep it in within the priority so priority equal to i street get priority and as an argument I would give that handle to task two. Then there would be a typical action for task one so task action with argument one and then I would modify the priority of task two using function i street set priority with two arguments the first one is a handle to the task I would like to modify and the second one is the priority level the new one which I would like to set so in this case I would just increase it by one so I use priority plus one. After this I just keep the time so I put half delay for one second. As start task on general task one has a higher priority than task two I could use it here as well os delay for one second the effect would be similar because os delay will send us to the red list and within the red list task one for the majority of the time is the only one which could be executed due to the high priority level. Let's keep it like this this is task one function body we are first reading the priority of task two then setting it increasing it by one and waiting for one second. We need to modify as well the function body for task two so the function start task two and here as well we need to specify the local variable of type os priority underscore t this local variable would be named priority as well and within the infinite loop I'm just reading the current priority of myself this is why the argument is task to handle. Okay so I'm reading the priority of the currently executed task in this case task two then I'm trying to perform the action so task action with argument two and at the end I'm decreasing the priority by two of task two as again so there are two arguments the first one is task to handle and priority minus two is the new level of the priority of this task. There is one more thing it would be very good to implement here as well to add here as well is to read the status or return value of this os treat set priority function to be sure that everything went okay and the function completed successfully you remember this os status underscore t value so to be sure that everything is going smoothly within the free artist based application it is always worth to check the status of executed functions especially those ones which are referring to quite important part of the operating system execution. Please have a look task one as it 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. Thank you for watching this video.