0
\$\begingroup\$

I am trying to understand that if for STM32F405 MCU a custom bootloader is used on the MCU then each of the two projects for the custom bootloader and the application code will have their own 'startup.s" files.

What I understand is that both of the two binaries, ie the bootloader and the application code, they both reside at different locations in the flash.

Now when the custom bootloader will exit and return the control then the control should pass-on to the startup code of the application code. But I don't know how it actually happens. Does the two binary programs resides at contiguous locations so that after the bootloader finishes the next instruction is that of the startup code?

Or they are at different locations and somehow the start address of startup of application code is saved as jump address at the end of the bootloader binary?

Will it make a difference in the way it is actually implemented if I use Keil or GCC compiler?

\$\endgroup\$
  • 1
    \$\begingroup\$ While you have received answers that are for the most part correct, they gloss over a lot of key detail. There are several existing questions here which cover practical difficulties you are likely to encounter in handing off control from one program to another, particularly with regard to chip configuration... In many cases it becomes best to set a flag, reset the CPU and then detect the flag in startup assembly and branch to the target before the initialization functions of the bootloader can run and again put the chip in a different state than the main program expects. \$\endgroup\$ – Chris Stratton Jul 9 at 12:34
  • \$\begingroup\$ Why do we need to reset the CPU for control hands-off from bootloader to main program? \$\endgroup\$ – alt-rose Jul 10 at 6:00
1
\$\begingroup\$

The compiled image of an STM32 application begins with a vector table, in which the first word contains the initial stack pointer value, the next one has the address of the first instruction.

The bootloader must obviously know the address the application is loaded at (how could it load it otherwise?), so it can look at the first two words of the image it had just flashed.

You must take the layout of the flash sectors into account when deciding the start address of the application. If parts of the bootloader and the application end up in the same flash sector, then the bootloader won't be able to reflash the app.

enter image description here

The designers of this MCU had arranged a few shorter sectors at the beginning of the flash exactly for this purpose. You might want to reserve 32k for the bootloader, and place the application at 0x08008000 for example, it's up to you (and the complexity of the bootloader).

Will it make a difference in the way it is actually implemented if I use Keil or GCC compiler?

The only difference would be in the linker configuration files, which tell the linker where to load the application. The GNU linker takes it from a linker script (*.ld), Keil calls it scatter file. They have the same purpose, but different syntax. You should adjust the linker script/scatter file of the bootloader too, limiting the amount of flash available to it.

\$\endgroup\$
1
\$\begingroup\$

Compiler does not matter, one can be used for bootloader and another for application. First you write the bootloader and see how large it is. Then you round up to nearest flash sector boundary as you don't want to erase a sector with bootloader code. Make the bootloader jump to start of first free sector. And then instruct the linker to generate code so that the application code is not loaded to start of flash (bootloader is there) but start of first free sector after bootloader.

\$\endgroup\$
  • \$\begingroup\$ "Make the bootloader jump to start of first free sector." Does it mean that while writing the 'Bootloader' we should know before hand where to jump after the bootloader exits? So we will write that jump address as the last instruction in the bootloader code? Or do we have to write the jump address outside of the bootloader code somewhere else in the other files? \$\endgroup\$ – alt-rose Jul 9 at 7:54
  • \$\begingroup\$ If you do it like I suggested, yes, then you pre-determine the start address of application yourself, and make the bootloader and application aware of their addresses. Feel free to implement more complex schemes if you want to. Yes the bootloader will jump outside of its code space, to address you specify in bootloader code, and that is the address where the application code space starts. When these binaries are loaded to MCU, there is no concept of files, just addresses you can jump to. Sorry if I don't understand what you are asking. \$\endgroup\$ – Justme Jul 9 at 9:33
  • \$\begingroup\$ In essence what is being proposed here is not to jump to a fixed address, but to put a pointer to the appropriate address at a fixed place. Since that's how the hardware starts the chip anyway, borrowing that mechanism makes a lot of sense. And if you do this, you can just copy the application's vector block to the start of flash where the bootloader's would go, and run the application without the bootloader, too - which sometimes simplifies debugging. \$\endgroup\$ – Chris Stratton Jul 9 at 14:06
  • \$\begingroup\$ @ChrisStratton actually that is what must happen. It is the standard way how the STM32 boots, it loads stack pointer and instruction pointer from beginning of flash. And by the same logic, as the application must be linked to begin at some later address, the bootloader must know this address where to fetch stack pointer and instruction pointer of application, and then jump to that address. So the application is just a standard application but can be linked normally to enable debugging without bootloader, or linked specially to later address. \$\endgroup\$ – Justme Jul 9 at 20:05

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.