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的整体架构:

ARM CoreSight 调试架构 外部调试器 DP (SWJ-DP/SW-DP) DAP (调试访问端口) AP (MEM-AP) AP (AHB-AP) AP (APB-AP) 目标系统 (Cortex-M/A/R) 调试器 → DP → DAP → AP → 目标系统:这就是ARM调试的完整数据通路

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序列。