Pico 2 as a Debug Probe: Flash Official debugprobe_on_pico2.uf2, Then Debug Another Pico Over SWD

8 views 0 likes 0 comments 27 minutesOriginalTutorials

Turn a spare Raspberry Pi Pico 2 into a CMSIS-DAP SWD + UART probe with the official raspberrypi/debugprobe firmware: prebuilt debugprobe_on_pico2.uf2 (v2.3.1), GP2 SWCLK / GP3 SWDIO / GP4-GP5 UART from board_pico_config.h, then OpenOCD with cmsis-dap.cfg + rp2350.cfg.

#Raspberry Pi #Pico 2 #RP2350 #debugprobe #SWD #CMSIS-DAP #OpenOCD #GDB #Embedded #Affiliate
Pico 2 as a Debug Probe: Flash Official debugprobe_on_pico2.uf2, Then Debug Another Pico Over SWD

Pico 2 as a Debug Probe: Flash Official debugprobe_on_pico2.uf2, Then Debug Another Pico Over SWD

Once a Pico project grows past "blink," the BOOTSEL-unplug-drag-UF2 loop gets old fast, and printf debugging over USB stops being enough. What you want is SWD: load an ELF, set breakpoints, single-step, and keep a UART console open, all from one USB cable.

Raspberry Pi sells a dedicated Debug Probe for exactly this. But its firmware is open source, and the same repository builds a version that runs on a plain Raspberry Pi Pico 2. If you have a spare Pico 2, or can get one for about the price of lunch, you can turn it into a CMSIS-DAP probe in a couple of minutes.

Everything below comes from open-source, Raspberry Pi–maintained sources:

I checked these against copies fetched for this write-up: the README, board_pico_config.h, board_config.h, CMakeLists.txt, the v2.3.1 release asset list, the docs page, and OpenOCD's rp2350.cfg. I did not flash hardware for this post. Treat it as source-verified, not as a flash log.

Disclosure: further down I link one eBay listing for a Pico 2. That link is an eBay affiliate link (customid=blog01). If you buy through it I may earn a commission at no extra cost to you. Check the listing yourself before you pay.

Why a Pico 2 and not the "real" Debug Probe?

The official Debug Probe is the nicer product. It comes in a case, ships with three JST-SH cables, and the docs are written around it. While I was preparing this post, though, I couldn't readily find it from US eBay sellers. A bare Pico 2 was easy to find and cheap, and the firmware is officially built for it. You lose the enclosure and cables. You keep the protocol (CMSIS-DAP), the SWD + UART bridge, and OpenOCD compatibility.

The three facts that make this work

1. There is a prebuilt debugprobe_on_pico2.uf2. You don't need to compile anything. The debugprobe-v2.3.1 release (published May 29, 2026) ships six assets:

复制代码
debugprobe.uf2 / .elf             # the Debug Probe accessory itself
debugprobe_on_pico.uf2 / .elf     # Pico (RP2040)
debugprobe_on_pico2.uf2 / .elf    # Pico 2 (RP2350)

The Raspberry Pi docs also say the latest Debug Probe firmware is version 2.3.1, which matches the release.

2. Pico and Pico 2 share one pin map. include/board_config.h picks the header by board:

c 复制代码
#if defined(RASPBERRYPI_DEBUG_PROBE)
#include "board_debug_probe_config.h"
#elif defined(RASPBERRYPI_PICO) || defined(RASPBERRYPI_PICO2)
#include "board_pico_config.h"

and include/board_pico_config.h defines:

c 复制代码
#define PROBE_PIN_OFFSET 2
#define PROBE_PIN_SWCLK (PROBE_PIN_OFFSET + 0) // 2
#define PROBE_PIN_SWDIO (PROBE_PIN_OFFSET + 1) // 3
// Target reset config
#define PROBE_PIN_RESET 1

// UART config
#define PROBE_UART_TX 4
#define PROBE_UART_RX 5
#define PROBE_UART_INTERFACE uart1
#define PROBE_UART_BAUDRATE 115200

#define PROBE_USB_CONNECTED_LED 25

So on the probe board: GP2 = SWCLK, GP3 = SWDIO, GP4 = UART TX, GP5 = UART RX, GP1 = target reset, and the on-board LED (GP25) shows USB status.

3. The output name comes from PICO_BOARD. In the repo's CMakeLists.txt:

