I think you need to at least tell the firmware that its base address is now different, since the code is not position-independent (-fPIC
). That should be achievable via manipulating certain build flags and upload options in the platformio.ini
. Specifcially, for uploading, board_upload.offset_address
should be set to the absolute address where the binary shall be flashed. (Then PIO is also perfectly capable of flashing the binary directly).
Further, in the STM32Duino, sadly it only chooses from a handfull of offsets depending on the upload protocol, which won’t be correct for your case. So you would have to manually define -DVECT_TAB_OFFSET=<offset from 0x8000000
> and the -Wl,--defsym=LD_FLASH_OFFSET
flag.
In general, the Application note AN4767 by STMicroelectronics would also be an interesting read for you.
In any case, if I create an example project like
[env:nucleo_l073rz]
platform = ststm32
board = nucleo_l073rz
framework = arduino
with functionally empty src/main.cpp
of
#include <Arduino.h>
void setup(){}
void loop(){}
and compile the project, I can inspect the start address of the ELF file by force-disassembling the first 20 ‘instructions’ in the ELF file by doing
>arm-none-eabi-objdump -D .pio\build\nucleo_l073rz\firmware.elf | head -n20
.pio\build\nucleo_l073rz\firmware.elf: file format elf32-littlearm
Disassembly of section .isr_vector:
08000000 <g_pfnVectors>:
8000000: 20005000 andcs r5, r0, r0
8000004: 08001c05 stmdaeq r0, {r0, r2, sl, fp, ip}
and so the the firmware starts at the regular 0x08000000
. Now when I rewrite the platformio.ini
as in…
; global build settings
[env]
platform = ststm32
board = nucleo_l073rz
framework = arduino
[env:nucleo_l073rz_bank1]
; no special options
[env:nucleo_l073rz_bank2]
board_upload.offset_address = 0x08018000
extra_scripts = set_bank2.py
with set_bank2.py
as
Import("env")
offset = 0x18000 # from 0x8000000
env.Append(
CPPDEFINES=[("VECT_TAB_OFFSET", "%s" % hex(offset))],
)
# remove old 0-offset, inject new one
linkflags = env["LINKFLAGS"]
linkflags = [x for x in linkflags if not str(x).startswith("-Wl,--defsym=LD_FLASH_OFFSET=")]
linkflags.append("-Wl,--defsym=LD_FLASH_OFFSET=%s" % hex(offset))
env["LINKFLAGS"] = linkflags
And try to compile, most annoyingly, there is a compile error caused by the provided Arduino-STM32Duino…
C:\Users\Max\.platformio\packages\framework-arduinoststm32\system\STM32L0xx/system_stm32l0xx.c:71:1: error: unknown type name 'define'
71 | define USER_VECT_TAB_ADDRESS
| ^~~~~~
This line has to be #define USER_VECT_TAB_ADDRESS
to be fixed. Doing that, one gets a Bank2 firmware which…
>arm-none-eabi-objdump -D .pio\build\nucleo_l073rz_bank2\firmware.elf | head -n20
.pio\build\nucleo_l073rz_bank2\firmware.elf: file format elf32-littlearm
Disassembly of section .isr_vector:
08018000 <g_pfnVectors>:
8018000: 20005000 andcs r5, r0, r0
8018004: 08019c11 stmdaeq r1, {r0, r4, sl, fp, ip, pc}
starts at the right address ^-^. And as a side-effect, it also builds the firmware made for Bank1.
Now that firmware has a better chance of working. I’m not sure about the bank boot selection process, but if you’ve already figured that out so that it immediately starts executing at 0x08018000
, that should also be taken care of.