Flashing RP2350 via SWD Debug Probe (PiProbe / CMSIS-DAP)
๐Ÿ’ฌ Sample prompts Paste any of these into Claude Code to use this skill
Flash via SWD Flash my RP2350 firmware.elf via SWD using the PiProbe
Install probe toolchain Install Pico SDK 2.x and the raspberrypi/openocd fork so I can flash RP2350 via SWD probe
Probe pre-flight Verify my PiProbe + RP2350 SWD connection is up
SWD gdb debug Set up gdb debugging for my RP2350 over the SWD probe
Force BOOTSEL via SWD Force my RP2350 into USB BOOTSEL via the SWD probe (no physical jumper)
Explain probe path Explain the host โ†’ PiProbe โ†’ SWD โ†’ RP2350 path
โšก Install this skill

Paste this into Claude Code (VS Code panel, Adom editor, or terminal) to install:

Search the Adom Wiki for the skill "Flashing RP2350 via SWD Debug Probe (PiProbe / CMSIS-DAP)" (slug: rp2350-flash) at https://wiki-ufypy5dpx93o.adom.cloud/wiki/skills/rp2350-flash and install it into my local ~/.claude/skills/rp2350-flash/ directory. Fetch the skill_source content from the wiki page and save it as SKILL.md. Then confirm it's installed by showing the first 5 lines.
?
What is a skill? Skills are instructions that teach AI assistants like Claude Code how to perform specific tasks. The description below is loaded into the AI as context when you invoke this skill. Well-written skills make the AI significantly more effective. Like Wikipedia, anyone can improve a skill by clicking Edit AI Skill — or have your AI submit an edit on your behalf.

Description

Edit AI Skill

Flashing RP2350 via SWD Debug Probe (PiProbe / CMSIS-DAP)

โš  Scope โ€” SWD debug probe ONLY. This guide applies only when you have a CMSIS-DAP debug probe (PiProbe, Pico Debug Probe, J-Link in CMSIS-DAP mode, etc.) physically wired to the RP2350 target's SWD pins. It does NOT apply to:

  • USB BOOTSEL drag-drop / UF2 file copy
  • OTA / firmware-over-the-air updates
  • Self-bootloader flashing from already-running firmware
  • Any flash path that doesn't go through a CMSIS-DAP probe over SWD

If you don't have a debug probe wired to SWD, this guide is the wrong tool โ€” close the page.

End-to-end guide for building, flashing, and debugging an RP2350 target using a PiProbe (RP2040 running the raspberrypi/debugprobe firmware) or any other CMSIS-DAP probe, over SWD.

Hardware path (scope of this guide)

host (Linux) โ”€โ”€USBโ”€โ”€โ–บ PiProbe (CMSIS-DAPv2, 2e8a:000c)
                         โ”‚
                         โ”‚ SWD: SWCLK + SWDIO + GND (+ optional nRESET)
                         โ–ผ
                      RP2350 target

This guide covers everything from the host down to the SWD signals at the probe's target connector โ€” toolchain, probe firmware, OpenOCD config, flash command, debug session, USB BOOTSEL-via-SWD. It does NOT cover target-board-specific pinouts (which GPIO is the LED, where SWCLK lands on castellations, etc.) โ€” that belongs in the target board's own documentation.

Required downloads at a glance

#WhatSourceInstall method
1apt build depsdistro packagesapt-get install
2arm-none-eabi-gcc 13.xdistro gcc-arm-none-eabiapt-get install
3cmake โ‰ฅ 3.13distro cmakeapt-get install
4Pico SDK 2.xhttps://github.com/raspberrypi/pico-sdkgit clone + submodule init
5picotool 2.xhttps://github.com/raspberrypi/picotoolgit clone + cmake build
6OpenOCD (raspberrypi fork)https://github.com/raspberrypi/openocd, branch sdk-2.0.0git clone + autotools build

All three RPi-hosted repos must be cloned and built from source. Distro openocd will NOT work โ€” see the "Why this exact stack" section.

Why this exact stack

