 Hello, in this part we will focus on counting semaphores in practice. Let's do some practice. In our example we will use the following scenario. There are three tasks, task 1, task 2 and task 3, all of them have the same priority, for example OS Priority Normal. Additionally, there is one counting semaphore with its maxCount value set to 2. Task 1 and task 2 will release the semaphore while task 3 will wait for two tokens. At the beginning there are no three tokens in the semaphore, so task 3 is blocked. Context is switched to task 1, which is releasing one token of the semaphore, then task 2 during its time slot is releasing second token. It causes unblocking of task 3 till next iteration of its function where it will wait again for two tokens of the counting semaphore. In case task 3 would have higher priority than task 1 and task 2, the situation would look a bit different. As after release of a first token there would be a context switch from task 1 to task 3 as a first token has been unblocked and then task 3 will be moved again into blocked state waiting for the next token. After this, either task 1 would continue its job or there would be a context switch to task 2. Please notice that there is no single function to which is waiting for more than one semaphore. We should execute twice the wait function one by one waiting for one token of the semaphore each. Now we will try to check it in practice. We can reuse previous exercise to save some time. With an stm32cubemix or stm32cubedie, please select 3R2S in version CMCOS version 2. With any config parameters, please enable use config semaphores. In within tasks and qstab, please create 3 tasks. Task 1 with start task 1 entry function, task 2 with start task 2 entry function and task 3 with start task 3 function. All of those tasks should have the same priority, for example OSPriorityNormal and the same stack size like 256. We will need an external interrupt in our example. So we need to configure PC13 as GPIO XT13 within pinout configuration. Assuming that our blue button on Nucleo board is connected to PC13 pin. We can specify the label on this pin, but it is not necessary. Then within NVIC configuration, we need to enable XT line 15 to 10 interrupts and select it within column uses 3R2S functions. In this case, we would be able to release semaphore from external interrupt callback. In the next step, we'll create a counting semaphore. Within 3R test configuration, please select timers and semaphores tab and click on add button in counting semaphore section. Set semaphore name to, for example, mycountingsem01 and set its count to 2. Then click on OK button. After this, a new counting semaphore should be visible within counting semaphore list. Now we can generate the code and open main.cfile. Within main.cfile, we can notice how counting semaphore is created within create the semaphore section just after hardware initialization in main function. We need to place some code within all tasks entry functions bodies. Within start task1 function in its infinite loop, please release our counting semaphore using ossemaphore release function, then send one over swo using task action function and at the end, move the task to block state for two seconds using osdelay function. Then similar operations we should do in start task2 function with the only difference that this time we will send two over swo using task underscore action function. Please notice that there is no timeout within semaphore release functions. So in case of semaphore is already released or contains maximum number of tokens, function will not wait but just will return an error code. This is why in more complex examples, it is important to check the return values of those functions. In our simple example, there is no risk that semaphore will be full. This is why we have used simplified version. In task3 function body, we need to put two ossemaphore acquire functions one by one. There is no single function waiting for few instances of the same semaphore. In case you would like to synchronize a task with more than one component, other task or interrupt, it is better to use other techniques like thread flags or event flags. Please have a look at dedicated parts of this session for more details. Coming back to our example. After code modifications of task start task3 function, we can compile the code, start the debug session, open SWV ITM console and start the application. The result should be the following. Task3 synchronized, then task1 release counting semaphore, then task2 release the counting semaphore, again task3 synchronized because there are two tokens within our counting semaphore available, and just after it task3 is again in wait state waiting for two instances of our counting semaphore, so we need to wait till task1 release again the counting semaphore, and task2 will release again the counting semaphore. And it is continuing in the loop like this. Now we can extend our example by releasing the semaphore from the external interrupt callback. For this we need a one external interrupt connected to PC13 pin on a nuclear board where our blue button is connected. With an external interrupt callback HAL GPIO XT callback, which is defined as weak within HAL GPIO module, we need to send an exclamation mark over SWO interface using task underscore action function and release our semaphore. After this please again compile the code, start the debug session, open SWV ITM console and start an application. The final result should be similar to this one on the slide. Let's focus on selected area. What is happening there? Task1 and task2 have released semaphores, then task3 took it two times like requested. In the meantime there were two occurrences of external interrupt, two times fast press of blue button, what gave two times semaphore which is unblocking task3 again. Thank you for watching this video.