 Hello, in this video, we'll have a look at some typical mistakes which might happen during operating system-based embedded application development. Let's start with the most common possible issue. What would happen if we will use the same timer, it is by default cystic, for HAL library, time-based management, and for free R2S. In free R2S it is used to generate the time slices. If we are generating the code using stn32cubemix or stn32cubede, only receive a warning message prior code generation, but we can still generate the code with those settings. Possible issue during runtime could be improper timing management within the system where we will use HAL library functions. Please remember that within free R2S, cystic and pentasv interrupts are configured within lowest possible priority, so all operating system functions will freeze those interrupts every time will be in a critical section. In such a case, all planned delays timeouts within HAL-based code will be negatively affected, so delayed. Solution for this is selection of different time-based timer which would be used for HAL libraries. It can be done within sys, peripheral group, in stn32cubemix or stn32cubede. The best choice is either timer6 or timer7, as those two do not have any input nor output channels. Once we did it, after congeneration we can observe a new file in case of stn32l4 it would be stn32l4xx underscore harl underscore timebase underscore tim dot c file which would contain harl time-based timer functions implementation like HAL init tick to insuline selected timer to 1 millisecond time-based timer, HAL suspend tick to stop interrupt generation by time-based timer and HAL resume tick to start interrupt generation by time-based timer. Additionally, within stn32l4xx underscore it interrupt file there would be a new interrupt vector implementation of selected timer which would be used to generate our time-based for HAL libraries. Next possible problem we may face is once we call the operating system function from interrupt routine. In case we observe no effect of this function execution we should check its return value. If it is OS error ISR, so this is minus 6, it means that function mustn't be called from interrupt but only from the task code. As an action it is necessary to call the function from any task code or change the function which should be called from the interrupt. Another option is to use interrupt to trigger any task to perform this action instead of the interrupt directly. Another possible problem is related to not properly configured interrupt priorities. Please remember about the split with an interrupt vector into three groups once we are using operating system. The first group is completely independent from the operating system. Those interrupts have higher priority than configmax syscall interrupt priorities stored within 3.0.sconfig.h file and those interrupts are completely not affected by the critical sections used within operating system. The next group which is specified is the group which is below configmax syscall interrupt priority group and those interrupts are dedicated to fully cooperate with the operating system by calling its functions. And this is why those interrupts will be blocked by operating system critical sections. And within our coding we should call operating system functions only from those interrupts from interrupts from this group. The third group is collecting the interrupts related to scheduler tools. We've got here two of them, it's cystic and pentSV. Those interrupts have lowest possible priority to not block other hardware resources of the embedded system. The most common mistake is using interrupt from the first group to call operating system functions. In such a case once we would perform any modification within operating system, so for example changing the task state, its priority, switching the context, etc. And interrupt with higher priority will come, it will change operating system settings which may result in system crash at the end as interrupts from the first group are not blocked by the operating system critical sections. It is up to the user to monitor a proper level of interrupts which interacts, so calling operating system functions. There is a warning mechanism within freeR2S as well, it is enabled by default. It is enabled by setting config assert within freeR2S config.h file once and once interrupt with higher priority then maxSyscall and will be called, will call operating system function will land within vPortValidate interrupt priority function where we can implement a corrective action. What could be the root cause of the situation when the task is never selected by the scheduler? There are a few possible scenarios, task can be in blocked state waiting for other operating system component like queue, semaphore, flag threads or event threads which are either not released or are taken by other task first. It may happen that expected operating system component should be given from interrupt which is either not enabled or blocked. Solution here would be a correction of interrupt priority level or in other action to unblock requested operating system component. Another scenario is that higher priority task is constantly in run mode. In this case, if it was intended to send this task to the blocked state please verify whether OS thread yield has not been selected instead of OS delay. Please remember that yield operation is sending task from run to ready state not to blocked state but to ready state. In such a case higher priority task will be selected immediately for execution and lower priority tasks will not be in run mode. Solution here would be a replacement of yield function to, for example, OS delay one. The first scenario is that you can use cooperative configuration of our operating system. We can check it within free RTS config.h file in case use preemption option is clear to disabled it is our case. In such case an active task will perform its operation still it will decide to finish the job by calling yield or OS delay. So we can observe the situation that other tasks are completely blocked by this. Last scenario I would like to mention here is improper task priority. As we are using CMC OS version 2 layer over free RTS OS it may happen that in some areas of the code we will use numerical value of the priority once in other places we will use OS priority underscore t type def. Please notice that once you are using stm32cube IDE or stm32cubemix you have set a 56 priority levels which is not configurable it can be changed manually in free RTS config.h file within config max priority field. Please note as well that there is a numerical gap between OS priority idle coded as 1 and next one OS priority low coded as 8. If we select something in between and within the code we will use other components from this type def OS priority underscore t we may face an issue with correct task execution or it's completely blocked from the run state. You can find more information about OS priority underscore t type within CMC's underscore OS section of this training. Sometimes we can face the situation when the task which is waiting for the semaphore is unblocked immediately even semaphore has been not given yet. There are some possible root causes of such a situation. The first of them is when there is a too small timeout specified in the function and lack of monitoring of the returned value. Please remember that semaphore and queue wait acquire function can wait for the component so semaphore or queue for a specified time it is a last argument in a function and then after these those functions return a negative value it is OS status underscore t type and task continues its execution even the requested object has not been received. So this is important to check the return value of the functions which are waiting for semaphore or queue and in case we didn't receive them a perform a different action. Another option here would be an increase of a timeout would like to wait for other OS component. Let's consider the second scenario so nonzero initial number of tokens during semaphore creation in such a case it is important to check how the semaphore has been created. Please remember that within OS semaphore new function we have three arguments. The first one is maximum number of tokens in case of binary semaphores it is one then it is initial number of tokens in case there is nonzero value here it means that semaphore will be available directly after its creation sometimes it is let's say desired state and the third argument is an address of attributes structure of the semaphore. Critical point is this initial number of tokens in case we don't want to have a semaphore available just after its creation we should keep this value at zero and in case we are using the code generators which are setting it to one we should change it manually within the generated code. There is one potential trap within software timers configuration which might cause issues with software timers callback execution. The root cause of such situation could be wrong priority assigned to software timer task. By default it is set to two it is third within 3R2S config.h file and it is configurable within stm32cubemix and stm32cubede within 3R2S configuration. Please have a look that it is set to two while there is a gap between one and eight within os priority underscore t type depth specified within cmcs underscore os version two. This is why it is important to change these default settings default two into other value which is inline with other tasks priorities. Otherwise software timer callback will be not executed as expected or not executed at all and where we can modify it we should modify it within 3R2S config.h file within filled timer underscore task underscore priority field or we can do it the same within 3R2S configuration using stm32cubemix and or stm32cubede. Another possible issue is related to two small stack assigned to the task. What are the possible effects? Also before code generation so within stm32cubemix or stm32cubede we will receive a warning that we need to change the size of the operating system heap so total heap size within 3R2S config.h file or within 3R2S config parameters. Once we will have a problem within our code so for example after local variables declaration within an entry function of the task we will land in a hard fault interrupt. Solution here is to increase the stack size defined within task creation function. Please remember that the stack size for task is defined in words. Let's assume the situation that the operating system heap size is too small within our application. It is easy if we specify all operating system components at the beginning during project creation. Then in case of operating system heap when it is too small stm32cubemix or stm32cubede it will generate a warning so that 3R2S heap size stop within 3R2S configuration and it will display the requested size of the heap versus a specified one. So we can correct it quite easily. It is a bit more complex, more difficult to detect such a situation if it will happen during the runtime of the application. And it could happen in case we are creating some operating system components from our code. This would trigger an additional memory allocation which has not been considered at project creation phase. In such a case it is good to monitor return values of all of the functions which are creating new operating system objects. In case the value is this return value zero it means that the object has not been created due to lack of the memory. In both of the cases the solution is to increase total underscore heap underscore space within 3R2S configuration. So it can be config parameter stop within stm32cubemix or stm32cubede application or manually within 3R2S config.h file. Thank you for watching this video.