ComponentWhy this version
Pico SDK 2.xRP2350 support landed in SDK 2.0; SDK 1.x will not compile for PICO_PLATFORM=rp2350.
picotool 2.xRequired by SDK 2.x for binary post-processing (UF2 generation, OTP packing).
raspberrypi/openocd forkStock OpenOCD 0.12.0 predates RP2350 and ships no target/rp2350.cfg. Distro-installed OpenOCD will fail with no driver found for target rp2350. The raspberrypi fork (sdk-2.0.0 branch) is the canonical RP2350 OpenOCD.
arm-none-eabi-gcc 13.xToolchain. Older 10.x also compiles fine.
cmake โ‰ฅ 3.13Pico SDK CMake floor.

Install steps โ€” fresh container

Step 1: apt deps

sudo apt-get update -qq
sudo apt-get install -y --no-install-recommends \
  build-essential pkg-config git \
  libusb-1.0-0-dev libhidapi-dev libftdi1-dev \
  libtool autoconf automake texinfo \
  python3 python3-pip \
  gcc-arm-none-eabi cmake

gcc-arm-none-eabi and cmake may already be present from the base image โ€” apt-get install is a no-op when satisfied.

Step 2: Pico SDK 2.x

cd ~
git clone --depth 1 https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk
git submodule update --init --depth 1
echo 'export PICO_SDK_PATH=$HOME/pico-sdk' >> ~/.bashrc
export PICO_SDK_PATH=$HOME/pico-sdk

Verify โ‰ฅ 2.0.0:

grep 'set(PICO_SDK_VERSION_MAJOR' ~/pico-sdk/pico_sdk_version.cmake
# expect:  set(PICO_SDK_VERSION_MAJOR 2)

Step 3: picotool 2.x

cd ~
git clone --depth 1 https://github.com/raspberrypi/picotool.git
cd picotool && mkdir -p build && cd build
cmake ..
make -j"$(nproc)"
sudo make install
picotool version    # โ†’ picotool v2.2.x (Linux, ...)

Step 4: OpenOCD with RP2350 support (raspberrypi fork)

cd ~
git clone --depth 1 --branch sdk-2.0.0 https://github.com/raspberrypi/openocd.git openocd-rp
cd openocd-rp
./bootstrap
./configure --enable-cmsis-dap --disable-werror --prefix=/usr/local
make -j"$(nproc)"
sudo make install
hash -r
openocd --version 2>&1 | head -1   # โ†’ Open On-Chip Debugger 0.12.0+dev-...
ls /usr/local/share/openocd/scripts/target/ | grep rp2350
# expect: rp2350.cfg, rp2350-riscv.cfg, rp2350-rescue.cfg,
#         rp2350-dbgkey-secure.cfg, rp2350-dbgkey-nonsecure.cfg

Installs to /usr/local/bin/openocd, which takes precedence over any stock /usr/bin/openocd.

Building firmware for RP2350

Minimal project:

myapp/
โ”œโ”€โ”€ CMakeLists.txt
โ””โ”€โ”€ myapp.c

CMakeLists.txt:

cmake_minimum_required(VERSION 3.13)
set(PICO_BOARD pico2 CACHE STRING "")
set(PICO_PLATFORM rp2350 CACHE STRING "")
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(myapp C CXX ASM)
pico_sdk_init()
add_executable(myapp myapp.c)
target_link_libraries(myapp pico_stdlib)
pico_add_extra_outputs(myapp)

The two critical settings are:

  • PICO_BOARD=pico2 โ€” board headers for the RP2350A reference design (Pico 2). Override individual GPIO assignments in your code if your board differs.
  • PICO_PLATFORM=rp2350 โ€” tells the SDK to target the RP2350 architecture (vs rp2040).

Build:

mkdir -p build && cd build && cmake .. && make -j"$(nproc)"

Produces myapp.elf (used for SWD flashing) and myapp.uf2 (used for USB BOOTSEL drag-drop, if applicable).

Flashing via SWD โ€” the canonical command

openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000; program firmware.elf verify reset exit"

