Pressing BOOTSEL and re-plugging for every build gets old quickly, and printf debugging only goes so far. The Debug Probe solves both: an Arm SWD interface (CMSIS-DAP) plus a USB-UART bridge.
Wiring
- SWD: connect the probe's SWD cable to the Pico's three-pin debug connector (SWDIO, GND, SWCLK). That connector has no power pin: power the Pico separately via USB or VSYS.
- UART: connect the probe's UART cable to the Pico's default UART0 (GP0 = TX, GP1 = RX) and GND, then open the serial port at 115200 baud.
Flash without BOOTSEL
sudo openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg \
-c "adapter speed 5000" -c "program blink.elf verify reset exit"
OpenOCD loads the ELF, not the UF2. Use the target configuration that matches your chip (the documentation's example shows rp2040.cfg); Raspberry Pi maintains an OpenOCD fork for the Pico SDK.
Debug with GDB
- Build as Debug:
cmake -DCMAKE_BUILD_TYPE=Debug ... - Start the OpenOCD server (same command without
program ...). - In a second terminal (
gdb-multiarchon Linux PCs,arm-none-eabi-gdbon macOS/Windows):
gdb blink.elf
(gdb) target remote localhost:3333
(gdb) monitor reset init
(gdb) continue
The Pico VS Code extension sets up OpenOCD and GDB for you and is Raspberry Pi's recommended way to debug.
No Debug Probe? Use a second Pico
The debugprobe firmware also runs on a Pico (cmake -DDEBUG_ON_PICO=ON .., output debugprobe_on_pico.uf2) or a Pico 2 (-DDEBUG_ON_PICO=1 -DPICO_BOARD=pico2, output debugprobe_on_pico2.uf2).
Two useful details
- AutoBaud: set the probe's USB serial port to the custom baud rate 9728 and it detects the target's UART baud rate automatically.
- Updating the probe: its firmware is itself a UF2 (
debugprobe.uf2), installed with BOOTSEL like any Pico program.