Search code examples
debugginggdbgdbserversegger-jlink

How to debug a flash program on target ARM MCU with gdb


I am trying to debug a ARM flash program on target MCU using gdb

I am setting up the gdbserver on target system (cortex-m7) with jlinkgdbserver. And I have a elf ready for debug.

For the first time, it is OK for me do debug with the following

> arm-none-eabi-gdb flash_program.elf
(gdb)> target remote localhost:2331     # connect to gdb server on target
(gdb)> load                             # since it is a flash program, jlink will flash the program
                                        # target is reset to elf entry point
(gdb)> .... (debugging begins)

However, when debug goes to some place, and I want to debug from the entry point again, the way I figured out is do flashing again

(gdb)> Ctrl+D               # disconnect the gdbserver
> arm-none-eabi-gdb flash_program.elf
(gdb)> target remote localhost:2331
(gdb)> load
(gdb)> .... (debugging from start again)

So this seems a bit redundant, also it erase and program the same flash area again and again, I am afraid I will end up damaging the storage through my debugging.

The flash program has already been burned into the medium, I simply want to let the target to reset itself and run from entry point again. But I tried things like monitor reset and run. But the target M7 both can't start from beginning again.

Is there any other gdb command that I can try?


Solution

  • I used an STM32F103C8T6 for providing an answer, but you will just have to replace its ROM base address (0x20000000) by the one your Cortex-M7 uses: In my case, I loaded the initial value for the stack pointer from 0x20000000, and the initial value for the program counter from 0x20000000+4.

    The program to be debugged was stm32f103c8t6.elf, was already flashed and did contain the debug symbols.

    arm-none-eabi-gdb
    
    target remote localhost:2331
    0x20000480 in ?? ()
    (gdb) monitor halt
    (gdb) monitor reset 0
    Resets core & peripherals via SYSRESETREQ & VECTRESET bit.
    (gdb) monitor reset 1
    Resets the core only, not peripherals.
    (gdb) monitor reset 2
    Resets core & peripherals using RESET pin.
    (gdb) symbol-file stm32f103c8t6.elf
    Reading symbols from stm32f103c8t6.elf...
    (gdb) set $sp = *0x20000000
    (gdb) set $pc = *0x20000004
    (gdb) stepi
    0x200003c2      121     {
    (gdb)
    0x200003c4      121     {
    (gdb) stepi
    122       SystemInit();                             /* CMSIS System Initialization */
    (gdb)
    SystemInit () at /opt/arm/ARM.CMSIS.5.6.0//Device/ARM/ARMCM3/Source/system_ARMCM3.c:61
    61      {
    (gdb)
    

    Depending on the type of reset strategy you want to use, you may have to explicit it in the monitor reset command:

    As explained in the Segger documentation and this great article, you can use strategy number 0, 1 or 2:

    # Normal
    monitor reset
    monitor reset 0
    
    # Core
    monitor reset 1
    
    # ResetPin
    monitor reset 2
    

    My understanding is that being able to use strategy #2 depends on how your RESET pin was wired, i.e. if it is pulled-down or not on your board.

    Disclaimer: I am a software person, and all interpretation errors related to hardware-related questions are mine...