1. 多核调试工程导入

多核芯片的调试难点,往往不在“能不能连上”,而在“连上之后能不能看清每个核在做什么”。当 SoC 内部同时存在 Cortex-A 应用核、Cortex-R 实时核、Cortex-M 控制核以及 DSP 或 NPU 时,各核可能运行不同操作系统、处于不同电源域、由不同复位源释放,甚至共享同一段 DDR 与中断控制器。TRACE32 在这类场景中的角色,不是简单的“下载器”,而是一套多核可观测性与控制平台:它通过调试探针接入芯片的调试访问端口,为每个核建立独立的调试上下文,同时提供跨核的同步启停、内存视图、跟踪与脚本自动化能力。

一、TRACE32 在多核调试中的定位

理解 TRACE32 的多核能力,需要先区分三个层次。第一层是物理连接层:探针(如 PowerDebug、PowerTrace)通过 JTAG/cJTAG/SWD 或 Aurora 等接口接入芯片,芯片内部通常有一个调试访问端口(DAP)和多个访问点(AP),每个 AP 对应一个核或一个调试组件。第二层是逻辑核层:TRACE32 用 SYStem.CPU 声明当前核类型,用 CORE.ASSIGN 把多个核分配到同一个 SYStem 下的不同 core 编号,从而让一个 TRACE32 实例管理多个核。第三层是同步控制层:通过 SYStem.Mode、Go、Break、Step 等命令的 group 语义,实现“全部核一起运行、一起停止”或“只停某一个核、其余继续跑”。

这三层决定了多核调试工程的基本形态:一个工程文件(.cmm 脚本)负责建立连接、分配核、加载符号、初始化内存映射,然后才进入真正的调试阶段。很多初学者把工程导入理解为“打开 TRACE32 点连接”,结果在多核场景下频繁遇到“只能看到核 0”“断点命中后其他核跑飞”“符号加载错位”等问题,根源都在于没有把这三层关系理清。

二、典型工作流:从工程导入到多核同步

一个可复用的多核调试工作流通常包含以下环节,顺序不能随意颠倒:

  1. 确认硬件拓扑与调试接口:明确芯片有几个核、各自属于哪个簇、复位释放顺序、调试 AP 编号。例如某 SoC 中,Cortex-A55 四核位于 AP0,Cortex-M33 位于 AP2,DSP 位于 AP3。
  2. 建立 SYStem 并声明 CPU:先连接 DAP,再逐个 SYStem.CPU 切换并 CORE.ASSIGN。注意每个核的 CPU 类型必须与芯片实际一致,否则寄存器视图会错乱。
  3. 配置内存映射与访问路径:多核常共享 DDR,但每个核的 MMU/MPU 配置不同。TRACE32 的 MMU 或 SYStem.MemAccess 需要按核设置,否则读到的地址是物理地址还是虚拟地址会混淆。
  4. 加载符号与初始化脚本:为每个核分别加载 ELF,用 Data.LOAD.Elf 指定到对应 core。若核间共享代码段,可只加载一次并设置共享符号。
  5. 设置同步组与断点:用 SYStem.CONFIG 或 Break.Set 的 group 参数,把需要联动的核编入同一组。同步断点应设在核间通信的握手点或共享内存标志位处。
  6. 运行与观察:先 Go 全部核,再在关键路径上观察各核 PC、共享变量与中断状态。若某核未按预期启动,优先检查复位释放与时钟使能,而不是反复改断点。

下面这张图把上述工作流中“工程导入阶段”的核心对象与连接关系可视化出来,重点表现探针、DAP、多 AP、多核与 TRACE32 逻辑核之间的映射,以及同步控制的作用点。

TRACE32 主机 SYStem 配置 CPU / 内存映射 / 复位 CORE.ASSIGN core0 ~ core3 逻辑核 符号加载 Data.LOAD.Elf 按核 同步组 / 断点 group 联动启停 运行与观察 PC / 共享变量 / 中断 调试探针 PowerDebug JTAG / cJTAG Aurora(跟踪) USB/以太网 DAP 调试访问端口 AP0 / AP2 / AP3 AHB-AP / APB-AP CTI / CTM 交叉触发 物理链路 SoC 内部多核 Cortex-A55 ×4(AP0) core0 / core1 / core2 / core3 Cortex-M33(AP2) core4 实时控制核 DSP / NPU(AP3) core5 加速核 共享资源 DDR / GIC / 时钟复位 同步组:Go / Break / Step 跨核联动 工程导入阶段核心:探针 → DAP → AP → 逻辑核映射,同步组决定跨核启停行为

三、工程环境搭建的关键配置

把图上的关系落到实际工程,需要一份可执行的启动脚本。下面给出一个多核工程导入的示例脚本骨架,参数为教学示例,实际使用时需按芯片手册替换 AP 编号、CPU 类型与地址。

; multi_core_setup.cmm —— 多核工程导入示例
SYStem.CONFIG.DEBUGPORTTYPE JTAG
SYStem.CONFIG.SLAVE 1.      ; 选择 DAP 实例
SYStem.Mode Prepare

; 核 0:Cortex-A55
SYStem.CPU CortexA55
CORE.ASSIGN 0.
SYStem.Option.ResBreak ON
Data.LOAD.Elf app_core0.elf /NoClear

; 核 1:Cortex-A55
CORE.ASSIGN 1.
SYStem.CPU CortexA55
Data.LOAD.Elf app_core1.elf /NoClear

; 核 4:Cortex-M33
CORE.ASSIGN 4.
SYStem.CPU CortexM33
Data.LOAD.Elf rtos_m33.elf /NoClear

; 建立同步组:核 0~3 联动,核 4 独立
SYStem.CONFIG.CORE 0. 1. 2. 3. /Group
SYStem.Mode Attach
Go

这段脚本中有几个容易出错的点。第一,SYStem.Mode Prepare 与 Attach 的区别:Prepare 只建立调试连接但不复位核,适合“芯片已在运行、只想挂上去看”的场景;Attach 会尝试停止核,适合从复位开始调试。第二,CORE.ASSIGN 的编号是逻辑编号,必须与后续 Data.LOAD.Elf 和断点设置中的 core 号一致,否则符号会加载到错误的核。第三,同步组的范围要谨慎:如果把实时核也编入应用核的同步组,应用核断点命中时实时核会被一起停住,可能破坏实时性,因此示例中把核 4 排除在组外。

四、导入后如何判断工程是否正常

工程导入完成后,不要急着下断点。建议按以下顺序做一次快速自检:

  • 用 CORE.LIST 或 SYStem.CORE 查看已分配的核列表,确认数量与编号正确。
  • 逐个切换核,读取 PC 与 SP,确认每个核的寄存器视图能正常刷新,而不是显示全 0 或报错。
  • 在共享内存地址(如 DDR 中的握手标志)上设置一个读断点,让各核运行,观察是否能命中,以验证内存访问路径与符号映射正确。
  • 执行一次 Break,确认同步组内的核都停下,组外的核仍在运行。
若某个核始终无法连接,优先检查该核是否处于复位保持状态、时钟是否使能、电源域是否上电。TRACE32 报“debug port not responding”时,问题通常不在脚本,而在芯片的复位与时钟配置。

完成上述自检后,多核调试工程才算真正导入成功。后续的同步断点、跨核跟踪与性能分析,都建立在这一步的正确性之上。把工程导入当作一次“建立可观测性”的过程,而不是一次简单的连接操作,能显著减少后续调试中的误判。