cmake 复制代码
set(PICO_BOARD debug_probe CACHE STRING "Board type")
...
if (NOT PICO_BOARD STREQUAL "debug_probe")
    set_target_properties(debugprobe PROPERTIES
        OUTPUT_NAME "debugprobe_on_${PICO_BOARD}"
    )
endif ()

That is why -DPICO_BOARD=pico2 produces debugprobe_on_pico2.uf2. It also means a plain cmake .. builds firmware for the accessory, not for your Pico 2.

The board I'd point you to

If you need a Pico 2 to sacrifice as a probe, this is the listing I checked while writing: Raspberry Pi Pico 2 Microcontroller Board RP2350 (SC1631) on eBay (affiliate link).

When I looked on Nov 11, 2026, the title was Raspberry Pi Pico 2 Microcontroller Board RP2350 Dual-Core 150 MHz SC1631, condition New, Buy It Now at US $11.99 with free economy shipping from Sylmar, California. The seller (aaawavecom) was Top Rated Plus with about 99.7% positive feedback from roughly 32,858 ratings. The MPN is SC1631, which as far as I can tell is the board without pre-soldered headers, so check the listing photos and plan to solder pins on GP1–GP5 and GND (or the debug pads on the target). Prices and stock change, so treat these numbers as a snapshot.

You need two boards in total: the one that becomes the probe, and the target you want to debug. The target can be a Pico or a Pico 2.

1) Flash the probe firmware onto the Pico 2

  1. Download debugprobe_on_pico2.uf2 from the v2.3.1 release. The Pico 2 file is debugprobe_on_pico2.uf2, not debugprobe.uf2 (that one is for the accessory) and not debugprobe_on_pico.uf2 (that one is RP2040).
  2. Hold BOOTSEL, plug the Pico 2 into USB, then release. The docs say the volume is called RP2350 for Pico 2 (RPI-RP2 for the original Pico).
  3. Copy the UF2 onto the volume. It dismounts and reboots on its own.
bash 复制代码
## Linux example — adjust mount path for your OS
cp debugprobe_on_pico2.uf2 /media/$USER/RP2350/

After the reboot, the board should show up as a CMSIS-DAP device with a CDC serial port. The header's product string is "Debugprobe on Pico (CMSIS-DAP)". That string is shared by both Pico builds, so don't be surprised that it doesn't say "Pico 2."

Building it yourself (optional)

If you want to change pins or study the code, the README's Pico 2 recipe is:

bash 复制代码
git clone https://github.com/raspberrypi/debugprobe
cd debugprobe
git submodule sync
git submodule update --init --recursive
mkdir build-pico2
cd build-pico2
cmake -DPICO_BOARD=pico2 ../
make

The README calls out two gotchas. PICO_SDK_PATH must point to pico-sdk 2.3.0 or newer. And if you already built for another board in an existing clone, you must completely regenerate the build directory (or use a new one) and sync/update submodules. Reusing an old build/ is how you end up with the wrong firmware.

2) Wire probe → target

GPIO numbers are from board_pico_config.h (probe side) and the docs' default UART0 pins (target side):

Probe Pico 2 Signal Target Pico / Pico 2
GND ground GND (connect this first)
GP2 SWCLK SWCLK (debug connector)
GP3 SWDIO SWDIO (debug connector)
GP4 probe UART TX GP1 (UART0 RX)
GP5 probe UART RX GP0 (UART0 TX)
GP1 target reset (optional) target reset line

Notes:

  • TX goes to RX and RX goes to TX. The probe uses uart1 on GP4/GP5 at a default 115200 baud. The target side here is the Pico's default UART0 (GP0 TX on physical pin 1, GP1 RX on pin 2, per the docs).
  • SWCLK/SWDIO on the target are the three-pin debug connector (SWCLK, GND, SWDIO), not regular GPIOs. The docs' note for non-H boards is to solder a header onto those three pads.
  • The docs warn that if the two boards are powered separately, you should connect GND before any signal line. Everything here is 3.3 V logic. Powering each board from its own USB port is the simplest way to start.
  • PROBE_PIN_RESET (GP1) is optional. The firmware sets it up with a pull-up, but nothing requires you to wire it. I'd leave it off for a first connection test.

3) Talk to it with OpenOCD

The Raspberry Pi docs give this exact command for loading a binary through the probe:

bash 复制代码
sudo openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg \
  -c "adapter speed 5000" -c "program blink.elf verify reset exit"

