I’m trying to chase down an issue with debuggers failing to connect. I’m using PlatformIO on macOS Mojave in VSCode (PlatformIO, version 3.6.5
, IDE extension 1.6.0). My target is an Adafruit Trinket M0, wired up to a Cortex Debug Port (10 pin 1.27mm pitch).
I’ve got the following debuggers in front of me:
- ST-Link/V2 clone with CMSIS-DAP compatible firmware loaded
- Atmel-ICE
- BlackMagic Probe (1bitsquared hardware)
- J-Link EDU.
The J-Link is the only one that reliably works under all circumstances, and I can’t figure out why. I could just use the J-Link and be done with it, but this is a commercial project and that’d be illegal, so I’d like to get any of the others working reliably.
Here’s an experiment. I’ve run it with the Metro M4 for easy reproducibility - results are basically the same between the Metro M4 vs the M0. And the blackmagic probe isn’t supported for the M4 out of the box, so that result is on my Trinket M0. Each run I start with a fresh vscode launch and a deleted .pioenvs.
Metro M4, USB Power, J-Link EDU
; platformio.ini
[env:adafruit_metro_m4]
platform = atmelsam
board = adafruit_metro_m4
framework = arduino
debug_tool = jlink
upload_protocol = jlink
Default launch.json PIO Debug
results in nominal operation, including tbreak main, and breaking on any pre-existing breakpoints.
Metro M4, USB Power, Atmel-ICE
; platformio.ini
[env:adafruit_metro_m4]
platform = atmelsam
board = adafruit_metro_m4
framework = arduino
debug_tool = atmel-ice
upload_protocol = atmel-ice
PIO Debug
in this configuration results in nothing happening, but if I go over to the debug console, I see
Info : CMSIS-DAP: Interface ready
Info : clock speed 400 kHz
Info : SWD DPIDR 0x2ba01477
Info : at91samd51j19.cpu: hardware has 6 breakpoints, 4 watchpoints
Info : accepting 'gdb' connection from pipe
Error: Couldn't find part corresponding to DID 60060005
Error: auto_probe failed
Error: Connect failed. Consider setting up a gdb-attach event for the target to prepare target for GDB connect, or use 'gdb_memory_map disable'.
Error: attempted 'gdb' connection rejected
Ignoring packet error, continuing...
warning: unrecognized item "timeout" in "qSupported" response
Metro M4, USB Power, Clone CMSIS-DAP
; platformio.ini
[env:adafruit_metro_m4]
platform = atmelsam
board = adafruit_metro_m4
framework = arduino
debug_tool = atmel-ice
upload_protocol = atmel-ice
Identical result to real Atmel-ICE
Metro M4, BlackMagic Probe
Unsupported out of the box.
Trinket M0 Results
Full disclosure, this is actually a Trinket M0 clone, for what that’s worth. There have been minor BSP modifications in Arduino to reconfigure IO names and whatnot. But it’s the same SAMD21E18, etc.
Trinket M0 clone, USB Power, J-Link EDU
; platformio.ini
[env:trinket_m0_clone]
platform = atmelsam
board = trinket_m0_clone
framework = arduino
debug_tool = jlink
upload_protocol = jlink
Default launch.json PIO Debug
results in almost-nominal operation, including tbreak main. Oddly, for whatever reason, this config does NOT break on pre-existing breakpoints in the code. I have to add breakpoints when a debug session is already underway. If it means anything to you, I see the following in the debug console at the end of the start sequence, while the debugger is brokeon on the tbreak main
:
PlatformIO: Initialization completed
PlatformIO: Resume the execution to `debug_init_break = tbreak main`
Reading all registers
Starting target CPU...
Cannot execute this command while the target is running.
Cannot execute this command while the target is running.
Reading all registers
Starting target CPU...
If I then remove and re-add the breakpoint in my own code, I see
Debugger requested to halt target...
...Target halted (PC = 0x0000336C)
Reading all registers
Starting target CPU...
Debugger requested to halt target...
...Target halted (PC = 0x00003344)
Reading all registers
Starting target CPU...
Reading all registers
so it’s almost as if the debugger script for the SAMD21E18 doesn’t add custom breakpoints right off? I don’t really know how debuggers work under the hood - I just know the behavior is unexpected.
Trinket M0 clone, USB Power, Atmel-ICE
; platformio.ini
[env:trinket_m0_clone]
platform = atmelsam
board = trinket_m0_clone
framework = arduino
debug_tool = atmel-ice
upload_protocol = atmel-ice
This actually worked as expected when I ran it just now, for the first time today (maybe something to do with restarting VSCode, which I hadn’t been doing before?) It still didn’t respect pre-existing source breakpoints (just the initial tbreak main).
The second time I ran it, after deleting .pioenvs again, restarting Code, and re-plugging my board and debugger (so, power cycle target AND probe):
Info : clock speed 400 kHz
Error: SWD connect failed
in procedure 'init'
in procedure 'ocd_bouncer'
.pioinit:10: Error in sourced command file:
Remote connection closed
Trinket M0 clone, USB Power, Clone CMSIS-DAP
(Same platformio.ini as above)
Identical behavior to official atmel-ice.
Trinket M0 Clone, USB Power, BlackMagic Probe
; platformio.ini
[env:trinket_m0_clone]
platform = atmelsam
board = trinket_m0_clone
framework = arduino
debug_tool = blackmagic
upload_protocol = blackmagic
debug_port = /dev/cu.usbmodemC3E9D5EB1
Fails with the below:
Reading symbols from /Users/alexw/Documents/PlatformIO/Projects/ECMBlink/.pioenvs/mira_ecm_0-2-0/firmware.elf...
done.
PlatformIO Unified Debugger > http://bit.ly/pio-debug
PlatformIO: Initializing remote target...
Target voltage: 3.3V
SW-DP scan failed!
.pioinit:18: Error in sourced command file:
Attaching to Remote target failed
If I power-cycle the target and try again,
Reading symbols from /Users/alexw/Documents/PlatformIO/Projects/ECMBlink/.pioenvs/mira_ecm_0-2-0/firmware.elf...
done.
PlatformIO Unified Debugger > http://bit.ly/pio-debug
PlatformIO: Initializing remote target...
Target voltage: 3.3V
SW-DP scan failed!
.pioinit:18: Error in sourced command file:
Attaching to Remote target failed
If I manually reset-button the target right before clicking debug,
Reading symbols from /Users/alexw/Documents/PlatformIO/Projects/ECMBlink/.pioenvs/mira_ecm_0-2-0/firmware.elf...
done.
PlatformIO Unified Debugger > http://bit.ly/pio-debug
PlatformIO: Initializing remote target...
Target voltage: 3.3V
Available Targets:
No. Att Driver
1 Atmel SAMD21E18A (rev D)
Temporary breakpoint 1 at 0x337a: file /Users/alexw/.platformio/packages/framework-arduinosam/cores/adafruit/main.cpp, line 35.
Loading section .text, size 0x3740 lma 0x2000
Loading section .ramfunc, size 0x50 lma 0x5740
Loading section .data, size 0x104 lma 0x5790
Start address 0x32b8, load size 14484
Transfer rate: 17 KB/sec, 852 bytes/write.
PlatformIO: Initialization completed
PlatformIO: Resume the execution to `debug_init_break = tbreak main`
Note: automatically using hardware breakpoints for read-only addresses.
but then nothing happens after that.
Notably, manually resetting the target with the button before debug doesn’t seem to have any impact on behavior for the two atmel-ice cases.
What’s going on here and how do I get sub-car-payment debuggers to work?