I have written a bootloader before for a STM32 that had support for the vector offset and is easy peasy.

For STM32F0xx using HAL I read I need to move the vector table to ram and copy from flash. I have done as far as I know all the steps described here:


I can jump from bootloader to application but the moment an interrupt comes it crashes.

However, the ONLY thing I haven't done is to use the linker script. I have changed as follow the settings:

enter image description here

And I have selected "User memory layout from target dialgo" under Linker in Project settings. If I try to use the linker script by just writting):

VTRAM (xrw) : ORIGIN = 0x20000000, LENGTH = 192
RAM (xrw) : ORIGIN = 0x200000C0, LENGTH = 32K-192
FLASH (rx) : ORIGIN = 0x8008000, LENGTH = 256K-32K

I get the error:

*** Using Compiler 'V5.06 update 5 (build 528)', folder: 'C:\Keil_v5\ARM\ARMCC\Bin'
Build target 'Target 1'
.\Objects\DimmerBackend.axf: Warning: L6914W: option ropi ignored when using --scatter.
.\Objects\DimmerBackend.axf: Warning: L6914W: option rwpi ignored when using --scatter.
.\App2.sct(2): error: L6226E: Missing base address for region MEMORY.
.\App2.sct: Error: L6630E: Invalid token start expected number or ( but found x at position 8 on line 3
.\App2.sct: Error: L6629E: Unmatched parentheses expecting ) but found x at position 8 on line 3
.\App2.sct: Error: L6226E: Missing base address for region VTRAM.
.\App2.sct(3): error: L6292E: Ignoring unknown attribute 'xrw' specified for region VTRAM.
.\App2.sct(3): error: L6228E: Expected '{', found ')...'.
.\App2.sct(3): error: L6228E: Expected '}', found 'EOF'.
Not enough information to list image symbols.
Not enough information to list load addresses in the image map.
Finished: 2 information, 2 warning and 7 error messages.
".\Objects\DimmerBackend.axf" - 7 Error(s), 2 Warning(s).
Target not created.
Build Time Elapsed:  00:00:02

Without the linker script I can go to application but crash on interrupts. Therefore I assume somehow this magic misterious VTRAM is needed.

My questions are then:

  • What is this VTRAM?
  • Why I cant use that linker script?
  • How do I autogenerate a linker script, I dont think people write them themselves.
  • \$\begingroup\$ It is finally working! I have went trough all of it again and I can only imagine I made a small mistake somewhere. I was getting frustrated with the linking thinking it was the issue. A good way to verify the address are correct is to check the map file. Then be sure to do the copy correct and change 0x0 to ram with the macro! \$\endgroup\$
    – Carlos
    Apr 26, 2018 at 9:27
  • \$\begingroup\$ The link to the bootloader example is broken. The new link is: marcelojo.org/bootloader-on-stm32f0 \$\endgroup\$
    – NZD
    Mar 4, 2020 at 21:45

1 Answer 1


In that linker script, VTRAM is just an arbitrary area in RAM (addresses starting at 0x20000000 are in RAM), where you store the pointers to your ISRs.

As the tutorial mentions, you use the entry in the linker file to tell the linker that those 192 bytes are off-limits for use as normal RAM. If you don't use a custom linker file, the linker uses the default: it may use all memory for any purpose. This would mean that those pointers are over-written with data. When an ISR occurs, it tries to jump to the address in the vector table, which has been over-written and is now garbage.

The linker file in the tutorial is for GCC. Your screenshot indicates you use the Keil IDE, which uses armcc, and does not accept the syntax. You must either:

a. Start using GCC (*)

b. "Translate" the GCC linker file to a "scatter file" (what armcc uses).

c. Attempt to declare a IROM2 read-only area in the GUI (start at 0x20000000, size 192), then in code declare something like

volatile uint32_t VectorTable[] __attribute__((at(0x20000000))) = {

The "at" pragma tells the compiler/linker to put the pointer array at the desired location.

You are both right and wrong that "people don't write [linker files] themselves". They do, but typically by changing a template. If you decide to translate to scatter-file, I suggest you look up an example and modify it to fit your case.

(*) technically you only need to call the GNU linker; you may be able to compile with Keil/armcc and link with the GNU linker, but I can't imagine this is worth the effort

  • \$\begingroup\$ Thank you for your answer, very informative. I have opened the map file and I can see that the first address used in RAM is at 0x200000c0 so I must assume it is working correctly without the linker script. If I open the bootloader I can see the first one is on the other hand at 0x20000000 as expected. Then I am not sure what else could be missing? I haven't disabled all the pheripherical interrupts as when using vector offset didn't seem to be needed. I can try that, otherwise do you have any suggestion on what could be wrong? As I said I can boot its only when the interrupt comes it crashes. \$\endgroup\$
    – Carlos
    Apr 26, 2018 at 9:16
  • \$\begingroup\$ I'm not sure what you mean by "If I open the bootloader I can see the first one is on the other hand at 0x20000000 as expected". The bootloader should copy the values from 0x08001000 to 0x080010C0 (the ISR pointers of the loaded image) to 0x20000000 to 0x200000C0. That way, when you use the macro __HAL_SYSCFG_REMAPMEMORY_SRAM(), the CPU can find the ISRs by looking at the start of SRAM. Figure 4 in the tutorial illustrates this. \$\endgroup\$
    – Makotanist
    Apr 26, 2018 at 11:17

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

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