 I will start with STM32QPIDE, you can use as well QBemix with your preferred toolchain. So, within STM32QPIDE, I would create a new project within current workspace. So, file new STM32 project, I'm selecting my microcontroller for 7.6LG board. I press next, name of my project would be 12 underscore T-class. Okay, within hardware configuration, I will start with selecting a debug interface. So, system core says, within debug, I'm selecting trace a synchronous SW to have two debug lines, SWD and one single trace line, which is called single wire output SWO. I would change as well the time-based source from default SysTick to Timer 6. This time-based source is used by the whole library. I selected it, I changed it from SysTick because SysTick is reserved for operating system. Within middle-wars, I would select 3R2S in interface CMC's V2, within its config parameters tab. I need to enable use tickless idle, which is by default disabled. I will select build-in functionality enabled, which would guarantee that once I would create, generate the project, all of the functions supporting tickless mode would be already configured and they would use sleep mode, within STM32 L4 device. Then, within tasks and queues tab, I would just rename existing task because we will need one task in this project. I double-click on its name, I change default task into task1, I keep the priority as priority normal and I change the stack size to 256 words. The entry function I will change to start task1 and that's it. We are done with configuration of 3R2S. There are two missing points in front of us. As we would like to use low-power modes, we would need some additional timer to wake up our system from low-power mode. We will use low-power timer, which would be clocked by the external crystal 32 kHz, which is installed on my board. So first, I need to enable this low-power oscillator, so I go to RCC and within low-speed clock LSE, I'm selecting crystal ceramic resonator. If I have a look on the pinout, I can see that this resonator is present right now. It's visible that it's connected on my pinout. Next point would be selection and configuration of this low-power timer. So I go to timers, low-power timer 1 and within mode, I'm selecting COUNT, COUNT's internal clock events. Within the configuration, I'm selecting the pre-scaler to divide by 32, as I would like to have 1 kHz timebase. Instead of 32 kHz, I would like to have 1 kHz on input of my low-power timer 1. Okay, so the rest of the parameters I would keep by default. Then I need to configure the clock source for my low-power timer 1. To do this, I go to clock configuration. As you can see, the complete system is still working on MSI 4 MHz, which is the default configuration. If I go down, I can see that there is a low-power timer 1 clock multiplexer. By default, it is sourced by peripheral clock 1, which is 4 MHz, and now we will change it to LSE, which is 32 kHz. If we scroll up, we can see that our LSE crystal is already present, it's selected. As we have done it with an RCC peripheral. There is one more point to be done, so I come back to pinout and configuration, and within my low-power timer configuration, I go to NVIC settings, and I enable low-power timer 1 global interrupt. I can keep the default priority settings. That's all for now. We need now to activate all of the components and make some code processing. I generate the code and open main.c file. If main.c is not open automatically, you can go to core, source, main.c, and by double-click, you can open this file. Now we will do some code processing to activate the stickless mode. Let's continue with main.c file. The first thing I would like to implement is our sign-of-life function, so task action. I would first define this prototype when this user code begin private function prototype section. So this is void task action. You can use any other function. I'm using ITM interface on one line as the single-wire output to send simple messages from the tasks and the interrupts. I would, let's say, define this function, so just not to waste the time. I would copy-paste it, see header, and locate it in code. This area is very good for this. So user code begin for section, and I would just send over ITM interface. Okay, so this is our sign-of-life function. And then let's fill the function body of our task one. To illustrate the stickless mode, we need to simulate the situation where one, let's say, all of the task except idle task would be in a blocked or suspend state. In this case, a scheduler can enter into low power mode within idle task. So to do this, within my, let's say, task one entry function, I would go to the blocked state for five seconds at the beginning. Then I would send some sign-of-life after this, and I would keep this task active for half a second. Additionally, to observe the current consumption on the cube monitor power. Okay, so those are all modifications within main.c file, and next point would be some code modification within freeRTas.c file. In the next step, we'll switch to freeRTas.c file. At the beginning, we need to make our low power timer one handler visible within this freeRTas.c file. So let me just copy the declaration of this handler. I will use these private variables and add extern. Then we need to prepare application to enter into low power mode. Please have a look that within this freeRTas.c file, as we enabled T-class mode, we can see two new functions, press-slip processing and post-slip processing. Those two functions are used to prepare our system to enter into low power mode, and then to, let's say, prepare the system to work after low power mode. Let's focus first on this press-slip processing. So to prepare our system to enter into low power mode. Please notice that both functions are defined here within, let's say, as weak functions, so we can either do the code processing within this file, or we can declare the same functions or define them within main.c file within our code area. I would continue with this file as it is done like this within the slides. Now, within this press-slip processing function, at the beginning, we need to suspend the HAL timebase by calling HAL suspend tick function. In our, let's say, example, it is timer six, which we selected as a timebase for the HAL library. So I will stop the tick timer for the HAL library. Then in the second step, we need to start low power timer one in interrupt mode using HAL low power timer underscore timeout s. We would like to start it with some timeout. So it should, let's say, wake up us after some timeout. We will use interrupt. So I will select this function. First argument is, let's say, the handler to our low power timer. The second argument, it is the maximum possible period. And we will use the maximum value for 16-bit timer. So it is for f's and the timeout itself. This timeout, it is the second argument is, in fact, auto-reload register content. And the timeout, it is the value we would like to, let's say, count two. And this value should be taken from the argument of our, let's say, presleep processing. And this time is calculated automatically by the free R2S code. It is calculated based on the system clock and tick timer. Tick timer in meaning of operating system tick timer. So sys tick. It is calculated in such a way to not overflow this timer. In our example, the maximum expected idle time should be not more than 2 in power to 24 as sys tick is 24-bit long. And it should be divided then by 4 MHz as it is our system clock. So the maximum value within this expected idle time should be 4194. In case all active tasks are sent to block state for longer time, like in our example, 5000 milliseconds, we can observe intermediate wake up of the system after 4194 milliseconds and then enter into low power mode again for the remaining sleep time. It is handled automatically by free R2S tickless mode implementation, but it is visible, it will be visible within our current measurement process. So this function have, let's say, three arguments, handler to low power timer, its maximum value, so auto-reload register, and its maximum timeout specified by the tickless mode of free R2S. And this value is calculated to not overflow the sys tick and the wake up and reload it again in case our timeout is longer than this maximum value. Okay, so this is, let's say, all operations within press sleep processing. And the next point would be, within this file, preparation application to exit from low power mode. So to prepare the code, which would be executed just after wake up from low power mode. And what we need to define here. In step one, we need to stop low power timer by calling similar function than this one, but to stop this timer, the only argument of it is the handler to, let's say, our low power timer one. And then we need to resume our timer six for HAL operations. So HAL resume tick without any arguments. After this, we can compile the code and start a debug session. And our application should work in a following way. Active task is going into block state for five seconds, what we've seen at the beginning. Then at this time, the idle task would be the only active task. So scheduler will send our operating system into low power mode. By default, it is a sleep mode. After, let's say, 4194 milliseconds, more or less, we will be woken up by the system, as it is, let's say, the maximum timeout possible to be set within the system. After this, we will go immediately to low power mode again for the remaining time. And in total, we would be five seconds in this low power timer one. Then active task will send its sign of life. So it can be, for example, LED on or in our case, SWO data send this one over the data console. And then it will be active for half a second. This is done by this HAL delay function. After this, it will start its second iteration of this endless loop, of its endless loop, and it will start from five seconds in a block state. So we will go to the idle task once again. So let's verify it. We can connect, let's say, all the components together and start the debug session. Okay, I will start with, let's say, code build. So I press the hammer button and let's check whether there are no bad surprises. Okay, no errors, no warnings. So we can start debug session, but the board is not yet connected. So let's connect our exNucleo to our Nucleo board. This step you can replace by connecting the multimeter. If you would like to connect the multimeter, you can use JP6 jumper IDD marked, which is present just on top of the microcontroller on the board. Then if you are using the multimeter, you need to connect, let's say, both cables on this jumper. I will use a different connection. I would use exNucleo LPM01 board and cube monitor power application. My exNucleo LPM01 board would be, let's say, the source of the power to my microcontroller. So I will have the following connection. I would connect the GND wire on top of the board and I would use the red wire on the left pin on this JP6 jumper. Then the same wire I would connect to the white socket. It is marked CN14 on exNucleo LPM01. The black button GND would be connected to the first pin on this white connector. The third connector I would connect the red button. So that's the plus. Then I need to connect the both boards to USB. I will use mini USB cable for my Nucleo L476RG and I would need, let's say, micro USB cable to connect to my exNucleo LPM01. Both boards are connected. Coat is compiled. So let's start a debug session. So I would just, let's say, run it, clicking the back icon. Within the debugger I would enable serial wire viewer, as we are using single wire output pin, and I would set it to 4 MHz. Okay, now device found target. We need to power our application. As it is powered through this exNucleo LPM01, I need to start my STM32Q monitor power. So I will do this now. So this application looks like this. I will just, let's shrink it a bit. Okay, first I need to select the board. So in fact the virtual COM port where it is connected. So in my case it is COM 21. I put take control. Okay, then I can select the sampling frequency. So how often I would like to take, let's say, the samples of the, let's say, the current consumption of the board I'm supplying. Acquisition time I would set to infinite, just not to say finish exercise earlier. I can put as well the input voltage, so the power supply voltage. I would keep, let's say, the default value, and I press start acquisition. After this we can see on the screen the current consumption of my Nucleo board. So now the board is supplied. I can start once again the debug session. So I come back to the cube IDE. I start debug session once again. You can see that debugger is connected right now. Okay, I will run this single wire viewer, ITM data console, so I click on this. In case you do not see it, you can use this quick access and put single wire viewer and select this line with the monitor icon. As I've got it already, I would use this. And I need to configure it. So I click on this configure trace button. I select this zero channel with an ITM stimulus board. This is my single wire output pin. And I start tracing by clicking on this icon. Then I press resume. And I should see within this board once per, let's say, five seconds one, which is our sign of life. Let's switch to our cube monitor power application. And we can see at the moment how it is working. So let me stop acquisition and comment a bit. We can see, in fact, a few phases here. Let me start from this point. At the beginning, we can see that application is in some low power mode. So the maximum current consumption in this mode is 900 microampers. And then after more or less four seconds, we've got this wake up caused by the overflow of cystic. Just after this, we are continuing, let's say, our low power mode. So the total time, it should be, let's say, five seconds. Then the task is woken up from blocked state to the run state. It is sending this one over ITM interface. And it's waiting using how delay half a second. So this is our half a second. In fact, more or less, come back to this point. So at the beginning, there is some startup. So we will not focus on this. We need only this area. So as you can see, it's quite easy to manipulate on this. You just select the area and it would be automatically scaled. We can see that this space is really half a second. This space is half a second. This one is one five seconds. So we see this tickless mode is operational right now. The current saving is not that much in the beginning, because by default, we are using sleep mode. So let's come back to the code and analyze it for a while. Okay, after we stop a debug session, we can observe what is happening within the code. So the tickless mode, in fact, is programmed within port.c file. So I go to middle worse, third part is free or to source and port table. Then GCC, ARM, let's say Cortex-M4 and port.c. And what we are, let's say, looking for here, it is the function vport suppress ticks and sleep. So vport soup, let's see whether it will find it. Yes, it is our main function responsible for the tickless mode. Please have a look that it's run only if the tickless mode is with an option one. We just selected the beginning of this part. If we go below, the most critical point is over here. So this is real entrance into low power mode. As you can see, it is done by execution of WFI instruction. So wait for interrupt, which is calling, in fact, sleep mode. Sleep mode within Cortex-M devices. So in our next exercise, we will try to replace it with, let's say, entrance into more restrictive, more, let's say, current saving mode, which is a stop mode. So we will replace it with some other code. But just to let you know where to find the heart of this tickless mode implementation, it is port.c file and the function name is vport suppress ticks and sleep. So thank you for watching this video. We will continue tickless mode analysis with other low power modes, like stop one or stop two in next videos. Thank you for watching.