Successful output ends with:

** Programming Started **
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **

5 MHz SWD is comfortable on clean wiring; the PiProbe + RP2350 can also run at 24 MHz reliably with short SWD leads.

The target executes the new firmware immediately after Resetting Target โ€” no power cycle needed.

Debugging via gdb over the probe

Terminal 1 (leave running):

openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg

OpenOCD listens on :3333 for gdb.

Terminal 2:

arm-none-eabi-gdb firmware.elf \
  -ex 'target extended-remote :3333' \
  -ex 'monitor reset halt'

Then load, b main, c, etc. as normal.

Watching live printf output via ARM semihosting

Semihosting routes the target's printf (and other libc I/O) through the SWD probe back into OpenOCD's stdout โ€” no UART, no USB-on-the-target needed. Useful when SWD is the only physical link to the target.

Firmware side

Link against semihosting stdio and disable the other stdio backends:

target_link_libraries(myapp pico_stdlib)
pico_enable_stdio_semihosting(myapp 1)
pico_enable_stdio_uart(myapp 0)
pico_enable_stdio_usb(myapp 0)

After stdio_init_all(), every printf() becomes a semihosting BKPT 0xAB call that OpenOCD intercepts.

Host side โ€” the canonical "watch the target run" command

openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000" \
  -c "init" \
  -c "reset halt" \
  -c "arm semihosting enable" \
  -c "resume"

Leave it running. Every printf from the firmware streams to stdout. Ctrl-C to stop.

Order matters:

  1. init โ€” attach to the probe and examine cores.
  2. reset halt โ€” reset the target and leave it halted. Plain reset runs after reset, which leaves the cores in an undefined state for the next step.
  3. arm semihosting enable โ€” turn on the BKPT 0xAB intercept while the target is halted.
  4. resume โ€” let the firmware run with semihosting now wired up.

Reordering or skipping halt produces the failure modes in the troubleshooting table below (not halted / context restore failed).

Forcing USB BOOTSEL via SWD (optional)

picotool reboot -u -f works only over USB โ€” it cannot drive a CMSIS-DAP probe in the upstream picotool build. To force a target into BOOTSEL via SWD only, load a tiny SRAM stub that calls the bootrom's reset_usb_boot().

Stub source โ€” ~/tools/force-bootsel/force_bootsel.c:

#include "pico/bootrom.h"
int main(void) {
    reset_usb_boot(0, 0);
    while (1) { __asm volatile("wfi"); }
}

CMakeLists.txt uses pico_set_binary_type(force_bootsel no_flash) so the binary runs entirely from SRAM and doesn't disturb flash.

Wrapper at /usr/local/bin/rp2350-bootsel:

#!/usr/bin/env bash
set -e
STUB=${RP2350_BOOTSEL_STUB:-/home/adom/tools/force-bootsel/build/force_bootsel.elf}
ENTRY=$(arm-none-eabi-readelf -h "$STUB" | awk '/Entry point/ {print $NF}')
exec openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "init; reset halt; load_image $STUB; reg sp 0x20040000; reg pc $ENTRY; resume; sleep 300; exit"

Caveat. BOOTSEL puts the chip into USB MSC mode, but a USB host must be connected to the target's USB Dยฑ lines to see the resulting drive. If the only physical link between host and target is the probe's SWD, BOOTSEL has nowhere to go โ€” flash directly via SWD instead.

Pre-flight: confirm probe + target are alive

Before touching anything else, run:

openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "init; targets; exit"

Expect, in order:

  1. Info : CMSIS-DAP: FW Version = 2.0.0 โ€” PiProbe is talking.
  2. Info : SWD DPIDR 0x4c013477 โ€” SWD link is up and the DAP IDCODE matches RP2350.
  3. Info : [rp2350.dap.core0] Cortex-M33 r1p0 processor detected
  4. Info : [rp2350.dap.core1] Cortex-M33 r1p0 processor detected

If you see the probe (1) but no DPIDR (2): SWD wires are broken/swapped, target is unpowered, or there's no common ground between probe and target.

