Showing results for 
Search instead for 
Did you mean: 

STM32F072 Boot to random address without VTOR

Associate II

I need help..
I'm trying to write my own bootloader and make the go to up to the main program, I've collected a lot of information and probably for the most part I was able to figure it out myself

In the main firmware, I made the LED blink twice for visual indication that it is working, but the LED is just on (not blinking) I can not find the error ..

I have generated two empty projects in a cubeМХ, one is the bootloader and the other is the base FW LED is blinking


Bootloader code:

#define FW_MAIN_ADDRESS_START 0x0800A000

void StartMainFw(void)
uint32_t MainfwStartAddress = 0;
void (*GoToMainFw)(void);
MainfwStartAddress = *((__IO uint32_t*)(FW_MAIN_ADDRESS_START + 4));
GoToMainFw = (void(*)(void))MainfwStartAddress;
__set_MSP(*((__IO uint32_t*)FW_MAIN_ADDRESS_START));

Main FW

#define APPLICATION_ADDRESS 0x0800A000

#if (defined ( __CC_ARM ))
__IO uint32_t VectorTable[48] __attribute__((at(0x20000000)));
#elif (defined (__ICCARM__))
#pragma location = 0x20000000
__no_init __IO uint32_t VectorTable[48];
#elif defined ( __GNUC__ )
__IO uint32_t VectorTable[48] __attribute__((section(".RAMVectorTable")));


for (i = 0; i < 48; i++) {
VectorTable[i] = *(__IO uint32_t*) (APPLICATION_ADDRESS + (i << 2));
  /* Enable the SYSCFG peripheral clock*/
  /* Remap SRAM at 0x00000000 */
Andreas Bolsch
Lead II

Well, this can be almost anything ... Try single-stepping through bootloader and inspect registers after each step.
To do this in a sensible way, you need the assembler listing (preferably intermixed with C source).

BTW 1) What about your linker files? How did you adopt the default one for your main firmware?
2) There is no need to copy the vector table from flash to RAM by yourself. By instructing the linker that the (main firmware) vector tables's relocation address is at begin of RAM whereas its load address is in flash, the startup code will automatically do the copying, in the same way as for initialized global variables. For GNU ld this might look like
/* The vector table goes first into FLASH */
.isr_vector 0x20000000 :
. = ALIGN(4);
_sdata = .; /* create a global symbol at data start */
KEEP(*(.isr_vector)) /* vector table */
. = ALIGN(4);


Thanks for the answer
Unfortunately, I don't know assembler...
In fact, I thought it would be easier, like with other series, such as M3 or M4...

I change the FLASH (rx) : ORIGIN = 0x800A000, LENGTH = 128K

You don't have to know all details about assembler, probably the cpu runs into a HardFault for some reason. From stepping through you will see *where* this happens in machine code, and then by comparison to the C sources, it will be rather evindent where the problem is in source code.

In principle it's not complicated, most certainly just a simple detail ...

I'd suggest to comment out the _HAL_*Deinit() call in bootloader and the corresponding _HAL_*Init() in the main firmware for the time being. For blinking an LED the settings from the bootloader are certainly safe to retain.
Furthermore I'd try to leave interrupts disabled in main firmware as well, until you're certain that jump to main firmware and set up of vector table works as desired.

The "__set_MSP" is not necessary, as the CubeMx startup code initializes the stack later anyway (don't know why, as it is initialized by hardware upon leaving reset ...). And even if not, the worst thing would be to sacrifice some stack area. The "FLASH (rx) : ORIGIN = 0x800A000, LENGTH = 128K" probably has to be changed to "FLASH (rx) : ORIGIN = 0x800A000, LENGTH = 88", but at this point it doesn't matter.


Actually I don't know how stepping from bootloader to main FW in debug mode In bootloader not goes into a Hard Fault, but in main FW in hal_delay i goes into some error (Break at address "0x20004000" with no debug information available, or outside of program code.)

My code in while(1) very simple:



that in my microcontroller it is impossible to change the vector table, as in other versions, I need to copy the vector table from the address 0x08000000 to 0x080000BC in SRAM from the address 0x20000000, if so, then now I'm trying to check if the copy is correct

Andreas Bolsch
Lead II

Break at address "0x20004000" is right beyond end of RAM. Hm, could be stack or vector table related, probably the latter. The HAL initialization probably sets up and *enables* SysTick interrupt, even before your vector table copying takes place. To overcome this, the vector table copying must be done in the startup code *before* "main" is called.

Actually I did something rather similar recently for F030/G030: With the addition above to the linker script that's done automatically, no need to worry about size of vector table etc. and it happens even before SystemInit is called, so no chance that an interrupt might interfere. 

Regarding stepping through bootloader: That depends on your development environment, so I can't help there ... 

I have a question if possible
I looked at how the vector table is copied to the SRAM and I have an address offset, I am attaching screenshots, is this how it should be?


Ah, that's the problem. The vector table in RAM must start with value 0x2000400 (initial stack pointer), exactly as the one in flash. Essentially your vector table starts at 0x2000000C, not 0x20000000 as it should. Most likely the linker placed some other variablen at RAM start, so the vector table comes later ...

Probably you use GNU C? Your #define says that your RAM vector table goes to section ".RAMVectorTable", but it looks like your linker script lacks an absolut placement for that section, or maybe additional sections go to the same region? The placement of section ".RAMVectorTable" must be the first and only one in a special region, and this region must come first, too. Alternative approach for GNU ld:

The startup code contains a line .section .isr_vector,"a",%progbits, i.e. the vector table has a special section named .isr_vector, and this section is placed at the very beginning of flash via linker script (STM32F072RBTx_FLASH.ld or similar):
/* The startup code goes first into FLASH */
.isr_vector :
. = ALIGN(4);
KEEP(*(.isr_vector)) /* Startup code */
. = ALIGN(4);
The attached linker skript (for G030, but changes for F072 are straightforward) places vector table in flash and  ensures that the startup code will copy it to 0x20000000 --- automatically. No need to copy it yourself!

Why's the table misaligned, needs to be at 0x20000000, or appropriate 256/512-byte aligned address.

The stack can start at 0x20004000, it predecrements, and moves downward from there.

Tips, buy me a coffee, or three.. PayPal Venmo Up vote any posts that you find helpful, it shows what's working..

Thanks for the detailed answer, I will study it, for me the linker script is new to me, as if I read the Chinese language.
I use STM32CubeIDE.
I took an example of a bootloader from the repository for STM32091C_EVAL, there is an example with copying the vector table, so I did it that way.
I will deal with your example for G0
Thank you


I didn't think it would be so difficult in F0
In the reference manual, it is also written to copy the vector table and relocate to the SRAM, but for some reason this does not work correctly.