 Okay. So we need to add the library, we need to add the feature, we need to add the operating system, and which way? Well, simply Alt-O or go to Software Pack Select Components here on the top bar. Appopap will appear. You have here all of the SCXCube, so a list of the expansion package, for SCM32 Open Development Environment. Some of them will be in black, it means that you have on your PC. Some of them will be in gray, it means that you can add it, you can include it. We are going to use with the Azure AirTos H7, that you should be already installed, version 2.0.0, the latest update. You can see here all of the components that Paolo showed you on the first part of this session. You can see the file X, the level X, the USB X, the net text duo. All of them are built on top of the operating system, and the operating system is the first line, so the RTOS 3X. Four check button are available. In the second session, we will take a look at the other one. By now, we will only include the core feature, so only the operating system itself. So let's click on core, and then select OK. You will notice here, on the center part of the screen, here that a new line will appear, called software packs. Click on software packs, select the only available feature we included, the STM32XQ Bazzur RTOS H7. And after that, you can see that the center part will be refreshed with the feature related to these software packs just added. The only component is the RTOS 3X, because the software packs that component we added, but now we need to enable it. So let's click on RTOS 3X, and let's enable it. You will see that the bottom part of this table will be updated. And three tab will appear. The first tab is about the configuration of the RTOS itself, and mainly by now for the memory configuration. With the RTOS 3X, you can both work in a static way or in a dynamic way. The selection between static and dynamic memory is totally under your control. And this is totally depending on your strategy for your application. There are some cases where you prefer to work in a static way, other cases where you prefer to work in a dynamic way. This is mostly related to the amount of RAM that you have selected for your STM32. If static memory is selected, the all of the memory is added inside the task stack at compile time, let's say. On the other side, working in a dynamic way with a dynamic memory, the memory is reserved to say allocated and freed at runtime. And all of this RAM is not belonging to the task stack. It's outside the task stack, beginning at the first free location, obviously. Working this way, you need to apply some change, let's say change the RAM linker file. And you need to work starting again with the first free location. And you have a pointer inside the source code I will show you later, dealing with the first free location. Obviously you have advantages and disadvantages working with a static or dynamic way. The most important drawback working with the dynamic memory is the fragmentation. Because if you are going to allocate in free multiple times, several times during the lifetime of your project, you will probably reach a point where you will no more be able to allocate some RAM. This is called fragmentation. And this is a typical issue working with the dynamic RAM. For this morning session, for this demo, we are going to use the most simple one, so the static memory allocation, dealing with one K memory pool size. So static memory, one K inside. So there will be a big buffer, let's say, one K inside, inside the stack of the task. The second tab is about the TroDex. And this is simply a huge list of features that you can enable. Let's try to increase the size. Okay, you can here lead a list. Everything is disabled, everything. Except there is, okay, there is the disable preemption that is enabled. You will deal with it in the next session with Manuel, when he will show you what is a priority and what is a preemption. I only want here to focus on one configuration, one feature that is the ticks per second. Ticks per second equal to 100. It means that every second, you will get 100 interrupt from the system tick. It means that the time slice related to every task is 10 millisecond. This is important because after that, we will replace the all delay function with the OSSleep function. The all delay took millisecond. The OSSleep will take tick. So one tick is 10 millisecond. Is it possible to change the default one? 100, obviously. But let's say it's not recommended. I mean, having an higher number, it means you will have a shorter tick. And having a shorter tick, it means that you will have a faster, a more frequent, let's say, content switch from one task to another. And this is really not recommended. Also because the higher is the amount of value passed to the delay function, to the sleep function, to the timer function, and so on, the higher is the number, the less accurate will be the resulting, depending on the increased or decreased value of this tick. So let's stay with the default one with the 100. This is the minimum list of the feature to have a working operating system. You saw that we did not enable anything. Let's stay with the default one. Okay, the other one is empty. I mean, the user constant, you can define your own preferred macro if you want to add some define or whatever to the source code. Okay, let's go to generate the project. So all of the content of this tab, of this core 3DX configuration, will be reflected as it is inside the 3DX underscore user.h file, we will see now. To generate the project, simply save it using the floppy disk image, or type Ctrl K or click on the gear button here. You can see where I have the mouse. ApplePap will appear. You want to generate the code, click yes, obviously, and take a look what will happen on the left side where there's the project explorer. Ah, okay, yes, this is correct. You will get a warning. Do you want to generate the code? No, click no please. The warning told you that since you are now going to use an operating system and the operating system need a time base, the selected time base for the operating system is the system tick. But in the previous part of this training with the bare metal implementation, the system tick was used by the AL, by the hardware instruction layer, by the driver to create the delay. So we need now to select another time base for the HIL. So let's come back to the IOC file. Let's go to the system core part. So in category system core and click on sys. Sys system. The only available option here is the time base source. Let's move from the system tick, that's I repeat is the default one selected by the operating system, to a basic timer, to a timer with a low resolution because you don't need so much accuracy to perform this kind of a simple counter. Select timer six, for example. But you can select whatever timer you like. I selected the timer six because I repeat it's basic. If you want to take a look at the list of timer and take a look at which kind of timer it is, you can click on the timer section here on the left. And go with the mouse without pressing any button. Let's go with the mouse over one timer. And a pop-up will appear showing you that is a general purpose timer or is an advanced basic timer or is an advanced timer in case of timer one or a low power one in case of the LP timer five, four, etc. So let's use a basic one, so timer six. Now it's really the case to create the project to generate, take a look again what will happen here on the left side. So select press control S or control K. Do you want to generate the code? Yes, this is now the case. It will again take us a while because the operating system will be now included. Okay, on the left part, you have now another folder called Milderware. Inside the Milder, you will have the ST, there's the DEX and inside the common subfolder, you will have the list source. You will have the list of features of the operating system. Every feature is on a dedicated and ad hoc file.c. You will have task create, task delete, Qsend, Qrecyve, Mutec, Blockpool, et cetera. Another folder is the Azure Ertos. Here you will have the configuration of the Azure. Go outside, go below. You will see for example the stack that we allocated, the basic one that is 1K in size. If you remember when we discussed about the dynamic memory allocation, I told you that you need to pass to your allocation, to your allocator a pointer to the first free memory. And this is the pointer, memory pointer here. It's unused here, but this is the way it works. So let's say with the static one and let's go on. The most important in the end, the file that will go to replace the main.c is the app underscore tradix.c. Let's open it. You will have here all of the code related to your application. Let's come back for one second to the main.c file. You can see that the main did not change in your code because you put your code in between the begin and the while directive. But now there is on line 124 the startup of the operating system, the startup of the canner in the end. It means that everything after this instruction included the while one, the all delay and so on will never be executed. So this loop will never be reached. Since the thread, that function on the main.c we just saw will never, it's not re-entered. So it will never come back from this function. The main.c you can now ignore and put all of the, all of your code inside the app underscore tradix underscore init function. We saw below. It's important to say that generally speaking, talking about the operating system, potentially all of the function can succeed or fail. It's very important to pay attention to the return value. So after every call to your function to the operating system from the thread creation to the semaphore get put and so on, always be sure to check what is going to happen. So you can avoid potential issue. So always check the true false of the resulting of the function. So let's come back to the source code. Let's go to the app.tredex.c file. I will use again the cheat sheet to create to copy paste the source code. So the first line is the imat slide 37 for your information. First line there's define thread stack sites. Let's move it to line 36 between again, between end, between begin and end of private define user code. Second and third line of code at line 47 copy paste again. It's inside the private variables again between begin and end. Two lines here, the first one is the thread stack. And the second one is the thread sites, let's say, thread stack with the stack sites, 1K in sites. The second variable is the thread pointer because every components of the operating system from thread to semaphore queue, mute, et cetera, have an end layer. When you declare it, you will have a way to work with it to start, to stop, to change the priority, to send a message, to receive a message to take the mute and so on. You always will have an end layer, a pointer to the resource. Now, what we need? We need the prototype, basically the function that will be called by our task. And after the, inside the creation of the task we will pass a pointer to this function. So line 52, we have the thread entry with this initial input. So we need this parameter, even if we will not use it. I'm at slide 38. We need to create the task, obviously. So let's add the function threadex threadcreate to around line 70. So inside the app's threadex init between a begin and end of the threadex init, let's paste the threadcreation function. You will see first parameter is the end layer we declared before. The second parameter is the name. You can use any name you like. No restriction about the size, no rules about it. You can type whatever you want. Third parameter, third and fourth are related to the function that will be used for the thread itself. The function that will include the wild one, the wild true loop, and that will be executed by the scheduler, will be called by the scheduler every time there is a content switch. After that you have the memory. So the stack and this size of the task. Other parameters are the priority and the preemption priority of the task. The one parameter is the time slice. Time slice is how many tick a thread can stay in execution without be, let's say, preempted by the scheduler. It's not recommended using it with a value higher than one when you will work with an operating system. So if you are going to work with an operating system, with an operating system, just use the priority and the preemption priority. The time slice is used basically when you want to implement a round robin scheme. So all tasks have no priorities. All of them can stay in execution for the same amount of time, the time slice, in tick. So one time slice is 10 millisecond here. Using the round robin scheme, the scheduler select, simply select the task to be executed simply based on the arrival order inside the ready list. And the process will move on this way in a circular way. This is called the round robin. But again, here the indication is ignore the wine, ignore the one, ignore the time slice, use it with one parameter always and simply focus on the priority and the preemption. The last parameter is the auto start. It means that after the task creation at the beginning, the kernel will start with the execution of this task. The other option is to avoid the auto start and simply use the thread pointer to enable it. So to turn on this task at runtime, for example, calling the start from another task basically. The last step we need like the 39 is the function of the module to be executed. So let's copy the main trade entry function, the body and add it at the end of this task, of this file, again between the begin and the end. Let's copy. You can see here that you have the same behavior. So half GPIO toggle with the same pin and the sleep function. You will not going to use the millisecond here, but you are going to use the number of tick. So 20 tick, 10 millisecond each is 200 millisecond. So 400 millisecond period, 200 for the uptime and 200 for the downtime. Okay, we have done. You need simply also to add the inclusion of the main.h file to take advantage of the HIL library and of the macro led underscore green GPIO port and pin in place of PB zero. So let's go at the beginning at line 26 here inside the include section and include main.h file. Okay, we have done. Now we need simply to save and after that control B to build or the army. Again, this is the first time so the operating system file will be compiled and this will take a while. Okay, we have done. So again, let's go in the bug mode. So click on the, click on the bug and let's go to the bug, the led underscore toggle underscore led underscore toggle project. This allow the target, the estimator two H seven to be your erase and then the fleshed. Okay. Again, the code stuck at the beginning to allow the execution and see the lead toggling. Click on the resume button F eight. And you will see hopefully the lead toggling with that an higher rate, an higher speed. Compliment, you fleshed your first project based on the Microsoft Azure F toss. Finally, let's go to see what is going to happen at task labor. So let's stop the execution, clicking on the suspend button. Okay. And you will see that the code block inside the thread schedule dot S. This is an assembler file and this is basically the scheduler because we are, we have only one task and this task is mostly pretty always in a sleep mode. You can see here that the scheduler is simply in the, in the wait state. To take a look at it, let's go also to windows button show view, thread X, thread list. And you can see here that your task is in sleep. You will see later with Manuel the reason behind it. I can already tell you that your task is 20 tick. So 200 millisecond in sleep and only five micro second in run mode. So 90, 97%, 98% of the time is always in sleep. To see it run mode, there is only one way. So let's go to our code and add a breakpoint to the toggle pin function. So line 98, double click on the blue bar on the left where I have the mouse, double click and you will find that a small circle will appear. The small circle, it means that there is now a breakpoint and the execution will stop once the code reached this point. Let's click again on the resume button and the code will stop here. Now let's go back to that view, to that thread list. And you can see that now the thread is really running. So we were able to stop the point, to stop the execution within the five microsecond that the toggle pin, the LGPL toggle pin is executing. The very last point I want to highlight is about the stack usage. You will see here in this list that you have your name, you have your priority, you have the state, you have a run count. You have the indication about the stack start point and hand point with these sites and you have the step pointer. You will see here the stack usage that is disabled by default. To enable it and to take a look at what is going on, click on the three horizontal bar here on the toggle stack checking button, click it and you will see that the stack usage will appear. Stack usage 300 something upon stack size 1,000. It means that we are working in a static way. We reserved 1K, we are only using 300, so we are, let's say, wasting some memory. So 700 bytes we reserved are really not used. This is the reason why when you work in a static way you need to really pay attention to the amount of RAM you are giving to each task. To avoid this kind of situation when you take reserve a lot of RAM but in the end you are not using it really or on the opposite side you are reserving 1K RAM for example but your task will require more than this and you risk to reach a point where you will get some kind of a stack overflow, let's say. Okay, we have done. Hope you are linked with my execution. We can come back to where we left off and I got a question in the meantime if it would have been possible to come back to actually the section in which we are showing the two threads running and the thread list. So let's say that now we will restart the debug. I'm doing a step back. We restart the debug. Our thread is already initialized. I'm going in up thread.c. Normally if you enable the thread list, thread x thread list, you have to click here or if you don't have it already here you have to go on Windows, show view thread x thread x list and if you like this one we will pop up. So normally if you start the execution for a few seconds and you stop, you finish in the scheduler and the thread is shown as a slip. This is happening because the normal toggling operation so the lgbi toggle is actually going to take just a few microseconds. So you are not going to see it. You really have to stop in that microsecond which will be difficult. So to be able to see the thread running you shall put a break point at the line in this case for me it's line 98. So it should be at the same line of HAL GPO toggle pin. You can click behind on the left of the line. At this stage you can resume the execution so it's in a wild one. So we always finish there and when we click back to thread list you see that your hardware is there so it means that you are currently debugging this extraction. You are inside the thread body so the thread state now is running. Maybe you can write this in the chat if you got to the straight to the point because if so I can actually start with the step number two which will be activating the tracing features with Tracex.