If you don't see the probe at all (1 missing): lsusb | grep 2e8a:000c โ€” if absent, the probe isn't on USB. Check cables / hub.

Troubleshooting

SymptomCauseFix
error: no driver found for target rp2350Stock OpenOCD 0.12.0 (predates RP2350)Build raspberrypi/openocd fork (Step 4 above)
Error: Could not find a USB deviceProbe missing or /dev/bus/usb permissionslsusb | grep 2e8a:000c; if device node exists but is root-only, fix udev or run with sudo
Error: error submitting USB read: Input/Output Error (flooded repeatedly)A previous openocd process is still holding the probe (often a wedged session from an earlier resume failure)pgrep -af openocd to find the stale PID; kill <PID> that specific process. Do NOT pkill openocd if other openocd sessions are needed elsewhere.
SWD DPIDR 0x00000000Bad SWD wiring, target unpowered, or no common GNDVerify continuity on SWCLK/SWDIO/GND, verify target's +3V3 rail
Error: timed out while waiting for target haltedSWD clock too fast for the cableDrop adapter speed 5000 to adapter speed 1000
Error: target was in unexpected state XTarget stuck in a bad loop / WFIAdd reset halt before program
Error: [rp2350.dap.core0] not halted / context restore failed, aborting resume after arm semihosting enableUsed reset (which runs after reset) instead of reset halt before enabling semihosting and calling resume. The semihosting resume requires a defined halted start state.Reorder commands to init; reset halt; arm semihosting enable; resume. Always halt before enabling semihosting.
resume of a SMP target failed, trying to resume current one followed by both cores halting unexpectedlyRaspberry Pi OpenOCD fork's SMP resume path is fragile on RP2350Either use reset halt; resume (avoids the SMP race), or set USE_CORE 0 via -c "set USE_CORE 0" before the target config to debug only core 0
picotool: No accessible RP-series devices in BOOTSEL mode were foundTarget's USB isn't on the host busDon't use picotool over USB โ€” flash via OpenOCD/SWD instead
Verify fails after flashWrong PICO_BOARD / PICO_PLATFORMConfirm CMake cache has PICO_BOARD=pico2 and PICO_PLATFORM=rp2350; nuke build/ and rebuild
VECTRESET is not supported on this Cortex-M core, using SYSRESETREQ insteadCosmeticIgnore โ€” RP2350 cores don't implement VECTRESET; SYSRESETREQ is the correct path

File map (after a full install)

