使用邏輯分析儀初探SWD協定
實際量測 ARM Debug Interface (ADI) 波型
📌 SWD/JTAG Debug Port(DP) 基本理解
- JTAG-DP (JTAG Debug Port): 基於 IEEE 1149.1 標準,使用 DBGTAP 掃描鏈 (Scan Chains) 來讀寫暫存器資訊。這是一種傳統且廣泛使用的標準介面。
- SW-DP (Serial Wire Debug Port): 這是一種 雙腳位 (Two-pin) 的序列介面,使用 封包傳輸協定 (Packet-based protocol) 來進行暫存器的讀寫。
| 特性 | JTAG (IEEE 1149.1) | SWD (Serial Wire Debug) |
|---|---|---|
| 訊號腳位 | 需要較多腳位,包含 TDI, TDO, TMS, TCK (以及可選的 nTRST),。 | 僅需 2 個腳位:雙向資料線 SWDIO 與時脈線 SWCLK,。 |
| 傳輸機制 | 透過 狀態機 (State Machine) 與 掃描鏈 進行序列位移操作。 | 透過 封包 (Packet) 進行通訊,包含請求(Request)、回應(Acknowledge)與資料傳輸階段,。 |
| 主要優勢 | 廣泛支持以及豐富調試功能。 | 腳位需求少,讀取效率更高。 |
🔧 工具平台選擇
單純讀文件資料會比較枯燥乏味,因此決定使用實際的硬體工具來觀察 SWD 協定的運作。 使用的工具包含 STM32 開發板與邏輯分析儀。
邏輯分析儀
使用的是便宜的 24Mhz 8CH 邏輯分析儀,其應是來自開源的 WeAct LogicAnalyzer V1 的設計(仿製cypress)。
拆開其外殼後,可以看到其內部使用的是 芯佰微 (CoreBai) 的 CBM9002A 晶片,這是一款基於 8051 核心的 USB 微控制器。
搭配的軟體是 sigrok 的 PulseView,這是一款開源且跨平台的邏輯分析軟體,支援多種硬體設備。 安裝與使用可以參考 WeActStudio/LogicAnalyzerV1 的教學說明。
STM32 開發板
使用的是NUCLEO-F767ZI,其上有內建 ST-LINK/V2-1,可以直接透過 USB 連接進行 SWD 調試 STM32F767ZI 微控制器。並且上面有external SWD header,可以方便接線。
附上其 Debug Connector 的腳位表:
而操作上,使用 STM32CubeProgrammer ,在 GUI 介面命令 ST-LINK 進行 SWD 通訊,並且在 PulseView 上觀察 SWD 波型。
📈 SWD 通訊觀察
透過 CubeProgrammer 連接 STM32F767ZI 後,按下 Connect 按鈕,ST-LINK 會自動透過 SWD 協定與目標 MCU 進行通訊。 此次觀察的重點在於 SWD 協定的初始化過程,以及讀取 DPIDR (Debug Port ID Register) 的操作。
JTAG 轉 SWD 序列
經過NRST 重置後,由於 JTAG interface 必須在 TLR state 才能偵測 16-bit JTAG-to-SWD sequence,因此套過 Line Reset (至少 50 個 TCK 並且 TMS HIGH) 後,接著會送出 JTAG-to-SWD sequence。
Note: 我的疑問,為何假設此時初始狀態是在JTAG的某state下,其software reset 明明只要5個TCK就可以了? 參考文件的解釋
The sequence that is shown in the figure has been chosen to ensure that the SWJ-DP switches to SWD, independent of whether it was previously expecting JTAG or SWD.,由於此時無法確定處於的狀態,因此使用了較長的序列來確保切換成功。
而 JTAG-to-SWD sequence 為 16-bit 的固定序列 0x79E7 (大多是MSB first),其二進位為 0b0111 1001 1110 0111。
SWD 讀 IDCODE (DPIDR)
SWD 不同於 JTAG 有 IDCODE instrunction,其走的是封包概念,所以當我們要辨識其 SW-DP 時,會透過 SWD 讀取 DPIDR (Debug Port ID Register) 來取得,而其位址為 0x00。
我們的 STLink 調適器作為 Host 端,會先送出一個讀取 DPIDR 的 8-bit 請求封包 (Request Packet),然後等待目標IC回應,在讀DPIDR此操作上,其部會回應 WAIT 或 FAULT,而是會直接回應 OK (0b001) by LSB first。
Parity bit 看傳送封包的資料位元數量來決定其值,若資料中 1 的數量為奇數,則 Parity bit 為 1 (使得總數為偶數),反之亦然。 Park bit 為 1,事先將資料線拉高,表示傳輸結束,且確保 Trn 期間資料線為高電位。 Trn (Turnaround) 為雙向資料線切換方向的時間,讀取操作時,Host 端在送出請求封包後,需要釋放資料線,讓目標 IC 可以回應資料,因此會有一個 Trn 週期。
在上圖中,IDCODE 傳送8-bit 後,看起來少了一個 Trn cycle,尚不確定原因,懷疑 LA 取樣率不夠高導致少觀察到。
傳送回來的 DPIDR 資料為 0x5BA02477,其二進位為 0101 1011 1010 0000 0010 0100 0111 0111,符合 ARM DPIDR 的格式說明:
| Bits | Name | Value | Description |
|---|---|---|---|
| [31:28] | Revision | 0x5 | 修訂版本號 (Revision code) 表示此 DP 設計的修訂版本為 r5。 |
| [27:20] | Part Number | 0xBA | 零件編號 (Part Number) 由設計者 (Designer) 分配的編號。0xBA 通常對應 Arm CoreSight SoC-400 系列的 SW-DP。 |
| [19:17] | Reserved | 0x0 | 保留位,應設為零。 |
| [16] | Min | 0x0 | 最小化實作 (Minimal DP) 0表示此 DP 不是 MINDP。 |
| [15:12] | Version | 0x2 | DP 架構版本 (DP Version) 0x2 表示此 DP 符合 DPv2 規範。 |
| [11:1] | Designer ID | 0x23B | 設計者代碼 (Designer ID) 這是 JEDEC JEP106 代碼,代表 Arm Limited。 |
| [0] | RAO | 0x1 | Read As One 此位元永遠為 1。 |
在資料後面,同樣在下個操作前,會有一個 Parity bit 和 Trn 週期。
📝 結語
由於 ARM 架構的細節相當多,因此在了解 SWD 協定時,必須同時補充相關的背景知識。 在使用新買的邏輯分析儀並操作 PulseView ,發現其操作介面相當直觀,且支援多種協定解碼器 (Protocol Decoder),對於我後續學習與工作上debug 相關會有很大幫助。 原本想學習到至少讀出 IC UID ,不過後續發現還需要對 Access Port (AP) 操作等等,暫時先擱置,未來有機會再繼續深入研究。