 Hello, and welcome to the video series of how to create a super simple bootloader. I'm Bruno and I'll be your host. So here's the agenda for today. We're going to get started by creating a very simple project. Then I'm going to dive into how the linker file works and how to create a few things inside it. And then we're going to split between developing the bootloader and the application. Of course, we're going to also share an API between the two of them. And then I'm going to add a bonus track where I'm going to create a very simple static library to add in the project. So let's get started. The first thing is to create a project using the STM32Q by DE for the nuclear board G071. So here I'm going to create and I'm going to select tab for the boards filtered by TMCU, the G071. And then scroll down until I find the G071 board. And for this particular project, I'll label it as bootloader. And once the project is loaded, all I have to do is make sure that I know the settings for the UR, because that's what we're going to actually use throughout the video series. So I'm expanding here so everyone can see the above rate, parity and sub-bit. All right, now that this is all set, we can actually switch to the linker file settings. So before we jump into the linker file hands-on, I just want to share a little bit about the flow between compiler, assembler and linker file. The compiler and assembler will take the input source and produce the option files. Once we build and the linker file, which is the main objective of our videos, will be the one responsible to piece everything together and produce the final binary for us. As part of the linker file, we have the linker script, which is on the broad sense, the configuration file that tells the linker the details for how to combine the object files. This is the place we are actually going to change the play during this hands-on session. So our main goal here is to create a section in the linker file and then create a variable to place there. So by switching to the code and opening the linker script, I can actually go into a little bit more details of how the structure of the linker script works. So first we have the eStack variable that perceives the value that represents the beginning of the stack. By default, the stacks begin at the end of the run, as you can see on the declaration there. This has a sense if you consider the growing pattern followed by the stack. It grows in the opposite side as the heap. It grows from the ending of the run to the beginning of it. So for a broad perspective of how the structure of the run works, here's a chart where we can see the data, which is the segment that stores the global and static variables that are initialized by the application. Then we have the PSS, which stands for the global and static variable that are not initialized. And then we have the heap and stack. The heap will be allocated after the PSS and will grow in the same direction as shown in the arrow, where the stack, as I mentioned, will grow on the opposite side. And finally, we have our memory definitions divided into the run, which has the attributes for execution, read and write, and then flash with the attributions for read and execute. Alright, so I'll browse through here and scroll down into the sections. And what I'm going to create is a pretty straightforward section at the beginning of the yes run with the 100x address offset. And I'm actually going to use the buff section run that I just created. And I use the keep command to ensure that even if I'm not using the compiler will not remove that. And at the bottom, you can see that it was placed on the run region of the linker script. So I can actually go to the code now and use the attribute to place the variable into the section that I just created. So here I'm typing the section and placing the heap of the score run into that position. A simple way to check is by building the application. And at the end, you're going to see it's going to take a very long time to actually create the binary. And you can see here it took roughly 39 seconds to create. And if we go to the build analyzer and over the memory details, we can see that the region is there. The 128 bytes that we created on the buffer is present. And I can even see the name through the build analyzer. So this is very handy to know. But why did it took that much time to create the binary? So the main reason is because the binary file is actually a continuous sequence of bytes. So the array goes from the flash up into the run, populating everything in a continuous way. So an easy way to prevent it is to use the no load command to basically tell the compiler that this part of the run will not be filled. So it will just create the binary for the flash instead of going all the way up to the run. So if we do the same thing, we can see that the memory regions are the same, everything is kept roughly equally. But if we do go to check the binary size, then we can actually see that this size is what we would expect for around 11 kilobytes of information. Alright, so now I'm going to create something very similar, but instead of using on the run allocation, I'm going to use the flash. So I just copy and paste the buff, change the name, edit a few values to initialize that, and I'll just copy that and move to the linker part. So on the linker, very similar to what we had done for the placing in run, now we're going to do the placing flash. So I'm going to create the buff flash here, and this is the address I'm adding 1000x offset from the initial flash position. And inside it, I'm just going to keep and use the section that I just created. And of course, I'm placing that in the flash region. Alright, so if I build this, then I can actually see on the build analyzer that the flash now has the block flash buffer that I created with the 10 bytes. And of course, it's too small to perceive that on the flash size, but if we do enter in the debug mode, and I'm just keeping everything by default here, just connecting the board and entering there, we can go to the window, show view, and memory. And now I can actually add the memory region that I want to check upon. So I'm going to add the region that we created the buff. And by checking, we can actually see that the information is there present. So it was programmed while we updated the firmware there. So that's basically what I wanted to show for the first getting started part of the hands-on session. I hope to see you guys on the next video. And don't forget to like and subscribe if you enjoyed the video. Leave a comment down below. Thank you.