PathPurpose
~/pico-sdk/Pico SDK 2.x source (download #4)
~/picotool/picotool source (download #5)
~/openocd-rp/OpenOCD raspberrypi fork source (download #6)
~/tools/force-bootsel/BOOTSEL-trigger SRAM stub source
/usr/local/bin/picotoolInstalled binary, picotool 2.x
/usr/local/bin/openocdInstalled binary, raspberrypi fork (overlays any stock)
/usr/local/bin/rp2350-bootselSWD โ†’ BOOTSEL wrapper
/usr/local/share/openocd/scripts/target/rp2350.cfgOpenOCD target config
/usr/local/share/openocd/scripts/interface/cmsis-dap.cfgOpenOCD interface config

Quick command reference

# Pre-flight
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "init; targets; exit"

# Flash an .elf via SWD
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000; program firmware.elf verify reset exit"

# Halt + reset only (no flash)
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "init; reset halt; exit"

# Start gdb-server (terminal 1)
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg

# Attach gdb (terminal 2)
arm-none-eabi-gdb firmware.elf -ex 'target extended-remote :3333'

# Stream printf via ARM semihosting through the probe (no UART/USB needed)
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000" -c "init" -c "reset halt" \
  -c "arm semihosting enable" -c "resume"

# Probe stuck after a wedged session? Kill the SPECIFIC stale openocd PID
pgrep -af openocd            # find the PID
kill <PID>                   # only that PID โ€” never `pkill openocd`

# Force BOOTSEL via SWD (only if target USB is wired to a host)
rp2350-bootsel

# Build a Pico SDK project for RP2350
cd myapp && mkdir -p build && cd build && cmake .. && make -j$(nproc)

Skill Source

Edit AI Skill
---
name: rp2350-flash
description: >
  SWD-only flashing/debugging of RP2350 targets via a CMSIS-DAP debug
  probe (PiProbe, Pico Debug Probe, J-Link in CMSIS-DAP mode).
  REQUIRES a probe physically wired to the target's SWD pins. Does
  NOT cover USB BOOTSEL drag-drop, UF2 install, OTA, or any non-probe
  flashing path. Covers the install (Pico SDK 2.x, picotool 2.x,
  raspberrypi/openocd fork), the canonical openocd flash command, the
  rp2350-bootsel SRAM-stub wrapper, and probe-side troubleshooting.
  Scope: host down to the probe's SWD pins โ€” not target-board pinouts.
  Trigger words: flash rp2350 via swd, swd flash rp2350, swd program
  rp2350, piprobe flash, pico debug probe rp2350, cmsis-dap probe
  rp2350, openocd rp2350, rp2350 swd, debug probe rp2350, rp2350 gdb,
  reset_usb_boot via swd, force bootsel via swd, rp2350-bootsel,
  pico sdk rp2350 swd.
---

# rp2350-flash โ€” flash RP2350 over SWD via a CMSIS-DAP debug probe

> โš  **Scope โ€” SWD debug probe ONLY.** Use this skill *only* when the user has a CMSIS-DAP debug probe (PiProbe, Pico Debug Probe, J-Link in CMSIS-DAP mode) **physically wired to the RP2350 target's SWD pins**. Do **NOT** invoke this skill for:
>
> - USB BOOTSEL drag-drop / UF2 file copy
> - OTA / firmware-over-the-air updates
> - Self-bootloader flashing from running firmware
> - Any flash path that doesn't go through a CMSIS-DAP probe over SWD

Full setup + troubleshooting reference: **[flashing-rp2350.md](./flashing-rp2350.md)** (also published as the body of `skills/rp2350-flash` on the Adom Wiki).

## When to use this skill

- User has a CMSIS-DAP probe wired to a target's SWD pins **and** wants to flash an `.elf` onto the RP2350.
- User wants to build firmware with the Pico SDK for `PICO_PLATFORM=rp2350`, then flash via the probe.
- User wants to debug RP2350 via gdb-over-openocd, with the probe as the SWD bridge.
- User wants to force a target into USB BOOTSEL **via SWD** (the `rp2350-bootsel` wrapper) โ€” only relevant when the target's USB lines are also wired to a host.
- User mentions "openocd rp2350", "piprobe flash", "pico debug probe", "swd flash", "swd program rp2350", etc.

## When NOT to use this skill

- User wants to drag-and-drop a `.uf2` onto the target's BOOTSEL drive over **USB** (no probe in the loop).
- User wants to update firmware over WiFi / BLE / OTA.
- User is flashing a running RP2350 from its own firmware (self-bootloader / dual-bank).
- There is no debug probe in the topology.

**Scope:** host โ†’ USB โ†’ probe โ†’ SWD pins. Target-board specifics (which GPIO is the LED, where SWCLK lands on castellations, USB-Dยฑ wiring) are out of scope โ€” refer to the target board's own docs.

## Required downloads (the install is non-optional)

| # | What | Source | How |
|---|------|--------|-----|
| 1 | apt deps | distro | `apt-get install` |
| 2 | arm-none-eabi-gcc | distro `gcc-arm-none-eabi` | `apt-get install` |
| 3 | cmake | distro `cmake` | `apt-get install` |
| 4 | **Pico SDK 2.x** | https://github.com/raspberrypi/pico-sdk | `git clone` + submodule init |
| 5 | **picotool 2.x** | https://github.com/raspberrypi/picotool | `git clone` + cmake build |
| 6 | **OpenOCD (raspberrypi fork)** | https://github.com/raspberrypi/openocd, branch `sdk-2.0.0` | `git clone` + autotools build |

Stock distro OpenOCD 0.12.0 **does not work** โ€” it predates RP2350 and ships no target config. This is the #1 cause of `no driver found for target rp2350`. The full install takes ~10 min on a fresh container.

Step-by-step install commands: [flashing-rp2350.md ยง Install steps](./flashing-rp2350.md#install-steps--fresh-container).

## Pre-flight check โ€” always run this first

Before doing anything, confirm probe + target are alive:

```bash
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "init; targets; exit"
```

Expected: `CMSIS-DAP: FW Version = 2.0.0`, `SWD DPIDR 0x4c013477`, and both `rp2350.dap.core0` + `core1` as Cortex-M33 r1p0. If you see those, the toolchain is installed and the wiring is good โ€” skip to "Flash via SWD" below.

Failure modes:
- `no driver found for target rp2350` โ†’ stock OpenOCD, install the raspberrypi fork (download #6).
- `Could not find a USB device` โ†’ probe isn't on USB. `lsusb | grep 2e8a:000c`. Fix the cable.
- `SWD DPIDR 0x00000000` โ†’ target unpowered, SWD wires bad/swapped, or no common ground between probe and target.

## Build firmware for RP2350

`CMakeLists.txt` must set:

```cmake
cmake_minimum_required(VERSION 3.13)
set(PICO_BOARD pico2 CACHE STRING "")
set(PICO_PLATFORM rp2350 CACHE STRING "")
include($ENV{PICO_SDK_PATH}/external/pico_sdk_import.cmake)
project(myapp C CXX ASM)
pico_sdk_init()
add_executable(myapp myapp.c)
target_link_libraries(myapp pico_stdlib)
pico_add_extra_outputs(myapp)
```

Build:

```bash
mkdir -p build && cd build && cmake .. && make -j$(nproc)
```

Produces `myapp.elf` (for SWD flash) and `myapp.uf2` (for USB BOOTSEL drag-drop, if applicable).

## Flash via SWD โ€” the recommended path

```bash
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000; program firmware.elf verify reset exit"
```

Successful run ends with `** Verified OK **` and `** Resetting Target **`. The new firmware starts running immediately.

**Don't bother with BOOTSEL when you have a probe.** SWD flashes work even if the target's USB pins aren't wired anywhere.

## Force USB BOOTSEL via SWD (rare path)

`picotool reboot -u -f` only works when the target is already on USB โ€” it cannot drive a CMSIS-DAP probe in the upstream build. If you need to force BOOTSEL via SWD only:

```bash
rp2350-bootsel
```

This wraps OpenOCD + a tiny SRAM stub (`~/tools/force-bootsel/`) that calls the bootrom's `reset_usb_boot(0, 0)`.

**Caveat**: BOOTSEL is only useful if the target's USB Dยฑ lines are physically wired to a USB host. In a probe-only setup (SWD between probe and target, no USB cable on the target), BOOTSEL puts the chip into MSC mode but there's no host to see the drive. **Use the SWD flash path instead** โ€” that works regardless.

## Debug via gdb over the probe

Terminal 1 (leave running):

```bash
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg
```

Terminal 2:

```bash
arm-none-eabi-gdb firmware.elf -ex 'target extended-remote :3333'
```

## Stream `printf` via ARM semihosting through the probe

When the target has no UART/USB wired, route `printf` through SWD via semihosting:

Firmware CMake:
```cmake
pico_enable_stdio_semihosting(myapp 1)
pico_enable_stdio_uart(myapp 0)
pico_enable_stdio_usb(myapp 0)
```

Host command (leave it running):
```bash
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000" -c "init" -c "reset halt" \
  -c "arm semihosting enable" -c "resume"
```

**Order matters:** `init โ†’ reset halt โ†’ arm semihosting enable โ†’ resume`. Plain `reset` (without `halt`) leaves the target running, then `arm semihosting enable` and `resume` will fail with `not halted` / `context restore failed`.

## Common failure modes (one-liner triage)

| Error | Likely cause |
|-------|--------------|
| `no driver found for target rp2350` | Stock OpenOCD; install raspberrypi fork (download #6) |
| `Could not find a USB device` | PiProbe missing from `lsusb`; fix cabling |
| `error submitting USB read: Input/Output Error` (flood) | Another openocd is holding the probe โ€” `pgrep -af openocd` then `kill <PID>` that specific PID (never `pkill openocd`) |
| `SWD DPIDR 0x00000000` | Target unpowered, SWD wires bad, or no common GND |
| `timed out while waiting for target halted` | SWD clock too fast โ€” drop `adapter speed` to 1000 |
| `not halted` / `context restore failed, aborting resume` (after `arm semihosting enable`) | Used `reset` instead of `reset halt` โ€” reorder to `init; reset halt; arm semihosting enable; resume` |
| `resume of a SMP target failed` | RP2350 fork's SMP resume is fragile โ€” use `reset halt; resume` or `set USE_CORE 0` |
| `picotool: No accessible RP-series devices in BOOTSEL` | Target USB not on host bus โ€” use OpenOCD/SWD instead |
| Verify fails after flash | Wrong `PICO_BOARD` / `PICO_PLATFORM`; nuke `build/` and rebuild |
| `VECTRESET is not supported... using SYSRESETREQ` | Cosmetic warning, ignore |

Full troubleshooting table: [flashing-rp2350.md ยง Troubleshooting](./flashing-rp2350.md#troubleshooting).

## Quick command reference

```bash
# Pre-flight
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg -c "init; targets; exit"

# Flash an .elf via SWD (canonical)
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000; program firmware.elf verify reset exit"

# Start a gdb-server (terminal 1)
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg

# Attach gdb (terminal 2)
arm-none-eabi-gdb firmware.elf -ex 'target extended-remote :3333'

# Stream printf via ARM semihosting through the probe (no UART/USB needed)
openocd -f interface/cmsis-dap.cfg -f target/rp2350.cfg \
  -c "adapter speed 5000" -c "init" -c "reset halt" \
  -c "arm semihosting enable" -c "resume"

# Probe stuck after a wedged session? Kill the SPECIFIC stale openocd PID
pgrep -af openocd            # find the PID
kill <PID>                   # only that PID โ€” never `pkill openocd`

# Force BOOTSEL via SWD (only if target USB is wired to host)
rp2350-bootsel

# Build a Pico SDK project for RP2350
cd myapp && mkdir -p build && cd build && cmake .. && make -j$(nproc)
```

Sub-Skills
?
What are Sub-Skills?

Sub-skills are community-contributed AI skill extensions for this component. They teach AI assistants about specific tools, configurators, or workflows.

Examples:

  • A manufacturer’s configuration tool for a motor controller
  • A community-written design guide for an amplifier circuit
  • An automated test/validation script for a sensor module

How to add one: Click Add Sub-Skill, provide the URL to your skill and a brief description. Submissions are reviewed by the Adom team before going live.

No sub-skills yet. Be the first to contribute one!

Recent activity

3 commits
  • โฌ†
    Asset uploaded Caleb 15 hours ago
    Upload hero diagram showing the host โ†’ PiProbe โ†’ SWD โ†’ RP2350 path with prominent SWD-debug-probe-only scope warning in orange
  • โœŽ
    Edit v1.0.0 Caleb 15 hours ago
    Set discovery_triggers (SWD-explicit phrases only) and discovery_pitch with prominent scope-limitation language so the skill is not invoked for USB BOOTSEL or non-probe flash paths
  • ๐Ÿท
    Release v1.0.0 Caleb 15 hours ago
    Initial publish: SWD-only RP2350 flash workflow via PiProbe / CMSIS-DAP. Covers Pico SDK 2.x, picotool 2.x, raspberrypi/openocd fork install, canonical openocd flash command, rp2350-bootsel SRAM-stub wrapper for forcing USB BOOTSEL via SWD, gdb-over-openocd debug, and full probe-side troubleshooting table.
2 revisions · Updated 2026-05-27 23:04:00