 Hello and welcome to Lab 7 of the STM42C0 MOOC. In this lab, we will learn how to execute code from RAM instead of Flash to improve the performance and the power consumption. The objective of this lab will be first to create a little application and then we will move part of the code into RAM. This is the top view of the application we want to develop. So basically, we're going to have a UR terminal. And this terminal, so every time we send a character, it will be sent back to the terminal. So the STM42C0 is going to be responsible for that. And it's going to recognize what character has been typed. And if it is the E or like uppercase E or lowercase E, then we'll toggle the LED on your nuclear board. Under QBID, we will create a new project. And the first thing we'll do is to configure the USART2. So you'll find it under connectivity. So that's USART2. And asynchronous mode for the parameters, we'll use 115,000 and 200 boards, 8 bits of data, no parity, and 1 bit of stop. And make sure that the proper IOs have been selected, which are PA2 and PA3 right there. Otherwise, please remap them. So under QBID, create a new project. Select part number, like we did previously. So STM42C031C686. Then press next. We give a name to the project. So STM42C0, for example, RAM, and press finish. So in pinout configuration, under connectivity, click on USART2. And select the asynchronous mode for the parameters. So go to the parameter settings. We're going to select 115,200 boards, so bits per second. And then 8 bits of data, no parity, and 1 bit of stop. And then make sure that PA2 and PA3 have been selected. Next, we're going to go into the NVIC settings to enable the USART interrupt, because we want to use the interrupt mode of the USART. So to do this, enable the USART2 interrupt. Now go to NVIC settings and enable the interrupt for USART2. Now we're going to configure the LED. So to do this, remember PA5 configured as an output. So GPIO output. And then we'll give a user label, and we'll call it LED. So PA5 configure it as a GPIO output. Then right-click on it to enter a user label. So we call it LED. For the clock configuration, switch to the clock configuration tab and enter 48 MHz for the HCLK, which is the system clock. Switch to the clock configuration and select 48 MHz. To optimize the code, we will use the low-layer driver, so the LL library. So remember, we talked about it in a previous lab. So this is a way to optimize in other performance and also the code size and the RAM size. So go to Advanced Settings in Project Manager. And then we'll configure RCC GPIO USART and Cortex MZO+, as LL switch to Project Manager. Then select Advanced Settings. Now instead of HAL, we'll select the LL, so the low-layer drivers for RCC GPIO USART and also the Cortex MZO+. Now generate the code. So remember, just save the project that will generate your code. Press Yes and then change perspective. Time to add some code. So we're going to use one of the features of the QBID. Remember that if you press Control and Space, that's going to give you a template proposal. So for example, if you press uppercase LL, underscore USART, and then press Control and Space, this is going to give you a list of all the functions that you can use. First step, we're going to enable the interrupts for the UART, both receive and errors. In main.c, in the user code 2 sections, we're going to add two function calls. The first one is to enable the interrupts for receptions for USART2. The second one will be to enable the interrupts for errors for USART2. And here is where we're going to add the code. Go to the USART2 sections. So this is in main.c, right here after the initialization. So we want to add two lines of code, remember, LL, underscore USART, then Control Space. This gives you all the different functions you know that are available. The ones that we want are so enable IT, right? underscore, and we want to enable, so first the reception, so RxNE. And then put USART2 right here. Scroll down to the user2 section that is located in your main function, in main.c. First function you want to add is to enable, remember, the reception on USART2. Then enable the interrupts for errors for USART2, right here. Again, so you can type this code by yourself, or you can copy and paste it from the document, the text file that we provided with the MOOC. Second step is to define the callback function for the UART in main.h. In main.h, in the exported function prototype, so which is EFP, we're going to add the definition of the callback function for our UART in this section right here, in main.h. To open main.h, so one easy way is you go to the include of main.h right here, then select it, so select at least in our main, then right click and click on open declaration. This will open main.h. Scroll down and look for the EFP section that is located right here. Now add the definition of our callback function. So USART underscore char reception underscore callback. In the third step, we will create service routine in callback. In the user code section 4 of main.c. The function will save receive character and transmit it back. It will check the receive character and compare it with the character's lowercase e and uppercase e. If there is a match, we will toggle the LED. Here is the function. So USART underscore char reception underscore callback. So we'll have a variable receive underscore char. And then we'll save the receive data from the user2 and we'll send it back at the end of the function. We will compare the receive data with uppercase e or lowercase e. If there is a match, we'll toggle the LED. In main.c. So in the user4 section, scroll down at the end of the file, you're going to add the callback function that we just talked about. So same thing, you can either type it, so pause the video and type it, or copy and paste it from the document that we provide with the MOOC. Last step, we will call the service routine in the IRQ handler. In the file stm42c0xx underscore 80.c, find the IRQ handler for ur2. In the user2 IRQ handler, add the callback function we just added. The file ending by 80.c can be found under call and then source, so here. And here is the file, see? So stm42c0xx underscore 80.c, double-click on it. Look for the IRQ for ur2 or user2 which is located here and add our callback function. Save your project and then build it with the icon right there and now make sure that your board is connected and you can enter the debug session. Press OK and OK again. Now use any terminal on your PC, so use your favorite one, like I don't know, for example, Terratorme or Putti. So in my case, I'm going to use the one that is embedded inside the cube ID. For the terminal to open it, so go here, you see this icon right there. So this has an arrow down that you want to click on and then you're going to open command shell console. So here, me, I have already, you know, like a one that is selected. So this is my new term. That's the name I gave for the serial port. So if you don't have it, if you never used it, what you want to do is select, you know, the connection type to serial port. Then you're going to click on new. Give a name, select the port that is connected, you know, to your ST link. So the enumerated COM port of your ST link, virtual COM port. And then select for the board rate, 115 and 200, 8, 9 and 1. In my case, so I can click cancel because I already have it. And I can select the new term that is already here. Okay. To test that my application is running, we're going to execute the code. Now make sure your console has been selected and you can type, for example, E. So E is going to toggle the LED on your nuclear port. If I type something else, this is going to return it, but it doesn't toggle the LED. If I press uppercase, that also toggles the LED. See, but if I type, for example, Y, it just returns the character, but it doesn't toggle the LED. So the application is running properly. You can now terminate the execution. Now that we have our code, so the application called running from flash, we're going to learn how to execute from RAM and what are the benefits of executing from RAM. First, this has to do with the code execution. So this is going to be a faster code execution because the flash requires one way state, whereas the RAM requires zero way state. Running from RAM is also useful in bootloaders or other codes where there is a need to reprogram the flash during running of the code. It uses less power because you can execute from RAM and turn off the flash. But you won't say space in flash because anyway, you have to store the code in flash and then copy it into the RAM. Where is what stored are defined in linker file or linker script? Definitions and allocations are made in chronological order. Each ID have different semantics and process how to use it. We will do modifications in linker file for GNU compiler collection. In cases where the vector table is placed in RAM, do not forget to change the VTOR register. Let's look at the structure of a linker file. So we're going to look at the allocation of specific variables and functions in the linker file. This is defined by specific names. So for example, data for initialized variables. BSS for non-initialized variables. Texte, this is for the code. ROR data, so it stands for Read Only Data so like the constants. The star will define all the files or functions. It is possible to allocate specific functions by using starfile.or.text.userCode. The goal of this lab is to place part of the code into the RAM. So which part of the code will be placed in RAM? First, the drivers. So containing all the LL drivers, so the low-layer drivers. Then, all the initialization of the peripherals. Finally, our callback function. Before doing any modifications, we're going to look at the memory footprint of our application. In SCM52Q by D, so we can look at the build analyzer to look at the data for memory regions and usage of RAM, flash in kilobytes and percentage. This is the build analyzer for our application. You can look at the RAM usage, the flash usage, the start address and address, the size. Then by clicking on memory details, you can have access to more information. Like for example, the data section, the BSS sections, the heap stack section. To access the build analyzer from QID, just go to Windows and then show view, build analyzer. So this opens this window. You have the memory regions first. So with the RAM usage and the flash usage. And then you can go to memory details where you have more details about the flash organization and also the RAM organization right here. So in your project, so the SCM52C0 underscore RAM, for example, in my case, you're going to expand it and look for the LD file. So the LD file is your linker file. So in our case, the file is named SCM52C031C6TX underscore flash dot LD. So open this file. Okay. So your linker file is right here. See the LD file. So double click on it. And now we're going to start modifying it. When it comes to linker files, so allocations are made in chronological sequences. First, we remove part of the data sections into RAM line 131 to 147. And we'll place it before other data and flash line 61. Scroll down to the line 131 of your linker file right here. And then so select from 131 to 147. And then cut this part. Now scroll back up to line 61. And we're going to add the part that we just cut. So we're going to paste it right here. Perfect. To move the LED drivers into RAM, we're going to add this line right here. So line 73. So we're going to add star, then drivers star dot text star. So line 73, right after RAM fact, you're going to add this. So star, driver. And we're going to add it here. In order to move our init functions and also our callback function, we're going to add these three lines right here in our linker file. Line 73. Add these three lines. Like this. OK. So one to move, you know, the GPI unit. One to move the UART, you know, two init. And one to move our callback function. We are now done with all the modifications. So you can save your project and build, you know, the project again. Make sure your board is connected and now enter the debug session. Now we're going to add some breakpoints. So first in main.c, one inside our callback function and also one inside the user2 init function. We'll also add one inside the IRQ handler for the UART2. We're going to add the breakpoints. So scroll down and go to the first function. We're going to add the breakpoints. So that's the init function for user2. And to add the breakpoints, what you're going to do is put your cursor on the left side of the line you want to add. So 154 in my case. And then left click. So double left click. And as you can see now, so this is a breakpoint that has been added. OK, next one we said inside our callback function. So remember, at the end, so in this section right there, and we're going to put it right at the beginning. So I'm adding another breakpoint. OK, another breakpoint. So third breakpoint, you're going to put it inside your it.c file. Scroll down to the UART. So the IRQ UART2. And add the breakpoint right there. Now we will display the disassembly window. So to do this, very easy, you're going to go to window, show view, disassembly. OK, for the disassembly, so go window, then show view, and look for disassembly. And right here, so we have our disassembly window with the addresses in the memory map of the SDM42C0 and the assembly instructions. As you can see, the code starts in flash because look at the address here, 8 million, so this is the address of the flash. Now execute the code. So we're going to stop at our first breakpoint. And now look at the addresses here. So this is the RAM, you know, the 2 million, this is the RAM area, so the RAM. So now we're executing from RAM. Now resume the execution of your code. And remember, so the code is waiting for a character to be typed into the terminal. So I'm going to open my terminal right here and I'm going to press a key. And now, see, we hit another breakpoint. So this is the one inside the IRQN layer of your 2. And this is executing from flash, as you can see, so 8 million addresses range. So we are back to flash now. Now, if you continue, so if you resume, we hit the third breakpoint that is inside our callback function. And this function, remember we moved it to the RAM. And we can see that because the addresses are back to 2 million ranges. Ok, so if we continue the execution, if I type on another key, you see I'm back to flash now. So this is the IRQ that is still in flash. So we can move also the IRQ into flash, but then don't forget to remap the vector table and the Vitor register. And so on can continue. Now we are into RAM. Continue. Hit a new key. We are back to flash. Continue. And now we are in RAM. So perfect. So we did what we wanted. So we moved some code into RAM, as you saw. So you learn how to do that by changing the linker file. So perfect. And you can close this project.