 Hello, in this part I would like to work with queues, so it will be the basic example how to create a simple queue with a single receiver and a single sender. We will start from stm32 cube IDE, so I've got some ready workspace in front of me, I will start a new project, so I go to file new stm32 project. Just to remind you, in this training we are working with stm32 l476rg microcontroller which is soldered on Nucleo l476rg board. So I selected this one, click next, my project name would be to underscore queues underscore basic, then I would click just finish. Okay, finally we've got pinout of our microcontroller. Just to save the time you can reuse any of exercises from the front section. What we will do within this one, what we will need. First, within system core and sys, I would select debug as trace as a chronos sw, just to have swd plus single wire output, which is used to communicate some simple commands from tasks and interrupts within our code. Then I need to change the time-based source used by Harlibrary from default SysTik to, for example, timer six. It is due to the fact that SysTik is used already by the operating system. Then within this we will do not need any other hardware resources, we keep the clock configuration on default settings, so MSI for megahertz without any PLL. So we can go to middle worse and here we select freer toys and within this we select interface, so API inversion two, so CMS is V2 and within its configuration we'll keep at the moment default settings and the default includes and let's go to tasks and queues. There is already some default task defined over here, so I would rename it to our new task which would be sender one. I can do it by double click on its name. Priority normal will keep the same stack size 256, just to be sure that it would be enough memory for our operations and then the entry function would be start sender one. Then okay and let's add one more task, so go again to tasks and queues, I click add and this time it would be receiver. Priority again normal stack size 256 and the name of the function start receiver. Okay, next point would be to create a queue, so I click on within this queue area on add. Let's change this default name into queue one, number of components within the queue we will define to 8, limited to 8 and item size we will use 8 bit values without sign, so unsigned in 8. So in our queue we are planning to have maximum 8 components of 8 bit each. I create okay so now I can see two tasks and one queue as operating system components, so that's it for the configuration of our system. I can generate the code using for example this device configuration tool button, so it will take some time. We should be expecting to change the perspective to cc++, if not I can just manually switch to main.cfile. Within main.cfile I can see within the private variables part initialization, the declaration of OS components, so both tasks sender1 and receiver and queue. As you can see there is as well the definition of attributes of each component and within those attributes usually we are defining only the names within tasks as well priority and stack size. The rest of the attributes also the pointers to the memory structures are generated and filled automatically during the creation of those components. If we go below within main function we can see the hardware initialization of the complete system, so how it needs system clock config, our peripherals, so where we need we used on the GPIOs. Then there is initialization of kernel, so usually it is the hip initialization especially in hip4 and hip5 models. After this there is a creation of OS components which we define to the MEX part, so we create a queue and then both tasks. Then there is a kernel start and while one loop where we should never let's say reach this line. Let's go to our task entry functions, so our first function is a code for the sender, so it is called start sender1. Within this function we will add some local variable, so it will be 8 bit x initialized to 0 and then within let's say the endless loop we will first send some sign of life using some universal function, it is called task action. You can define within any action, so we can send data over UR, send data over ITM interface. In this particular example as in others within this training we will use ITM data send, as within STM32 cube IDE it is possible to put single wire output on data console, it is quite efficient way to have some additional debug interface. And as you remember within tube MEX part we have selected as well as SWO as an active pin within our debug interface. Okay we'll come back to this task action a bit later on. Let's focus now on let's say the implementation of our sender task code. So sign of life it is the first one, first line, the second line it will be sending some data into the queue, so as message control space put, then we've got only one queue, so I select this one, then there is a message pointer, so in our case it will be this x variable, its address, then priority. We are not using this so I put 0 and the timeout, so how much time I would like to try to send data over into the queue I would put 200 milliseconds. After this I would increase my variable just to be sure that the code is executed properly, so it should send the data from 0 to 9 and then from 0 again. After these those operations I would like to send my task, my sender task into blood state for one second. So it will be the implementation of sender and then let's implement our receiver task function body, so it is just below. So here we will define as well some local variable, it will be as well 8 bit without any sign and it will be some data taken from the queue. I would define it as 0 at the beginning, then I would start as well from sign of life, task action and it will be big R. After this I would try to get some data from the queue, last message and then again we've got queue handle and we need to define let's say our variable where we would like to store the data from the queue, then the priority we are not using this and the timeout so how long we'll wait for the data I would put 2 seconds. After this I will display what I just received, so it will be data plus 48. As I would send to the queue only digits from 0 to 9 I add this 48 to have the ASCII codes of the digits. We will not use any delay for this task, so it should try to get the data from the queue and of course in case of missing information in the queue it will be in a blocked state for maximum 2 seconds waiting for the data, so it would be the result. Now it is a time to define our task action function so I would use for this user code begin for, so this is only the skeleton and now we will fill the data inside. Okay, so let's come back to our task action just to be in line with our materials. I want to use exactly the same namings and moving our code would use 2 instructions, so it will be itm send char, so instrumentation trace macrosel send char, so single character, then I would send this one character and then just to start new message in newline I would use the sign of newline, that's it. Just to be compliant of C I put the declaration on top in the user code private function prototypes part and I will try to de-build the code using the hammer. My board is already connected, okay, so I start a debug session, I will just check whether everything is enabled, so I need serial wire viewer, my clock is 4 megahertz not 16, so I need to change it and I press apply and okay. I will reconnect my part. Okay, let's start our debug session, so I click on this back icon, okay, now I need to run my SWV itm data console. For those of you who started with this part already, you can find it within this quick access by SWV and then this data console is this itm data data console. Okay, we need to configure it first, so to enable this pin0 port0 as we are using single wire for the trace, before running the application I need to start tracing, so I press start trace and then I start my application. I can see something is coming, I will pause it, suspend the application, data execution and what I can see. I can see that the beginning was a receiver and then it was stopped because it was waiting for data from the queue. Then sender was selected by this scheduler, this is why I can see this big S over here and then sender sends this zero, the first character, first digit into the queue and it went to block state for one second. After this receiver has been selected by the scheduler, this is why I can see first zero and then receiver. It is due to the fact that if we come back to this, to our content we have a look on the receiver, so our receiver executed first this line, then it was blocked on this waiting for data and once sender sends this data to the queue, it has been unblocked and it was possible for this receiver to execute this line, this is why we can see as a third line this zero. After this, as we do not see any delay here, there is a second iteration of this loop, this is why we can see the SF4 element, the R receiver. Then receiver is waiting for next data in the queue, this is why it is in blocked state, so in the meantime scheduler is selecting the sender, so sender appears here, this is his, it's let's say sign of life and after this, again we can see first the digit, so this is one and then R, which is over here and story continues. So this is how it is behaving and now we will try to make this application a bit robust because we would like to be sure whether it was possible for us to get any data from the queue. Please have a look that within this function this OS message queue get, we are specifying the timeout given in milliseconds and this function can go, so it can pass with success of getting data from the queue, in this case we can see something within this variable RES, but it can return with error message, error message which can be for example timeout. So it would mean that it was not possible to get any data from the queue within this specified 2000 milliseconds timeout. And in our next step we will check what was the reason of passing into the line 266, so for the moment I would terminate the debug session and I would come back to code processing. Within this part we will have a closer look on this return value of OS message queue get, as I told you in the theoretical part it is OS status underscore T, very popular type within CMC's OS API and it is quite important to have a look on this return value especially if we are waiting for some OS components like queues, semaphores or mutexes. So in this case we will check whether this OS message queue get function returns correctly with a status zero, so OS okay, or it returns due to some issues for example with too short timeout, which is 2000 milliseconds in this case. So I would like to check this error state, this error state in our materials is defined within this local variable, but I would like to monitor this within my debugger, this is why it would be better to put it in as a global, so I go to this user code begin private variables part, this is my error state and it should be OS status underscore T type. Okay, so we've got this, I will build a code, start in debug session and I will try to add this error state to live variables. Here on the right side I can see the tab live expressions, I can add my error state over here, error underscore state and enter. At the moment we can see OS okay, OS okay means zero as you remember from our theoretical part, if I would use as well this SWV ITM data console I would start it and run, I can see this is still OS okay, so it seems it is working correctly. So let's do an experiment and within our experiment I would decrease this timeout to 200 milliseconds and rebuild the code, start in debug session okay, I would put this console live variables and let's start tracing and run application, oh you see it is executing from time to time as OS error timeout and we can we can see that receiver okay that what we can see on the screen, I pause it for a moment, you can see that we can see some the same values in the row, it is due to the fact that if we do not receive anything anything new within this REC value we'll have the same like previous iteration of this loop. So this is why we can see few times in a row, 9s, 8s etc. But what is important is this status as we observed we can see OS okay or OS timeout. OS timeout is a negative value which means that this timeout was too short to successfully get any data from the queue. This is why it is important to check really what is the return value of this function to be sure that we have something new from the queue or and we are not working on some let's say previous content. Okay the solution here could be as well to put OS wait forever and in this case we will wait for the data in the queue till we will have them. So it will be no other option to come back from this blocked state say from that the only only way to come back from this blocked state in this case would be to get any data in the queue. But in case we would like to use some timeouts it is good to check the return value of the of the function which is given by this OS message queue get. So this is that's all for this basic exercise concerning queues. In the next exercises we will focus on two topics the first one would be two senders and one receiver and next one would be how to handle more complex data using queues. So thank you for your attention.