Attach debugger to running program without reset

Hello PlatformIO-Gurus,

I am currently developing a variety of Projects on an STM32 (Bluepill) and an ESP32. I have Hardware debuggers for both (ST-Link V2 Clone, Olimex ARM-USB-OCD-H), which have already saved me from going insane multiple times.

I currently am trying to hunt down a bug that is hard to reproduce, i.e., occurs rarely. With such a rare bug, chances are high that it occurs when I’m not running with the Debugger active. When I notice the bug and then start debugging, the chip is reset and thus all the info I was looking for is gone.

I know that for desktop development, e.g., using Visual Studio 20something, you can attach to an already running executable. However, in the PlatformIO IDE I have not seen any such option to attach my debugger to the embedded target without resetting the embedded target.

Does such an option exist? If it does not exist, is there a workaround I can take to make the PlatformIO attach a debug session to the target? If it’s not possible with the PlatformIO IDE, is it possible with another IDE or non-IDE-Tool(chain)?

Regards
Damian

To my knowledge a flash of the debug firmware is done by the $LOAD_CMDS and the reset is done by the monitor reset halt commands that PlatformIO issues to the GDB client which then goes to openocd.

This is custumizable and thus removable. See docs. One can test that with like a very minimal firmware which e.g. does a

#include <Arduino.h>
int i=0;
void setup() { Serial.begin(115200); }
void loop() {
   Serial.println(i++);
   delay(500);
}

The loading can also be disabled by setting this to an empty value.

Example platformio.ini (unverified)

[env:bluepill]
platform = ststm32
board = bluepill
framework = arduino
; build in debug mode and upload firmware once normally via "Upload"
build_type = debug
; do not flash firmware when debugging starts
debug_load_cmds = 
; do not reset board upon connecting
debug_init_cmds =
  target extended-remote $DEBUG_PORT
  $INIT_BREAK
  monitor halt
  monitor init
  monitor resume
; this is a guess based on the openocd commands 
; in http://openocd.org/doc/html/General-Commands.html
; maybe also needs monitor reset run 
; or monitor reset init
1 Like

Hi @maxgerhardt,

your debug_init_cmds were spot-on. Instead of emptying out debug_load_cmds, I set debug_load_mode = manual to prevent firmware upload.

My overall process:

  • Start a debug sesseion with no modifications to platformio.ini. This ensures that a debug image is uploaded and running on the target.

  • Stop the debugging session but leave the target powered.

  • Extend platformio.ini as follows:

    debug_load_mode = manual
    ; do not reset board upon connecting
    debug_init_cmds =
      target extended-remote $DEBUG_PORT
      $INIT_BREAK
      monitor halt
      monitor init
      monitor resume
    ; this is a guess based on the openocd commands 
    ; in http://openocd.org/doc/html/General-Commands.html
    ; maybe also needs monitor reset run
    ; or monitor reset init
    
  • Start another debug session.

  • I can now stop the target, set breakpoints, etc. - the full debugging experience.

I can observe from the serial port that the target did not reset.

I will file a feature request for the PlatformIO IDE to offer this as a regular feature, so that you can select whether you want the regular build to build/upload a release or debug image and whether you want the debugger to reset/attach.

EDIT: Feature Request

Thank you!
Damian