概要
SWD(Serial Wire Debug)は、ARM が設計した 2 線式のデバッグインターフェースである。JTAG の4〜5本の信号線を SWDIO(双方向データ)と SWCLK(クロック)の 2本だけ に削減しながら、同等のデバッグ機能を実現する。
ARM Cortex-M シリーズ(Cortex-M0/M0+/M3/M4/M7/M33 など)のほぼすべてが SWD をネイティブサポートしており、STM32、nRF5x、RP2040(Raspberry Pi Pico)、SAMD シリーズといった組み込み開発で広く使われる MCU でも標準的に利用できる。
主な利点は以下のとおり。
- ピン数削減 — 2本なので小型基板やコスト削減に貢献
- デバッグポートとして完全 — ブレークポイント、ウォッチポイント、レジスタ読み書き、メモリアクセス、フラッシュ書き込みすべて対応
- 高速転送 — 最大 10 MHz 以上のクロックで動作可能
- JTAG ピン共用 — 多くの MCU で SWDIO=TMS、SWCLK=TCK にマッピングされており、JTAG と共用ピン構成になっている
歴史・背景
SWD は ARM が CoreSight デバッグアーキテクチャの一部として開発したもので、ADIv5(ARM Debug Interface version 5) 仕様の中に定義されている。初出は 2002 年頃であり、Cortex-M シリーズが 2004 年に登場して以降、急速に普及した。
JTAG が 1990 年に策定された時代にはチップのピン数に余裕があったが、2000 年代以降の超小型・低コスト MCU 全盛期にはピン数節約が切実な課題となった。SWD はその解答として登場し、特に マイクロコントローラのデバッグ用途においては JTAG を実質的に置き換えた と言っても過言ではない。
また、ARM は CMSIS-DAP(Cortex Microcontroller Software Interface Standard – Debug Access Port)という オープンなファームウェア仕様 を提供しており、SWD に対応した低コストなデバッグアダプタ(DAPLink ベースの安価な ST-Link 互換品など)が多数流通するきっかけにもなった。
| 世代 | ARM Debug Interface | 主な変更点 |
|---|---|---|
| ADIv1〜4 | JTAG のみ | Cortex-A 以前の世代 |
| ADIv5 | JTAG + SWD 両対応 | Cortex-M 登場〜現在 |
| ADIv6 | JTAG + SWD + cJTAG | Cortex-A55/M55 等の新世代 |
技術仕様
信号線
| 信号名 | 方向 | 説明 |
|---|---|---|
| SWCLK(Serial Wire Clock) | ホスト→ターゲット | クロック。推奨は 1〜10 MHz |
| SWDIO(Serial Wire Data I/O) | 双方向 | データ兼コマンド。ターンアラウンドで方向切り替え |
| SWO(Serial Wire Output)※任意 | ターゲット→ホスト | ITM トレース出力用。デバッグには必須でない |
| RESET(nRST)※任意 | ホスト→ターゲット | チップリセット |
コネクタは 10ピン 1.27mm ピッチ ARM Cortex Debug コネクタ が業界標準となっている。
10ピン ARM Cortex Debug コネクタ(1.27mm ピッチ)ピン配置:
1: VCC 2: SWDIO
3: GND 4: SWCLK
5: GND 6: SWO(任意)
7: KEY 8: NC
9: GND 10: nRESET
プロトコル概要
SWD パケットは以下の構造を持つ。
[START(1)] [APnDP(1)] [RnW(1)] [A2(1)] [A3(1)] [PARITY(1)] [STOP(1)] [PARK(1)]
→ ACK(3) → DATA(32) + PARITY(1)
- APnDP — Access Port(AP)か Debug Port(DP)か
- RnW — Read(1)か Write(0)か
- A[2:3] — レジスタアドレス(2ビット)
- ACK — OK / WAIT / FAULT の 3 種
ホストは SWDIO を出力にしてコマンドを送り、ACK 受信後にターンアラウンド(方向切り替え)してデータを受け取る。この双方向切り替えを 1 本の信号線で実現しているのが SWD の特徴である。
転送速度の目安
| クロック | 実効スループット(目安) |
|---|---|
| 1 MHz | 約 750 kbps |
| 4 MHz | 約 3 Mbps |
| 10 MHz | 約 7.5 Mbps |
フラッシュ書き込みでは実際にはフラッシュの書き込みサイクルが律速になるため、SWD クロックを上げても体感速度は頭打ちになりやすい。
動作原理
DAP(Debug Access Port)との関係
SWD は DAP の物理層インターフェースである。SWD 経由でアクセスできるのは DP(Debug Port) レジスタであり、DP を通じて AP(Access Port) にアクセスし、最終的に CPU コア・メモリ・ペリフェラルレジスタへ到達する。
デバッガ(PC)
│
JTAGアダプタ/SWDアダプタ(例: J-Link、CMSIS-DAP)
│ SWCLK + SWDIO
▼
DAP(Debug Access Port)
├─ DP(Debug Port) ← SWD/JTAG が直接アクセス
└─ MEM-AP(Memory Access Port)
│
▼
AHB/APBバス ── CPU Core / RAM / Flash / Peripheral
SWO トレース(ITM)
SWO(Serial Wire Output)は SWD に付随するオプション機能で、チップ内部の ITM(Instrumentation Trace Macrocell) からデータをストリーミング出力する。printf のようなソフトウェアログや、RTT(Real-Time Transfer)出力の代替として使われる。
// ITM を使ったデバッグ出力(CMSIS 利用)
#include "core_cm4.h"
void ITM_SendChar_Wrapper(char c) {
while (ITM->PORT[0].u32 == 0); // ポート0が利用可能になるまで待機
ITM->PORT[0].u8 = (uint8_t)c;
}
J-Link 等のアダプタでは SWO をリアルタイムで受信し、IDE に「SWO Console」として表示できる。
用途・ユースケース
ARM MCU 開発でのフラッシュ書き込み
最も日常的な用途はファームウェアのフラッシュ書き込みである。STM32CubeIDE、Keil MDK、IAR Embedded Workbench などの IDE はいずれも SWD 経由の書き込みをネイティブサポートしている。
# OpenOCD + SWD でのフラッシュ書き込み例(STM32)
openocd \
-f interface/cmsis-dap.cfg \
-c "transport select swd" \
-f target/stm32f4x.cfg \
-c "program firmware.bin verify reset exit 0x08000000"
Raspberry Pi Pico(RP2040)のデバッグ
RP2040 は SWD 専用の設計であり、JTAG をサポートしない。2本の GPIO(GPIO28=SWDIO、GPIO29=SWCLK)が SWD 端子として機能する。
Raspberry Pi Pico
┌──────────────────┐
│ GP28 ── SWDIO │──── デバッグアダプタ SWDIO
│ GP29 ── SWCLK │──── デバッグアダプタ SWCLK
│ GND │──── デバッグアダプタ GND
└──────────────────┘
別の Pico を CMSIS-DAP アダプタとして使う「picoprobe」という手法も広く使われており、低コストで SWD デバッグ環境を構築できる。
量産時の SWD 書き込み
量産ラインでは専用の SWD プログラマ(Segger J-Flash、STM32 ST-LINK Utility 等)を使ってフラッシュ書き込みを自動化する。SWD は 2 本のプローブピンで接続できるため、テストフィクスチャの設計がシンプルになる利点がある。
実装・開発のポイント
プルアップ/プルダウン抵抗
- SWDIO — 内部プルアップが有効になっている MCU が多いが、外付けで 10kΩ プルアップ推奨
- SWCLK — 外付けで 10kΩ プルダウン推奨(フローティング防止)
- nRESET — 100nF のデカップリング + 10kΩ プルアップ推奨
SWD ポートのセキュリティロック
JTAG 同様、製品出荷前には SWD ポートを無効化するのがセキュリティの基本である。STM32 では RDP(Read Protection)を設定することで、SWD 経由のフラッシュ読み出しとデバッグを禁止できる。
// STM32 RDP Level 2(完全ロック・不可逆)の例
// ※ Level 2 は一度設定すると解除不可能。量産前に十分テストすること
FLASH_OBProgramInitTypeDef OBInit = {0};
HAL_FLASH_Unlock();
HAL_FLASH_OB_Unlock();
OBInit.OptionType = OPTIONBYTE_RDP;
OBInit.RDPLevel = OB_RDP_LEVEL_2; // 不可逆ロック
HAL_FLASHEx_OBProgram(&OBInit);
HAL_FLASH_OB_Launch();
pyOCD を使った Python からの SWD 制御
from pyocd.core.helpers import ConnectHelper
with ConnectHelper.session_with_chosen_probe() as session:
board = session.board
target = board.target
target.reset_and_halt()
# メモリ読み出し例
value = target.read32(0x20000000)
print(f"Address 0x20000000: 0x{value:08X}")
# フラッシュ書き込み
with open("firmware.bin", "rb") as f:
data = list(f.read())
target.flash.flash_program_phrase(0x08000000, data)
target.reset()
他技術との比較
| 項目 | SWD | JTAG | UART BootROM |
|---|---|---|---|
| 信号線数 | 2本 | 4〜5本 | 2本 |
| 対応アーキテクチャ | ARM Cortex のみ | 汎用 | 汎用 |
| デバッグ機能 | 完全対応 | 完全対応 | 非対応 |
| バウンダリスキャン | 非対応 | 対応 | 非対応 |
| トレース機能(SWO) | 対応 | ETM 対応 | 非対応 |
| コネクタ面積 | 小(2線) | 大(4〜5線) | 小(2線) |
| デイジーチェーン | 非対応 | 対応 | 非対応 |
| 典型的な用途 | ARM MCU 全般 | FPGA・SoC | 初期ブート書き込み |
SWD と JTAG はどちらも ARM CoreSight DAP にアクセスする手段であり、デバッグ機能として得られる情報は同等である。ARM MCU に限定するなら、信号線が少なくコネクタ設計が楽な SWD が第一選択肢となる。FPGA や非 ARM チップを混在させる必要がある場合、デイジーチェーンが可能な JTAG を選択する。
Raspberry Pi Pico や STM32 などのポピュラーな ARM MCU ではどちらも共用ピンとして実装されているため、アダプタ側の設定で切り替えるだけで両方を使える構成も多い。