 Hello, within this part we'll create a simple template for Nucleo L476 RGBort using STM32QP IDE. So I'm starting with STM32QP IDE, this is version 1.4.2. I've got a dedicated folder created for this purpose, so I would use this one. I start the project and we'll start a new STM32 project, so I'm starting from this button. And now we can select our microcontroller. I will select the microcontroller instead of the board just to have full visibility of the pins which we'll use. So I would start with a part selector, it's enough to put a part of the name. So in our case it will be L476RG. Okay, this is this one. I press next. And then the project name. I will try to use the same like in your materials, but it may differ, it doesn't matter in this case. So I would name it Nucleo L476RG underscore template. Okay, it's enough to put a finish. There is a warning that there is a different perspective. Perspective means the set of windows which are displayed within the application. We've got three types of them within STM32Cube IDE, so-called device configuration tool perspective, which is in fact the view of STM32Cube MX, which allows the configure peripherals of the microcontroller. Then there is a CC++ perspective, which allows us to modify the code. And there is a debug perspective, which is used during debug sessions. So I would just click yes, that I'm aware that it will be changed. And after a while we should see the pinout of our microcontroller we just selected. Okay, so this is our STM32L476RG. We can rotate it. You can see these two buttons. This is quite small package. It's 64 pins, so it's quite easy to find anything there. But in case you would like to find a particular pin, you can use the search field, which is quite convenient. We will use it to just demonstrate to find a pin where we have a green LED connected. So this is pin PA5. So I will just select PA5 and my pin is highlighted over here. I click on left button on mouse and select GPIO output, because you would like to use this pin as output as it is connected to green LED. I can put some label over this pin. So I click right button on mouse and I select enter use label and I would name it LED underscore green. Okay, those labels are stored later on within main.c files. So in case you change a hardware platform, you can still operate on the same labels just by changing, we'll see the header file. Next point I would add here is a button. It is connected on nuclear board to pin PC13. So again, I can search over here. This is this pin. I click on left button on mouse, select the last option. This is GPIO XT13, which means that we would like to use this pin as an external interrupt. And like before on PA5, we will assign a label to this pin. So I click on right button on mouse and I put it, put here blue button. Okay, so those are, let's see, two pins, our basic user interface. Next step, which we will do, it will be the selection of the debug pins just to be sure that those pins are selected and are not overwritten by other functions. So I go to system, core, sys and within debug, I select trace, asynchronous, serial wire. So this is, this will select three lines of the within debug interface, not only SWCLK and SWIO, but as well as SWO. This SWO is used for a single line trace, which is part of instrumentation trace macro cell within Cortex-M4. And we will use it to display some comments, some data from the microcontroller into one of the consoles within STM4.com by DE. Okay, so we selected the debug interface. The next point in this part would be selection of the time base source. Time base source is, in fact, the timer, which would be dedicated to the HAL library, so hardware abstraction layer library, which is responsible for all the timeouts and the delays which would be used within the code. So I cannot select here, I cannot select here the SysTik because SysTik would be used for 3R2S, so we need to change it to something else. We'll select the timer six, timer seven are the best candidates, as those do not have any input nor output channels. So it will be not a big loss for us. I will describe this necessity of selection of different timer than 3R, used by the 3R2S within next parts of this session, especially within the last one, one of the last one's troubleshooting and possible issues. Okay, so within this system and system peripherals we have selected all, next point which we need to do is to finish our configuration of GPIOs. So I go to the GPIO over here, I can make it bigger and I can see that PI5, its output, it's by default is low, which is good because we are controlling this LED by high level. And we need to configure this PC13, so our line where we've got connected the button. So by default it is configured as external interrupt mode with rising edge trigger detection. We can keep it like this without pull up nor pull down, it is okay for us because this pin has an external pull up and the button connected as well, so we can select as well following detection, which would be much more natural in this case, but we can keep it as well rising edge. You can see here that instead of interrupt modes we can see as well the event mode. Event mode, event from interrupt, the difference is that event is only waking up the device from low power mode without any code execution, which is assigned to the source of this event, while interrupt is waking up the device from low power mode and it is triggering an interrupt assigned to the source of this wake up wake up source. So in our case, we need really an interrupt just to use some to put some piece of code within this interrupt, which would be used later on. Okay, so I keep it like this. Another very important point is to enable this and configure this interrupt within our interrupt controller configuration. So this is NVIC section, we can go it from here or within NVIC button in system view. So by default, this interrupt is disabled, so I need to enable it and I can configure its preemption and sub priority. At the moment, it's both are zeros, so the highest possible ones, because we should remember that in Cortex is reverse meaning of the of the interrupt level. So the lower number we've got, the higher priority we will have. So at the moment, we keep it like this. Now we'll come back to this point after enabling the freer ties. Okay, so from the hardware point of view, all the peripherals in our template are ready. Now we are not configuring any clocking system, we will just keep the clock configuration in default setting like this. So it will be clocked from MSI, multi speed internal RC for megahertz without any PLL. So we will work on four megahertz, we will not touch this. Another point we need to do is to enable our freer ties. To do this, I go to middleware, I select freer ties. And from these freer ties, I can select one of two options. I can of course disable it, I can select CMC version one and CMC version two. Or when this training will use CMC version two, as it is much more rich in terms of the features of the possibilities, and it's much more closer to native freer ties API and its capabilities and its features. So I select CMC's V2. And after this, I can see that I can configure quite a lot within freer ties using, let's say, those those tabs config parameters and include parameters tabs are used to store the configuration of freer ties. Those settings will be stored later on within freer ties config.h file. Then the rest tasks and queues, timers, semaphores, mutexes, advanced settings and user constants, those are related to particular components of the operating system, which we will use a bit later on. Last tab I would like to mention here is this freer ties heap usage, which is very helpful in terms of estimation of the memory or root news, RAM memory or root news, we would need to work with our operating system. What it is doing, it is estimating the heap size of our operating system, which would be needed based on the components we just selected. Now by default, if we will not select anything, within this configuration, we've got a selection of one single task, it is called default task with stack size 128 words. This important is that stack size for the task is given in words. So if we go again to freer ties heap usage, we can see that total amount for tasks is 632 bytes. So it's a bit more than this 128 words. This is due to the fact that task is using in fact two memory areas. The third one is so-called stack, which is used to keep temporary variables used by the particular task during its execution. And the second one is so-called task control block, which contains the configuration settings and connection with other components which are used within the task. So during task creation, those two areas are automatically created as well allocated. And this is why we can see this bigger amount of memory usage. Okay, we will not do anything within this configuration, we'll keep all default settings. Then in our code processing, we will just play with this default task. In fact, putting some code into this started default task, function body. What I would like to focus on right now is to have a brief look on a configuration parameters in terms of interrupts. If we go to config parameters and with an interrupt nesting behavior configuration section, we can see two fields to defines the first one, library lowest interrupt priority. It is set to 15, which is the lowest possible priority within Cortex-M3 and 4M7 devices. And this interrupt level would be assigned to interrupts, which are used by the kernel to switch the context. Those interrupts are pentSV and Cystic. So those two components are fully described in the next part of this training, especially in a context switch. Next, define is library max syscall interrupt priority, which is set to five. So this is the maximum level of the priority of the interrupts, which could execute execute operating system functions. It is not definitely not good to call the interrupts that operating system functions within interrupts with higher priority than this. Higher means lower in numbers. So what we need to do now, we will change our external interrupt priority to some number from 5 to 15 in order to use this interrupt later on to call our operating system functions. I will describe this terminology more in details and terminology and all the risks which are connected to different configuration later on within next sections of this training. And I would summarize it as well with trouble shooting part, which is close to the end of this of this training. Okay, so let's come back to interrupt controller and reconfigure our external interrupt for different priority and level. To do this, I go to system view, I go to NVIC. And as you can see, once I selected this NVIC, I can see this warning. So that is what we just described. Let me make it bigger. This is our interrupt, external interrupt. So preemption priority, sub priority. We can see that in fact, free interrupts has been selected by FreeR2S. The third one is SWI instruction. So this is system service call. It is used only to start the interrupt, the operating system. Then it is not used anymore. Pandable request for system service. This interrupt is used really always to switch the context from one interrupt to the other and system timer assist is used to give the time slices for different tasks. Okay, this is our interrupt. It has preemption priority zero. So we will set it to something between five and 15. I would select five. So in this case, it will be very safe to execute any operating system function from this interrupt. This is due to the fact that with an operating system, most of the operations are done in so-called critical sections. Critical sections done with an operating system within FreeR2S are blocking the interrupts from this level five. So this max syscall, which we described a bit before. So from five to 15 in this particular configuration, all interrupts, so from four to zero, so higher priority interrupts, they will be not blocked by these those critical sections. So if we could call any operating system function from the interrupt, which has higher priority, it could cause system crash due to the unexpected change of its configuration. Okay, so at the moment, our external interrupt is configured properly, got configured everything, we can generate the project. So I go to project manager, there is nothing, nothing else to be filled here. I can generate the project by this gear icon. So device configuration tool code generation or from project and generate code. After next modifications, I can just press Ctrl S and the project will be updated automatically. So I generate the code. There is another warning that there would be a change of the perspective into cc++. So it would allow us to perform some code modifications. So I press okay, press yes. Okay, and after a while, we can see our new project. So by default, there is an open of main.c file. So main file, which contains most of the functions since it is let's say place of our code. On the left side, we can see the project explorer. So this is name of our project then with the main folder for us is this core, which contains the main sources which will work on woven includes we've got some header files of the configuration, the main ones are three years test config.h file, which contains the configuration of three years ties and main .h file, which contains, for example, the assignment of the labels which is used. Then within sources, the main file for us is of course main.c file. We will work as well in the next section, especially within advanced topics with these three years test.c file. The rest of them will not touch. We can just briefly have a look on them. Interesting is this one. So how underscore time base underscore time team dot c file, which contains the functions for a time base used for HAL library. So we will see inside the functions like hl underscore init tick and suspend tick and resume tick. Please have a look that everything is operating on timer six. Coming back to our explorer again. Within drivers, we will find the cmcs and stn32l for HAL library. Within middlewares, we will find three years ties sources. So when sources, we can see the native three years ties sources, which are zero team not used in our case, even groups, lists, queue, stream buffer, tasks and timers. So those are native for a three year ties and platform agnostic. Then to connect it to our hardware, we need some porting files. Those are stored within this portable location. And here we've got two folders, GCC and memory management. Within GCC and particular Cortex and for floating point unit, we've got two files ported dot c and port macro dot h. Those two functions contains implementation of cystic and pent SV and single and system call interrupt handlers, which are called on context switch and start of the operating system. Those are really the lowest possible level to switch the context within operating system. Part of this is written in assembly language. We can just briefly have a look. So please have a look this system call handler. It's written really in assembly language, like start first task, then cystic pent SV. So this is the switching the context. So you can see complete code how to switch the context. We will focus on this in the next parts, especially when booting and context switch section of this session. Within memory management sub folder within the explorer, we can find a file which is called hip underscore four dot c. This is one of the five possible, let's say hip files, let me say this way. This file contains the memory allocation and release functions which are used to allocate the memory for operating system components. So we can select one of five models. We'll describe this within part concerning memory allocation schemes. Those are let's say the files which we'll use within our project. If we come back to main dot c file, we can see here quite a lot user code components, user code, begin user code and those parts dedicated to the user to the embedded software engineer to locate private code. If we locate the code within those parts, we will be sure we can be sure that after code regeneration, so we will be our code would be would be protected. If we go a bit below, we can see that our one task is defined within the private variables. And it's called default task. It has its own handler. With this type, let's say the name, priority and stack size, please have a look that it's multiplication by four. This is due to the fact that we are defining the stack of the task in words. Then within main function, we've got the hardware configuration. So this is how you need the system clock config and peripheral initialization. If you're interested in more details, you can refer to on our other trainings, like stn32cube IDE basics or some sessions about stn32cube ID and HAL libraries. After this, we've got initialization of the kernel, which is in fact allocation of its heap memory. And after this, there is a part to create operating system components. So we are starting with, let's say, our only task. It's done by this function, OSTratNew. And after this, we are starting the scheduler. We should never land oven debug session below this line, 130 on this function. If we land here, it means that we've got some issues with kernel itself, most probably with, let's say, the heap area of the operating system. And it is really a critical point. We need to review the code and to make some corrections. Once we started, the code is really executed within particular tasks. And each task has its own function body, which is executed during its time. So in our case, we've got only two tasks. The one is start default task. And the second one is so-called idle task. Idle task is so-called default task, which is always present when the operating system is starting. And this task is executed if no other task is ready for execution. This idle task has some very important roles within operating system. And most important one is releasing the memory when we delete some operating system components. So it is cleaning the memory allocation after task. We'll do the job. We will not discuss it now in details. It will be discussed a bit later on. So let's put some code within this start default task just to see whether it is working. To do this, I just try to toggle LED. So using hull library, it will be hull underscore GPIO underscore. I can press control space and look for a function which I can use. There is a table pin. Looks good. And here I can see that I need two arguments, the port and the pin. As we are using labels, I would try with the label name. So it was LED. I can press again control space. And I can see there is something with the port. So this is my first argument. And for the second argument, I will do the same. So LED underscore control space. And I can see that green pin. Okay, so this function should toggle LED. And I need to slow the down somehow. And please have a look that this task is built with the endless loop inside. We can treat it as a mini while one loop main.cfile. So if I would not use any delay afterwards, it will be executed constantly. As if this is the only task active a part of idle, but I do not be run if the higher priority task which is this one would be present and active. So how to slow it down? I can use either hull delay like standard hull library code. But in this case, this task would be blocked will block, let's say the time of the operating system. It is not the best choice. It's better to use OS delay. OS delay is sending my start the default task to so called blocked state. And is giving the space to other tasks. In our case, it will be idle task. And after the specified delay, the task is coming back to ready state and can be selected once again by the scheduler for execution. So I would use it with 500. So it will be sent to blocked state for half a second. Once done it, I can try to build the code. So using this hammer. Okay, there was no errors, no warnings. And the next step would be to start debug session. So first I will connect my Nucleo board to PC. I can see that my LED close to a USB connector of a sterling is not blinking, which means that the driver is properly installed and I should not have no problems with work on a sterling which is located in the board. The second red LED is informing us about the power supply connection to the target microcontroller. And now we are ready to start the debug session. So I click on this debug icon first. Okay, so it's trying to run a debug session. Again, we can see this warning that will switch the debug perspective. And so again, we can see the different view windows configuration within our STM32QPIDE, which would be much more convenient to perform a debug operations. So I click the time over of it. I ask to remember my decision. So switch. Okay, take some time. So I can see right now a bit different view. So instead of project explorer, I can see some objects which are used by our debugger. Central point is still our main.c file. On the right side, I can see some set of tabs which are related to the views which can be used within a debug session. So variables, breakpoints, expressions, registers, so registers in general are related to, let's say, the registers of the core itself, while the peripheral registers are stored within these SFR special function registers. We have as well the live view, which we will use a bit later on. I will not focus now on those components. We'll just try to run the application. For this, we've got a bit different toolbar on top. And the main buttons are those. So display, pause button, it's resume. So once I click it, I should see my LED blinking, what you can see right on the screen. If I press this pause button, it means that my application will be paused. So you can see that my code is paused as well. And if I press this stop, it would terminate the debug session. So in case I would like to run it, I just press play, so resume. And if I press pause, I would be paused again. So if I terminate the debug session, I would come back to my CC++ perspective. So I can continue the code execution. Our next point will be a preparation of a bit more complex user interface, which we will use in the next parts, next labs within the FreeRTOS training. So we will use an ITM interface, so instrumentation stress trace Microsoft to send some data from the tasks and from the interrupts, and display them on an internal console, a single wire viewer console, which is available within STM32Q IDE. And within this part, I will demonstrate to you how to use it, how to configure it to use it as an additional debug interface, which can be used on a development phase. So we'll start with declaration of new functions. So we'll select this user code begin project function, private function prototypes. And I would declare here our task action function. So it will be task underscore action. And it will have only one argument. Okay. And then in my code, I would define this function. So it's a user code begin for the start of my function. Okay. And here I would just send to sign signs using ITM interface. So the function is the following ITM, send and send char. And I would send here message. And just to have, let's say, everything in one line, I would do the same. But this time I would use the, say, the sign of the next line. Okay. So this would be our task action code. And instead of our LED blinking, so when our start default task, we will use this task action. So I would remove this one. And I would use task action. And I would send one. Okay. So after this, I would compile the code. Start. And before I will start the debug session, I will check whether our serial wire viewer is enabled. So I need to go to the configuration of the debug. So I press on this small arrow down arrow here and go debug configurations within the debugger tab. I'm checking whether there is some as the link. So it's okay. Enable serial wire viewer. This is our setting. We'll keep the rest. The important point is here to have exactly the same core clock. It is four megahertz in our case. So we've got everything correctly set. I can start the debug session. So let's wait for a while. Okay. And now I need to run the serial wire viewer view and how to do it. If we do not know where to find it, it's good to have this quick access. And I would just select single, single wire viewer. And what is interesting for us is this ITM console. I select this. Then we need to configure it. So I click on it and I can select port zero over here. Please have a look that we can use as well some data trace. We've got four comparators here. We can specify the variable or its address and trace its value graphical way. So it's very, very convenient. I will not use it in this exercise. So I just press okay. We've got port zero SWV ITM data console. And now what we need to do, we need to start the trace. And let's try and start in our code. So I press resume. And we can see that we've got this one sent over ITM interface to our SWV ITM data console. We will use this mechanism, this task action code, task action function to communicate our tasks with us via this console. We can send, we can call this function from interrupts as well. So it will be great help for us to check in which point we are within our application. So at the moment, I will switch off the code and just one more message once you prepare the template of application, you can export it for further use using file export. And now you go to general archive. Next, you select this template. It's good to select this result and export linked resources to be sure that all of the files are stored as well as well. And we just specified I can put it template template file, I can locate it somehow, I put on a desktop template zip and save. And then if you would like to reuse it, you can always import the archived project via file import and use it for further processing. And in the rest of the exercises we will do when this free R2S training will reuse this kind of the template. So sending the data using task action and just modifying some settings of the operating system, adding some components, removing some components, but just not to waste the time on the new project generation, you can use one template and modify it. So that's it for this part. Now we can move forward to move in free R2S training. Thank you for watching this part.