 Hello, in this part I would like to demonstrate binary semaphors used with freeRTOS system and CMC OS layer in version 2. We'll start from stm32-cube IDE, you can use as well Cubemix. So I will start a new project from file new stm32-project. My target micro is stm32-l476RG, which is located on our board Nucleo-l476RG. So I would put part of the name here and there is my selection. Name of my project would be 5 underscore is sem underscore bin and I press finish. With this exercise we would need two tasks and we will use one external interrupt, which will use the blue button which is connected to PIN PC-13. So first thing we need to do is to configure the PC-13 as external interrupt. We can put label on this pin as well, click on the right button on mouse and we can put here for example blue button. An assignment label to the PIN is done within main.hfile with the generated code. Next step is selection of debug interface, so I go to system core and sys group. Within sys group I'm selecting within debug trace asynchronous SW, just to have complete swd, those two lines and single wire output which is used for the trace single wire trace. Then within this same group I will change timebase source from sys-tick into for example timer6, just to do not have any conflicts between hull library which is using the timebase then by default it is sys-tick and freeRTS which is using sys-tick as well. So we will keep sys-tick for freeRTS and as a timebase for the hull library we will use timer6. So this is second selection, the third selection is freeRTS configuration, so we will start from middleware, freeRTS, interface, cmcs underscore v2 and within this we need to configure two tasks. So I go to tasks and queues, I would rename this default task by double click on its name and I would change it to task1, priority normal I would keep the same 256 words as a stack size and the start task1 as entry function, then coming back to tasks and queues I would add one more task, so the second task would be named task2. The same priority, normal 256 words and start task2 as entry function name, that's it. So we've got two tasks and now we need to create one semaphore. For this I would go to the next tab which is timers and semaphores and within binary semaphores I would click on it, I would keep the default name, my binary sem01 and that's it. So we've got the binary semaphore. The last thing we need to check is to check whether our external interrupt 13 which is supporting our blue button is already enabled, so for this I can go either to system view or I can go within system core and week configuration and within this I can see xt line 15 to 10, 10 to 15 in fact are gathered together and it's not enabled so I enable it and then there is an important point in front of us, in the current version of cube IDE there is no automatic preemption priority assignment into the interrupts and we need to correct it, we need to say fine tune it. We would like to use this interrupt to handle, to execute the operating system functions. In this case it is important that none of those functions would be executed once we are in a critical section in the operating system. The critical sections in freeR2s are used very often, always if you perform any operation on the tasks, its priorities, semaphore skews or other OS components. So it is important that during let's say the phase of critical section none of other operating system functions should be executed. So to do this we are specifying some let's say borders within our priorities of the interrupts and we can select some of the interrupts which would execute let's say operating system functions and the rest will not. This boundary is specified within freeR2s configuration, this is why I'm coming back to freeR2s and within config parameters tab I scroll down and I'm looking for this library max syscall interrupt priority. This is specified to 5, it means that all the priorities from 5 till 15 can execute operating system functions without any issues. All interrupts from 0 to 4, so with higher priority than 5 should not do it because it might cause the system crash. This is why the priority, preemption priority of our external interrupt should be numerically higher or the same than 5. So I come back to config and I specify my preemption priority for this interrupt to level 5. And this was the last step within this configurator so I can generate the code. Okay, code is generated, I can open main.cfile, if not displayed automatically I can go to core, source and double click on this main.cfile. Now we'll perform some operations on the code. Let's continue with code modifications. So we are within the main.cfile, if I would scroll down I can see the definition of my objects of the operating system, so both tasks, priority normal, the stack size 256 words, this is why I multiplied by 4, and I can see the definition of my semaphore. So within the definition of the semaphore there is only a name. There are more fields within the attributes of this component and those are for example the pointer to the semaphore control block. This field is assigned during the creation of the semaphore which is a bit below after the initialization of the kernel. So we can see here the semaphore creation. What is important is that we can specify within this function what would be the initial state of the semaphore. Please have a look that we've got three arguments here. Let me display the function. It's enough to click on it and wait a bit. You can see more information afterwards. So please have a look that the first argument is a max count, so the maximum number of available tokens. This function is common to binary and counting semaphores. So in the next exercise where we will use the counting semaphores we will have a different number here. For binary semaphores we need one. Then the next argument, the second one is very important one because this is the initial count. So the initial number of available tokens. If you would like to have the semaphore already available upon its creation we can keep one at the beginning. But usually it is not the case. Usually we would like to start an application with semaphores not let's say available and would like to make them available after. This is why I would change it to zero. The third argument is let's say the address of the structure which contains the attributes. In this case from our side we specified only the name of the semaphore but as I told you within this structure we have a bit more information especially the pointers to the memory where the semaphore data are kept. After this we can see the creation of both tasks and start of the kernel. Now it is time for our coding. Let me start with the universal function which we are using to make so called sign of life of our components. So I would first implement the task action function. It is returning nothing task underscore action and it is accepting one component which is char and then it is sending this char over idm interface and then I'm sending the sign of new line just to keep everything in separate lines. So this is it then I need to put it into the private function definitions prototypes over here before main and we can come back to our tasks. Okay we will start with the implementation of our tasks. So the first would be task1 function body. By default there is only the delay of one millisecond, always delay means that we will send the task to blocked state. So we will replace it into let's say a bit longer delay let me say two thousand milliseconds so two seconds. And we will let's say send some sign of life task action one and after we will try to release the semaphore. Task1 will release the semaphore and task2 will wait for it. And please notice one important point. Once we release the semaphore we do not specify any timeout. So we try to release it. If it's not possible the function will return let's say the error value the negative value and we continue execution. It is different than we have observed within for example queues where we specified the timeout in both cases while we put some data to the queue or we are waiting for data from the queue. This is the important difference. Okay so we would like let's say to give the semaphore once per two seconds. Then within our second task we would like to get this semaphore semaphore and now there is a not get but acquire semaphore this is this semaphore I'm sorry I made a mistake here here is the handler. And the timeout. In this case once we are waiting for the semaphore we can specify the timeout so if we get the semaphore within this timeout or it will pass with negative value as a return value if we will not be successful within these four seconds. It would be better if we monitor the return value but for this simple exercise and quite deterministic timing I'm pretty sure that it will be enough time to get the semaphore. As you can see that even if we do not do anything semaphore would be released twice during the timeout of task two action. Okay so after this we will just pass the sign of life again so this is task number two I would use two. There is now OS delay our OS delay is in fact this acquiring of the semaphore. Next point which we would like to add here is a second source of releasing the semaphore because the semaphore can be released as well from the interrupt. As we have enabled interrupt from our blue button which is connected to PIN PC-13 we can use this opportunity to release the semaphore from this interrupt callback as well. How to specify the callback if we go to the interrupt file which is in our case stn32l4xx underscore it.c file and we scroll down to the interrupt of external interrupts I can go to the definition of this of this function and I can see that there is a callback which is called after flag clearance so as it is defined as weak I can copy the definition and I can reuse exactly the same function on my site so I come back to my main.c file and after my task action I will define the same function and then the callback and within the callback I will send say my sign of life in this case I will send an exclamation mark and I would release the semaphore. After this we can compile the code and check whether it is working as expected so I'm compiling the code okay now there's no warnings okay so we can start at the bug sessions click this bug icon my board is already connected let's check whether a single wire viewer is enabled if not I need to specify 4 megahertz as it is our system clock and I press okay then I need to enable SWV ITM data console if you do not have this tab please use this quick access and put here SWV and select this monitor icon okay as I've got it I will not do it with you then the configuration we need to use this configure trace button and enable channel 0 let's say ITM stimulus port 0 which is SWO done and start let's say the tracing with this icon after this we can start an application so I resume it and I can see you remember there is a quite long delay two seconds for task 1 I can see task 1 task 2 one by one if I press the button you can see exclamation mark as well I can pause it and please have a look at the beginning I was not let's say pressing the button so task 2 was the task whose way which was waiting in fact for the semaphore let me come back to the code so it is waiting for the semaphore so we can see as a first executed task 1 because task 2 was blocked on this line so task 1 was the first one and let's say the first occurrence was visible after two seconds so then there was a sign of life from task 1 a releasing of the semaphore and after task 2 was unable to reach this value and gave its own task as a sign of life and it was coming one by one as you can see till the moment I press the button if I press the button the semaphore has been given so this is pressing of the button semaphore was released and it allows task 2 to be executed immediately this is why we can see just after let's say the task 2 execution and then again it was a task 1 task 2 and again it was an interrupt so just after was let's say task 2 executed as it is waiting all the time in fact it is waiting all the time for the data it is blocked only by this function so if we would provide to this task the semaphore frequently we can see for example only exclamation mark and 2 as you can see in this in this sequence to exclamation mark to exclamation mark to as you can see because task 1 was blocked by this always delay so it was not operational for two seconds that's all for this video thank you for watching it