はじめに
この記事は,udbipd-win を使うことでCortexのデバッグができるdevcontainer 環境を作るためのものです。
前の記事ではgdb-serverをホスト側に置きましたが,usbipd-winを使うことで,Linuxやdevcontainer側ですべて完結させることができます。
方針
usbipd-winを使うことで,開発に必要なソフトウェアは全てLinux側に入れます。
以下のような構成になります:
- ホストにusbipd-winを導入します
- WSLでudevの設定を行い,USBデバイスファイルに非rootの読み書きを許します。コンテナのユーザでstlinkなどのデバイスを制御できるようにするためです
- devcontainerの設定で,/dev/bus/usb をコンテナにマップします。コンテナからUSBを操作できるようにするためです
環境構築
ホスト(Windows)
usbipd-winを導入するため,以下のコマンドをAdministrator権限で投入します。
winget install --exact dorssel.usbipd-win
正常にインストールされると,usbipd listでUSBデバイス一覧が表示されるはずです。
私は ST-Link v3 をdevcontainerから使いたいので,このVIDとPIDをメモしておきます(これをusbipdでリダイレクトする)。
PS C:\Users\test> usbipd list
Connected:
BUSID VID:PID DEVICE STATE
1-4 13d3:56c6 HD Camera Not shared
1-10 8087:0aaa インテル(R) ワイヤレス Bluetooth(R) Not shared
3-4 0483:3754 ST-Link Debug, USB シリアル デバイス (COM9) Not shared
Persisted:
GUID DEVICE
usbipd: warning: USB filter 'TsUsbFlt' is known to be incompatible with this software; 'bind --force' will be required.
WSL
USBのデバイスファイルが作成されるとき,非rootからのアクセスを許す必要があります。
そこで,udevのルールを作成し読み込ませます。
ルールで指定するidVendorとidProductは,先ほど確認したST-Link v3のVIDとPIDです。
SUBSYSTEM=="usb", ATTRS{idVendor}=="0483", ATTRS{idProduct}=="3754", MODE="666"
ルールの再読み込みは,udevadmで行います。
$ sudo udevadm control --reload-rules
ここまでできたら,USBのリダイレクトができるか確認してみます。
Windows側でusbipd bindを投入して,デバイスをusbipd管理にします(ホストからは見えなくなる)。
PS C:\Users\test>usbipd bind -f -i 0483:3754
usbipd: info: Device with hardware-id '0483:3754' found at busid '3-4'.
続けてWindows側でusbipd attachを投入して,デバイスをWSLにアタッチします。
PS C:\Users\test>usbipd attach -a -w -i 0483:3754
usbipd: info: Device with hardware-id '0483:3754' found at busid '3-4'.
usbipd: info: Using WSL distribution 'Ubuntu' to attach; the device will be available in all WSL 2 distributions.
usbipd: info: Detected networking mode 'nat'.
usbipd: info: Using IP address 172.31.240.1 to reach the host.
usbipd: info: Starting endless attach loop; press Ctrl+C to quit.
WSL Monitoring host 172.31.240.1 for BUSID: 3-4
WSL 2025-07-27 13:49:20 Device 3-4 is now attached.
-a は --auto-attach で,アタッチ中のデバイスが物理的に抜去・再挿入されたとき,自動的に再アタッチするためのオプションです。
WSL側でUSBを確認すると,デバイスが接続されていること,デバイスファイルのパーミッションが設定されていることが確認できます。
$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 010: ID 0483:3754 STMicroelectronics STLINK-V3
Bus 002 Device 001: ID 1d6b:0003 Linux Foundation 3.0 root hub
$ ls -la /dev/bus/usb/001/010
crw-rw-rw- 1 root root 189, 9 Jul 27 13:45 /dev/bus/usb/001/010
devcontainer設定
devcontainer.json のrunArgsで,/dev/bus/usb をコンテナにマッピングしておきます。
また,cgroupのルールでキャラクタデバイスのメジャー番号189(= USB)に対する権限を追加します(read, mknod, write)
{
"name": "AWS CDK & SAM & LocalStack",
"image": "mcr.microsoft.com/devcontainers/base:bookworm",
"runArgs": ["--device-cgroup-rule", "c 189:* rmw", "-v", "/dev/bus/usb:/dev/bus/usb"],
"features": {
}
}
前の記事と同じく,Arm GNU Toolchainは手動で入れます。
また,vscode にCortex-Debug拡張を入れ,Arm GNU Toolchain のgdbを使う設定にします。
{
"cortex-debug.gdbPath": "arm-none-eabi-gdb",
}
devcontainer 上でopenocdを使う設定をします。
servertype が external ではなく openocd になっていますが,ベンダのgdb-server を使う場合,stlink とか jlinkにすればよいです。
{
"version": "0.2.0",
"configurations": [
{
"type": "cortex-debug",
"servertype": "openocd",
"request": "launch",
"name": "Debug (OpenOCD)",
"runToEntryPoint": "main",
"executable": "./build/stm32f4-c.elf",
"device": "STM32F405RGT6",
"configFiles": [
"interface/stlink.cfg",
"target/stm32f4x.cfg"
],
"cwd": "${workspaceRoot}",
}
]
}
ここまでの設定で,devcontainer 上でCortexのデバッグができるようになります。
終わりに
usbipdを使えば,コンテナ内に全ソフトウェアを詰め込めるので便利だなと思いました。また,ベンダのgdb-serverはローカルホスト以外からの接続を受け付けないものがある(らしい)ので,その場合でもLinux版が提供されていればコンテナでデバッグができます。
一方,gdb-serverをホストで動かす方が性能劣化は少なそう(USBプロトコルをIP化するより効率的)に思えます。usbipdのようにWSLにデバイスファイルが生えるわけではないので,コンテナ間の分離の観点ではこちらが有利そうです。
今回はdevcontainerでしたが,どちらの方法でも開発環境と物理的なデバッガを別PCに入れることができるはずです。code-serverで使えるかなど,試してみたいと思います。