That example uses target/rp2040.cfg, which matches an RP2040 target (original Pico). For a Pico 2 target, OpenOCD has a matching target/rp2350.cfg (in upstream OpenOCD master and in Raspberry Pi's fork), so the equivalent is:

bash 复制代码
sudo openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000" -c "program blink.elf verify reset exit"

Two things trip people up:

  • It's the ELF, not the UF2. The docs say so explicitly: SWD upload uses the .elf file.
  • Your OpenOCD may be too old for RP2350. The last tagged upstream release, v0.12.0, includes rp2040.cfg but not rp2350.cfg. An older distro OpenOCD may give you "can't find target/rp2350.cfg." The docs recommend the Raspberry Pi Pico VS Code extension, which bundles OpenOCD, the Arm toolchain, and GDB. Otherwise, build Raspberry Pi's fork as described in the Getting Started guide.

Also note that the interface config is interface/cmsis-dap.cfg whichever chip the probe uses. OpenOCD only sees a CMSIS-DAP adapter.

4) Debug session with GDB

Build the target firmware as Debug (cmake -DCMAKE_BUILD_TYPE=Debug .., per the docs). Start OpenOCD in server mode:

bash 复制代码
sudo openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "adapter speed 5000"
## (target/rp2040.cfg for an original Pico target)

Then in a second terminal:

bash 复制代码
gdb-multiarch blink.elf      # Linux; arm-none-eabi-gdb on macOS/Windows
(gdb) target remote localhost:3333
(gdb) monitor reset init
(gdb) continue

That localhost:3333 / monitor reset init / continue sequence is the docs' standalone flow. The docs name gdb-multiarch for Linux and arm-none-eabi-gdb for macOS and Windows.

5) The UART side (and AutoBaud)

The probe also exposes a USB CDC serial port that bridges to its GP4/GP5 UART. The docs open it like this:

bash 复制代码
minicom -b 115200 -o -D /dev/ttyACM0

(/dev/ttyACM0 on a Raspberry Pi. On macOS it shows up as something like /dev/cu.usbmodemXXXX.)

If your target isn't at 115200, the firmware has an AutoBaud mode. Set the CDC port to the custom rate 9728 (0x2600) (MAGIC_BAUD in src/autobaud.h) and the probe detects the target's baud rate as data arrives. Setting any other rate turns AutoBaud off. The README warns that some Linux serial tools can't set custom baud rates. PuTTY on Windows, or any terminal that accepts arbitrary rates, will work.

Troubleshooting in one table

Symptom Most likely cause Fix
Board doesn't enumerate as CMSIS-DAP after flashing Flashed debugprobe.uf2 or debugprobe_on_pico.uf2 onto a Pico 2 Re-enter BOOTSEL (RP2350 volume) and copy debugprobe_on_pico2.uf2
Self-built firmware behaves like the wrong board Ran plain cmake .. (defaults to debug_probe) or reused an old build dir Fresh build-pico2, git submodule sync + update --init --recursive, -DPICO_BOARD=pico2
can't find target/rp2350.cfg OpenOCD 0.12.0 or older distro build Use the VS Code extension's OpenOCD or Raspberry Pi's fork
OpenOCD connects to the probe but not the target SWCLK/SWDIO swapped, no common GND, or wrong target cfg GP2→SWCLK, GP3→SWDIO, GND first; rp2040.cfg vs rp2350.cfg must match the target
program fails on a .uf2 SWD loads ELF Pass the .elf
UART is silent or garbage TX/RX not crossed, or baud mismatch GP4→target RX, GP5→target TX; try 115200 or AutoBaud 9728
Breakpoints/stepping make no sense Release build Rebuild with -DCMAKE_BUILD_TYPE=Debug

Takeaway

You don't need the boxed Debug Probe to get SWD on a Pico. The official raspberrypi/debugprobe repo ships a prebuilt debugprobe_on_pico2.uf2 (v2.3.1 at time of writing). On a Pico 2 the pins are GP2 SWCLK, GP3 SWDIO, GP4/GP5 UART, straight from board_pico_config.h. After that it's normal OpenOCD: interface/cmsis-dap.cfg, plus the target config that matches the chip you're debugging, which is rp2350.cfg for a Pico 2 target. If you're still on the "first blink" stage, my earlier Pico 2 W blink walkthrough is the step before this one.

Affiliate disclosure: the eBay link above is an affiliate link (customid=blog01). Prices, stock and seller details change; I describe the listing as I saw it on Nov 11, 2026.

Last Updated:2026-11-11 10:07:54

Comments (0)

Post Comment

Loading...
0/500

No comments yet, be the first to comment!