Electrical – Remapping vector table in STM32F0 (no vector offset register)

bootloaderinterruptsoffsetstm32f0

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:

http://marcelojo.org/marcelojoeng/2015/09/bootloader-on-stm32f0.html

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):

MEMORY
{
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'
linking...
.\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.

Best Answer

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))) = {
     FIRMWARE_START_ADDR,
     FIRMWARE_START_ADDR + 4,
     FIRMWARE_START_ADDR + 8,
     .....
};

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