Hi, after digging thru different docs I finally manged to Debug in RAM.
My Setup is:
Black Magic Probe on STM32F4 Discovery Board, VSCode, Framework: opencm3, so your mileage may vary.
Starting with:
copy the original linker file stm32f405x6.ld to the root of your project and name it
[env:disco_f4]
board = disco_f407vg
platform = ststm32
framework = libopencm3
build_type = debug
upload_protocol = blackmagic
upload_port = /dev/ttyBmpGdb
debug_tool = blackmagic
debug_port = ${this.upload_port}
monitor_port =
build_flags =
-Werror
-Wl,-Map=${BUILD_DIR}/${PROGNAME}.map
board_build.ldscript = stm32f405x6_ram.ld
debug_init_break = tbreak reset_handler
debug_init_cmds =
# set trace-commands on
define pio_reset_halt_target
set language auto
; automatically by load
# set $pc=reset_handler
set $r0=$r1=$r2=$r3=$r4=$r5=$r6=$r7=$r8=$r9=$r10=$r11=$r12=0
# _stack does not exist, so "end" or:
set $sp=vector_table.initial_sp_value
set $msp=$sp
; VTOR in RAM, hardcoded
set *0xE000ED08=0x20000000
end
define pio_reset_run_target
pio_reset_halt_target
end
target extended-remote $DEBUG_PORT
monitor swdp_scan
attach 1
set mem inaccessible-by-default off
delete mem 0 # dont write flash
$LOAD_CMDS
$INIT_BREAK
pio_reset_halt_target
build your project but don’t upload. Instead start debugging (Pio Build in Statusbar, than switch to Debug pane and press the green play button (PIO Debug)
It should upload your ELF file to RAM and break in reset_handler. You can change this if you are quite sure that init stuff will work and change it to main or any location you like.
I tested with some interrupt / exception handlers which are working. I didn’t want to make HW changes (boot1 switch) nor software changes messing with reset_handler.c or startup.s (in different frameworks) so I put everything in the GDB init. Basically its just mapping your flash to RAM in Linker definition file, and change the provided debug init commands to:
forbid any kind of reset
re-implement missing init: SP / VTOR
optionally: delete flash mem area to no accidently write to it, init registers
Maybe not perfect but working. I will try to prove this on other boards/frameworks.
I continued testing, and found a strange problem which seems to happen only occasionally (!)
I tested with a simple systick handler, and a noticed a misalignment of one byte, from the entries in the vector table to the correctly aligned start adresses.
The consequences: all interrupts load wrong locations, even if this was tested succesfully.
gdb loads the elf
Start address 0x20000310, load size 1020
and pc is set to this value which is correct.
Each of those entries is correct, because the address of a function which is supposed to be executed in Thumb mode vs ARM instruction mode has to have + 1 to the address. The address jumped to will have the last bit masked (set to 0).
Ok, I was searching at wrong directions. It seems that MSP was forgotten to be initialized, I added this in the first post. It seem to work now, tried with timer / uart ISR, even in single step mode.