2. ARM调试架构:CoreSight、DAP与SWJ-DP/SW-DP
ARM的调试架构,说白了就是芯片内部给你留了一扇「后门」。这扇门让你能随时停下来看CPU在干什么,改它的内存,甚至单步执行代码。我刚开始接触ARM调试时,总觉得这东西很玄乎,后来拆开架构一看,其实就三个核心部件:CoreSight、DAP和DP/SWJ-DP接口。
咱们一个一个说清楚。
2.1 CoreSight调试架构
CoreSight是ARM官方的调试与追踪架构。它不是一个单一的模块,而是一整套IP的集合。你想想看,现在的SoC里动不动就四核八核,还有GPU、DSP、NPU,怎么统一调试?CoreSight就是干这个的。
它的核心思想是:所有调试和追踪数据,都通过一套标准化的总线(ATB,Advanced Trace Bus)来传输。调试器通过一个统一的入口访问所有内核和组件。
CoreSight的关键组件:
- DP(Debug Port):物理接口,负责和外部调试器握手。就是JTAG或SWD。
- AP(Access Port):功能接口,负责访问内存、寄存器、系统总线。
- DAP(Debug Access Port):DP + AP的组合体,是调试器进入芯片的「大门」。
- ETM/PTM(Embedded Trace Macrocell):追踪CPU指令流,用于性能分析。
- TPIU(Trace Port Interface Unit):把追踪数据从芯片内部送出去。
我记得有一次调试一个多核启动问题,其中一个核死活跑不起来。用CoreSight的ETM抓了一下指令流,发现它卡在了一个自旋锁上。如果没有追踪功能,这种问题靠断点根本查不出来。
下面这张图展示了CoreSight的整体架构:
2.2 DAP(调试访问端口)
DAP是CoreSight架构里的核心枢纽。它由两部分组成:
- DP(Debug Port):负责和外部调试器通信,处理协议层面的东西。
- AP(Access Port):负责访问芯片内部资源,比如内存、寄存器、外设。
一个DAP可以挂多个AP。最常见的AP类型是MEM-AP(Memory Access Port),它通过AHB或APB总线访问系统内存和外设。
个人经验:我习惯在调试前先确认DAP是否已经上电。很多芯片在低功耗模式下会把DAP的时钟关掉,这时候调试器连不上,不是硬件坏了,是DAP没醒。解决办法是给芯片一个外部唤醒信号,或者用复位引脚强制唤醒。
DAP的寄存器访问是通过DP来完成的。调试器先写DP的SELECT寄存器,选择要访问的AP,然后通过DP的RDBUFF或DRW寄存器读写AP的数据。这个过程在OpenOCD里是自动完成的,但理解它有助于排查连接问题。
2.3 SWJ-DP与SW-DP接口
ARM芯片上最常见的调试接口有两种:SWJ-DP和SW-DP。
| 特性 | SWJ-DP | SW-DP |
|---|---|---|
| 支持的协议 | JTAG + SWD | 仅SWD |
| 引脚数 | 5 (TCK, TMS, TDI, TDO, nTRST) 或 4 (无nTRST) | 2 (SWCLK, SWDIO) |
| 切换方式 | 通过JTAG序列切换到SWD模式 | 上电即SWD模式 |
| 典型应用 | Cortex-A/R系列,需要JTAG边界扫描 | Cortex-M系列,引脚受限场景 |
| 调试速度 | JTAG模式可达几十MHz | SWD模式通常4-10MHz |
SWJ-DP是「双模」接口。上电后默认进入JTAG模式,但你可以通过发送一串特定的SWJ序列(也叫「SWJ切换序列」),把它切换到SWD模式。切换后,JTAG引脚中的TMS变成SWDIO,TCK变成SWCLK,TDI和TDO可以复用为GPIO。
SW-DP是「纯SWD」接口。它只有两根线:SWCLK和SWDIO。我特别喜欢这种接口,尤其是在做小尺寸PCB设计时,省下来的引脚可以干很多事。
避坑指南:我曾经在一个项目里遇到SWD死活连不上的问题。查了半天,发现是SWCLK上被人加了一个100pF的电容,导致时钟沿变缓,SWD协议时序不满足。SWD对时钟质量要求比JTAG高,走线尽量短,不要乱加滤波电容。
2.4 SWJ-DP切换到SWD模式
如果你用的是SWJ-DP,想用SWD模式,需要发送一个特殊的切换序列。这个序列在ARM调试接口规范里有定义,我直接给你看OpenOCD里是怎么做的:
# OpenOCD 内部 SWJ-DP 切换序列(简化版)
# 1. 发送至少 50 个 TCK 周期的 TMS=1(进入 Test-Logic-Reset)
# 2. 发送序列:0xE79E(16位,LSB first)
# 3. 发送 0x00 作为确认
# 4. 之后 DP 就工作在 SWD 模式了
# 在 OpenOCD 配置中,你可以这样指定:
source [find interface/stlink.cfg]
transport select swd
# 这样 OpenOCD 会自动发送切换序列
切换序列的原理是:JTAG状态机在Test-Logic-Reset状态下,收到特定的TMS序列后,DP会识别出这是一个「协议切换请求」,然后内部切换到SWD模式。切换后,JTAG状态机就失效了,所有通信走SWD协议。
2.5 实际调试中的选择建议
我个人建议:
- 做原型验证或调试复杂SoC:用SWJ-DP,保留JTAG模式。JTAG的边界扫描功能在硬件调试时非常有用,比如检查引脚连接、扫描链完整性。
- 做量产产品或引脚受限设计:用SW-DP,省引脚、省PCB面积。SWD的速度虽然不如JTAG,但下载代码和单步调试完全够用。
- 如果芯片同时支持两种接口:我习惯在开发阶段用JTAG,量产阶段切到SWD。JTAG的调试能力更强,SWD更简洁。
核心要点回顾:
- CoreSight是ARM调试的骨架,DAP是核心枢纽。
- DP负责和外部通信,AP负责访问内部资源。
- SWJ-DP支持JTAG和SWD双模,SW-DP只支持SWD。
- SWD只有两根线,适合引脚受限场景。
- 切换SWD模式需要发送特定的JTAG序列。