本教學說明如何更新 Raspberry Pi Debug Probe 韌體,並使用它來燒錄與除錯 Raspberry Pi Pico / Pico 2(RP2040 / RP2350)。
參考資料:
📚 深入文件:OpenOCD 深入說明 | GDB 深入說明 | 常用指令速查表
- 什麼是 Debug Probe
- 硬體介紹與接線
- 更新 Debug Probe 韌體
- 安裝除錯工具(OpenOCD / GDB / picotool)
- 用 Debug Probe 燒錄程式
- 用 OpenOCD + GDB 進行除錯
- 實測驗證 SWD 連線
- 在 VS Code 中除錯
- 使用內建 UART 序列埠
- 常見問題 FAQ
Raspberry Pi Debug Probe 是一顆基於 RP2040 的官方除錯器,內含 debugprobe 韌體,對外提供兩大功能:
| 功能 | 說明 | 對應介面 |
|---|---|---|
| CMSIS-DAP 除錯器 | 透過 SWD(Serial Wire Debug)燒錄與除錯目標 MCU | USB Vendor 介面 |
| USB-to-UART 橋接器 | 把目標板的 UART 訊號轉成電腦上的序列埠 | USB CDC(/dev/ttyACM0) |
它在電腦上會辨識為 Raspberry Pi Debug Probe (CMSIS-DAP),
USB 識別碼為 2e8a:000c。
Debug Probe 出廠會附兩條 3-pin JST-SH 連接線:
- 橘色頭(D / SWD):接目標板的
SWCLK/SWDIO/GND(除錯用) - 黃色頭(U / UART):接目標板的
TX/RX/GND(序列埠用)
Debug Probe 外殼上有三個接頭:
┌──────────────────────────────┐
│ Debug Probe │
│ │
[USB]─┤ ● (D) (U) │
│ USB-C 橘框 黃框 │
└──────────────────────────────┘
│ │ │
接電腦 SWD 除錯 UART 序列
| 接頭 | 標示 | 附的線 | 用途 |
|---|---|---|---|
| USB-C | — | USB 線 | 接電腦供電+資料 |
| D(左) | 橘色框 | 三色排線(橘框) | SWD 除錯(燒錄 / 下中斷點) |
| U(右) | 黃色框 | 三色排線(黃框) | UART 序列埠(printf 輸出) |
附的 3-pin JST-SH 排線,接頭上通常標有 箭頭方向與顏色; 下面用「訊號名稱」對照,實際以你手上排線的絲印為準。
Debug Probe D 埠 ↔ Pico target 底部 DEBUG 排針
| Debug Probe D 埠 | 排線顏色 | → | Pico target(DEBUG 排針) |
|---|---|---|---|
SWCLK |
橘 | → | SWCLK |
GND |
黑 | → | GND |
SWDIO |
黃 | → | SWDIO |
Pico / Pico 2 底部有一排 3-pin 除錯排針,絲印由左到右為:
Pico 底部 DEBUG 排針(三個孔)
┌─────┬─────┬─────┐
│SWCLK│ GND │SWDIO│
└──┬──┴──┬──┴──┬──┘
│ │ │
橘 黑 黃 ← 來自 Debug Probe 的 D 埠
✅ SWD 是一對一直連(同名接同名):
SWCLK→SWCLK、GND→GND、SWDIO→SWDIO。
⚠️ 重點:UART 必須「TX↔RX 交叉」接,不是同名直連!
| Debug Probe U 埠 | 排線 | → | Pico target |
|---|---|---|---|
TX |
橘 | → | GP1(UART0 RX,實體第 2 腳) |
RX |
黃 | → | GP0(UART0 TX,實體第 1 腳) |
GND |
黑 | → | GND(例如實體第 3 腳) |
Debug Probe (U) Pico target
┌──────────┐ ┌──────────┐
│ TX ────┼────────────────┼──> GP1 (RX,pin 2)
│ RX <───┼────────────────┼──── GP0 (TX,pin 1)
│ GND ───┼────────────────┼──── GND (pin 3)
└──────────┘ └──────────┘
Probe 的 TX 接目標的 RX,Probe 的 RX 接目標的 TX(交叉)
一次接好 SWD+UART(除錯與序列埠同時使用):
| Debug Probe | 埠 | 排線 | Pico target 腳位 |
|---|---|---|---|
| SWCLK | D | 橘 | 底部 DEBUG:SWCLK |
| GND | D | 黑 | 底部 DEBUG:GND |
| SWDIO | D | 黃 | 底部 DEBUG:SWDIO |
| TX | U | 橘 | GP1 / UART0 RX(pin 2) |
| RX | U | 黃 | GP0 / UART0 TX(pin 1) |
| GND | U | 黑 | GND(pin 3) |
💡 若只是要燒錄/下中斷點除錯,接 D 埠(SWD) 就夠了; 只有需要看
printf序列輸出時才要另外接 U 埠(UART)。
🔌 目標板(Pico)仍需自己的電源:可用另一條 USB 線供電, 或視情況從 Debug Probe/其他 3V3 來源供電(本教學不從 Probe 供電)。
本節就是把 Debug Probe 內建的 debugprobe 韌體升級到最新版 (撰寫時最新為 debugprobe-v2.3.1)。
新版韌體修正了穩定度、支援 RP2350(Pico 2)目標、並提升 SWD 速度。 若你的 OpenOCD 連線常常斷線或速度慢,更新韌體通常能改善。
到 debugprobe Releases 下載對應檔案:
| 你的硬體 | 要下載的檔案 |
|---|---|
| 官方 Debug Probe(塑膠外殼那顆) | debugprobe.uf2 |
| 用一顆 Pico 當除錯器 | debugprobe_on_pico.uf2 |
| 用一顆 Pico 2 當除錯器 | debugprobe_on_pico2.uf2 |
指令下載(本專案已幫你下載並放在 firmware/):
curl -L -o debugprobe.uf2 \
https://github.com/raspberrypi/debugprobe/releases/download/debugprobe-v2.3.1/debugprobe.uf2Debug Probe 沒有 picotool 的 reset 介面,無法用軟體指令重開進 BOOTSEL, 必須用實體 BOOTSEL 按鈕。
- 把 Debug Probe 的 USB 線拔掉。
- 按住 Debug Probe 上的 BOOTSEL 按鈕(外殼上的小孔/小按鈕)。
- 一邊按住,一邊把 USB 線插回電腦。
- 放開按鈕。此時電腦會出現一個名為
RPI-RP2的隨身碟。
驗證是否進入 BOOTSEL:
lsusb | grep 2e8a
# 進入 BOOTSEL 前: 2e8a:000c Raspberry Pi Debug Probe (CMSIS-DAP)
# 進入 BOOTSEL 後: 2e8a:0003 Raspberry Pi RP2 Boot ← 出現這個就對了方法 A:直接把 UF2 拖進 RPI-RP2 隨身碟(最簡單)
把 debugprobe.uf2 複製到 RPI-RP2 磁碟即可,複製完裝置會自動重開,
回到 CMSIS-DAP 模式。
cp firmware/debugprobe-v2.3.1.uf2 /run/media/$USER/RPI-RP2/
sync方法 B:用 picotool 燒錄
sudo picotool load -x firmware/debugprobe-v2.3.1.uf2
# -x 代表燒完自動重開執行本專案提供的自動燒錄腳本(會等你按 BOOTSEL 插入後自動複製):
./firmware/flash-probe.sh重新插上(正常模式)後:
lsusb | grep 2e8a
# 應該又變回: 2e8a:000c Raspberry Pi Debug Probe (CMSIS-DAP)
# 查看版本(需要在 BOOTSEL 模式下才讀得到完整資訊)
sudo picotool info -a以 Fedora / RHEL 系 為例(本機環境):
# OpenOCD(Raspberry Pi 版含 rp2040/rp2350 支援)與 GDB
sudo dnf install openocd gdb
# picotool(也可用 Homebrew)
brew install picotoolDebian / Ubuntu:
sudo apt install openocd gdb-multiarch建議使用 Raspberry Pi 官方版 OpenOCD(
raspberrypi/openocd分支), 內含rp2040.cfg、rp2350.cfg與cmsis-dap.cfg,對 Debug Probe 支援最完整。
不設定的話,/dev/bus/usb/... 的探棒節點是 root:root 0664(一般使用者只能讀不能寫),
OpenOCD 會出現 unable to find a matching CMSIS-DAP device,必須加 sudo。
本專案已附好規則檔 udev/60-openocd-debugprobe.rules,一行安裝:
sudo cp udev/60-openocd-debugprobe.rules /etc/udev/rules.d/
sudo udevadm control --reload-rules && sudo udevadm trigger規則內容(涵蓋正常模式與 RP2040/RP2350 的 BOOTSEL):
# Debug Probe (CMSIS-DAP, 正常模式)
SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000c", MODE="0666", TAG+="uaccess"
# RP2040 BOOTSEL
SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="0003", MODE="0666", TAG+="uaccess"
# RP2350 BOOTSEL
SUBSYSTEM=="usb", ATTRS{idVendor}=="2e8a", ATTRS{idProduct}=="000f", MODE="0666", TAG+="uaccess"
安裝後把探棒重新插拔一次讓規則生效,之後 OpenOCD / picotool 就不用
sudo了。
若你要自己編譯程式(而不是只燒別人給的 .uf2),需要三樣東西:
CMake / Ninja、ARM GNU 編譯器、Pico SDK。
# 1) CMake + Ninja
brew install cmake ninja
# 2) ARM GNU Toolchain(arm-none-eabi)
# ⚠️ Homebrew 的 arm-none-eabi-gcc 不含 newlib,編譯會出現
# "cannot read spec file 'nosys.specs'"。請改用「官方版」:
# 到 https://developer.arm.com/downloads/-/arm-gnu-toolchain-downloads
# 下載 arm-gnu-toolchain-*-x86_64-arm-none-eabi.tar.xz 解壓,
# 再把它的 bin/ 加進 PATH:
export PATH="$HOME/arm-gnu-toolchain-14.2.rel1-x86_64-arm-none-eabi/bin:$PATH"
arm-none-eabi-gcc --version # 確認可執行
# 3) Pico SDK
git clone --depth 1 -b 2.1.1 https://github.com/raspberrypi/pico-sdk.git
cd pico-sdk && git submodule update --init lib/tinyusb && cd ..
export PICO_SDK_PATH=$(pwd)/pico-sdk💡 建議把
PATH與PICO_SDK_PATH兩行寫進~/.bashrc/~/.zshrc,以後開終端機就自動有。
本專案附了一個可直接編譯的範例:
examples/blink。 以下用它示範從編譯到燒錄的完整流程(已在真實 Pico 上實測成功)。
cd examples/blink
export PICO_SDK_PATH=/path/to/pico-sdk # 見 4.2
cmake -B build -G Ninja -DPICO_BOARD=pico . # Pico 2 用 -DPICO_BOARD=pico2
ninja -C build編譯成功會在 build/ 產生:
build/blink.elf ← 給 OpenOCD / GDB 用(含除錯資訊)
build/blink.uf2 ← 也可直接拖進 BOOTSEL 磁碟
build/blink.bin / .hex / .map
本專案實測輸出(RP2040):
text=18448 data=0 bss=1212,blink.elf/blink.uf2均正常產生。
openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg \
-c "adapter speed 5000" \
-c "program build/blink.elf verify reset exit"Pico 2(RP2350)改用 target/rp2350.cfg。
實測成功輸出(重點):
Info : SWD DPIDR 0x0bc12477 ...
Info : [rp2040.core0] Cortex-M0+ r0p1 processor detected
** Programming Started **
Info : Found flash device 'win w25q16jv' (ID 0x001540ef)
** Programming Finished **
** Verify Started **
** Verified OK **
** Resetting Target **
看到 ** Verified OK ** + ** Resetting Target ** 就代表燒錄成功、程式已開始執行(板載 LED 開始閃)。
🔧 若出現
couldn't bind gdb to socket on port 3333: Address already in use, 代表有另一個 OpenOCD 還開著佔用 3333 埠。清除:pkill -f 'openocd.*rp2040'(若該程序是用 sudo 開的,需sudo pkill ...)。這個警告不影響燒錄本身。
除錯時中間隔著兩層橋樑,需要同時跑 OpenOCD(伺服器)與 GDB(你下指令的地方):
你打字 軟體橋樑 硬體橋樑 晶片
┌─────┐ ┌──────────┐ ┌───────────┐ ┌──────┐
│ GDB │◄────►│ OpenOCD │◄───USB──►│Debug Probe│◄SWD►│ Pico │
└─────┘ TCP │(GDB server) └───────────┘ └──────┘
:3333 └──────────┘
- OpenOCD:跟探棒講話,在電腦開一個 port 3333 等 GDB 來接。
- GDB:你實際設中斷點、看變數的地方;它連到 3333,透過 OpenOCD 控制晶片。
- 因為兩個都要同時跑,所以用兩個終端機視窗。
openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg -c "adapter speed 5000"
# 停在 "Listening on port 3333 for gdb connections" 就代表 server 就緒,保持開著arm-none-eabi-gdb examples/blink/build/blink.elf
blink.elf換成你自己的程式檔;它含機器碼+除錯資訊(變數名、行號), GDB 才能對應到原始碼。用官方 ARM toolchain 的arm-none-eabi-gdb(Ubuntu 也可用gdb-multiarch)。
進到 (gdb) 後依序輸入:
target extended-remote localhost:3333 # 連到終端機 A 的 OpenOCD
monitor reset halt # 重置並停住 CPU
load # 把 blink.elf 燒進 flash
break main # 在 main 設中斷點
continue # 執行,會停在 main接著逐行除錯:
| 指令 | 作用 |
|---|---|
next (n) |
執行下一行(不進入函式) |
step (s) |
進入函式內部 |
print count |
印出變數 count 的值 |
info registers |
看暫存器 |
continue (c) |
繼續執行(讓 LED 繼續閃) |
monitor reset halt |
重新重置並停住 |
quit (q) |
離開 GDB |
💡 一步到位:也可用 VS Code 的 Cortex-Debug(見第 8 節),按 F5 就自動做完 「開 OpenOCD → load → 停在 main」,用圖形介面下中斷點。
OpenOCD 與 GDB 的完整用法(設定檔三層結構、埠、雙核心 multidrop、 中斷點/監看點、記憶體與暫存器檢視、常見錯誤等)已獨立成深入文件, 避免本篇過長:
- 📘 OpenOCD 深入說明
- 🐞 GDB 深入說明
- ⚡ 常用指令速查表
以下是本教學用升級到 v2.3.1 的 Debug Probe 連接一顆 Pico (RP2040) 的實際驗證紀錄。
Pico 用 D 埠接好 SWD(SWCLK/GND/SWDIO)並自行供電後,執行:
openocd -f interface/cmsis-dap.cfg -f target/rp2040.cfg \
-c "adapter speed 5000" -c "init" -c "targets" -c "reset halt" -c "shutdown"未設定 udev 權限前需加
sudo,並用-s <openocd>/share/openocd/scripts指定設定檔路徑。
Info : Using CMSIS-DAPv2 interface with VID:PID=0x2e8a:0x000c, serial=E663B03597206F21
Info : CMSIS-DAP: SWD supported
Info : CMSIS-DAP: FW Version = 2.0.0
Info : CMSIS-DAP: Interface Initialised (SWD)
Info : SWD DPIDR 0x0bc12477, DLPIDR 0x00000001
Info : [rp2040.core0] Cortex-M0+ r0p1 processor detected
Info : [rp2040.core1] Cortex-M0+ r0p1 processor detected
Info : Listening on port 3333 for gdb connections
TargetName Type Endian TapName State
-- ------------------ ---------- ------ ------------------ ------------
0* rp2040.core0 cortex_m little rp2040.cpu running
1 rp2040.core1 cortex_m little rp2040.cpu running
[rp2040.core0] halted due to debug-request, current mode: Thread
xPSR: 0xf1000000 pc: 0x000000ea msp: 0x20041f00
| 訊息 | 代表 |
|---|---|
VID:PID=0x2e8a:0x000c |
探棒被辨識(CMSIS-DAP 正常模式) |
CMSIS-DAP: Interface Initialised (SWD) |
探棒 SWD 介面初始化成功 |
SWD DPIDR 0x0bc12477 |
讀到 RP2040 的除錯埠 ID(電氣連線 OK) |
[rp2040.core0/core1] Cortex-M0+ ... detected |
偵測到雙核心 |
halted due to debug-request |
reset halt 成功停住 CPU |
Listening on port 3333 |
GDB server 已就緒,可接 GDB/VS Code |
💡
FW Version = 2.0.0指的是 CMSIS-DAP 協定版本,不是 debugprobe 韌體版本(本教學韌體為 v2.3.1),兩者不同屬正常。
若出現 Error: Failed to connect multidrop rp2040.dap0(讀不到目標),依序檢查:
- 目標 Pico 有沒有自己的電(D 埠不供電)。
- 接的是 D 埠(SWD)不是 U 埠(UART)。
- SWDIO 與 SWCLK 是否接反(最常見)、
GND是否有接。 - 板子若是 Pico 2 (RP2350) 要改用
target/rp2350.cfg。 - 接線品質差時,把
adapter speed降到1000再試。
安裝 Cortex-Debug 擴充套件,在 .vscode/launch.json 加入:
{
"version": "0.2.0",
"configurations": [
{
"name": "Pico Debug (Debug Probe)",
"type": "cortex-debug",
"request": "launch",
"servertype": "openocd",
"cwd": "${workspaceFolder}",
"executable": "${workspaceFolder}/build/blink.elf",
"gdbPath": "gdb-multiarch",
"device": "RP2040",
"configFiles": [
"interface/cmsis-dap.cfg",
"target/rp2040.cfg"
],
"openOCDLaunchCommands": [ "adapter speed 5000" ],
"svdFile": "${env:PICO_SDK_PATH}/src/rp2040/hardware_regs/rp2040.svd",
"runToEntryPoint": "main"
}
]
}若使用官方 Raspberry Pi Pico VS Code 擴充套件, 它會自動偵測 Debug Probe,選
Debug(F5)即可直接下中斷點除錯。
Debug Probe 的 U 埠(黃線)接好後,會在電腦出現 /dev/ttyACM0:
# minicom
minicom -b 115200 -D /dev/ttyACM0
# 或 screen
screen /dev/ttyACM0 115200
# 或 tio
tio /dev/ttyACM0在 Pico 程式中用 printf() / stdio_uart 輸出的訊息就會出現在這裡。
Q1:openocd 找不到裝置 / Error: unable to find CMSIS-DAP device
- 確認
lsusb有看到2e8a:000c。 - 設定第 4.1 節的 udev 權限,或先用
sudo測試。
Q2:更新韌體時找不到 RPI-RP2 磁碟
- 確認
lsusb顯示2e8a:0003(RP2 Boot)。若有但沒自動掛載, 用sudo mount手動掛載,或改用sudo picotool load。
Q3:picotool 顯示 No accessible RP-series devices in BOOTSEL mode
- Debug Probe 在正常模式下 picotool 讀不到,這是正常的;
只有進入 BOOTSEL(
2e8a:0003)後 picotool 才看得到。
Q4:序列埠沒有輸出
- 檢查 UART 是否交叉接線(Probe TX ↔ 目標 RX)。
- 確認 baud rate(預設常見為 115200)。
Q5:SWD 連線不穩 / 速度慢
- 降低
adapter speed(例如 2000)試試,接線越短越穩。 - 更新到最新韌體(見第 3 節)通常有幫助。
本專案有 .github/workflows/release.yml:推一個 v* 版本 tag,CI 會自動
編譯 blink(pico + pico2),並建立 GitHub Release、附上以下檔案:
blink-pico.uf2/blink-pico2.uf2(可直接拖進 BOOTSEL)blink-pico.elf/blink-pico2.elf(給 OpenOCD / GDB 除錯)debugprobe-v2.3.1.uf2(Debug Probe 韌體)
發布方式:
git tag v1.0.0
git push origin v1.0.0 # 觸發 release workflow或到 GitHub 的 Actions → Release → Run workflow,手動輸入 tag 名稱執行。
已存在的 tag 會改為更新該 release 的附件(
--clobber),不會重複建立。
pico-debug-probe-tutorial/
├── README.md # 本教學
├── .github/workflows/
│ ├── build-blink.yml # CI:自動編譯 blink(pico / pico2)
│ └── release.yml # 推 v* tag 自動發 release 並附上 .uf2
├── docs/
│ ├── openocd.md # OpenOCD 深入說明
│ ├── gdb.md # GDB 深入說明
│ └── cheatsheet.md # 常用指令速查表
├── firmware/
│ ├── debugprobe-v2.3.1.uf2 # 已下載的最新韌體
│ └── flash-probe.sh # 自動燒錄腳本(等 BOOTSEL 後自動複製)
├── udev/
│ └── 60-openocd-debugprobe.rules # 免 sudo 的 USB 權限規則(見 4.1)
└── examples/
└── blink/ # 可編譯範例:LED 閃爍 + UART printf
├── blink.c
├── CMakeLists.txt
├── pico_sdk_import.cmake
├── .vscode/launch.json # VS Code (Cortex-Debug) 設定
└── README.md # 範例的編譯→load→除錯步驟
韌體 SHA-256:
aae9585f456c28c00865eb3df4d4bfc184f8e7ae60ebed3cc32a32512521a1b8