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”“断点命中后其他核跑飞”“符号加载错位”等问题,根源都在于没有把这三层关系理清。
二、典型工作流:从工程导入到多核同步
一个可复用的多核调试工作流通常包含以下环节,顺序不能随意颠倒:
- 确认硬件拓扑与调试接口:明确芯片有几个核、各自属于哪个簇、复位释放顺序、调试 AP 编号。例如某 SoC 中,Cortex-A55 四核位于 AP0,Cortex-M33 位于 AP2,DSP 位于 AP3。
- 建立 SYStem 并声明 CPU:先连接 DAP,再逐个
SYStem.CPU切换并CORE.ASSIGN。注意每个核的 CPU 类型必须与芯片实际一致,否则寄存器视图会错乱。 - 配置内存映射与访问路径:多核常共享 DDR,但每个核的 MMU/MPU 配置不同。TRACE32 的
MMU或SYStem.MemAccess需要按核设置,否则读到的地址是物理地址还是虚拟地址会混淆。 - 加载符号与初始化脚本:为每个核分别加载 ELF,用
Data.LOAD.Elf指定到对应 core。若核间共享代码段,可只加载一次并设置共享符号。 - 设置同步组与断点:用
SYStem.CONFIG或Break.Set的 group 参数,把需要联动的核编入同一组。同步断点应设在核间通信的握手点或共享内存标志位处。 - 运行与观察:先
Go全部核,再在关键路径上观察各核 PC、共享变量与中断状态。若某核未按预期启动,优先检查复位释放与时钟使能,而不是反复改断点。
下面这张图把上述工作流中“工程导入阶段”的核心对象与连接关系可视化出来,重点表现探针、DAP、多 AP、多核与 TRACE32 逻辑核之间的映射,以及同步控制的作用点。
三、工程环境搭建的关键配置
把图上的关系落到实际工程,需要一份可执行的启动脚本。下面给出一个多核工程导入的示例脚本骨架,参数为教学示例,实际使用时需按芯片手册替换 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,确认同步组内的核都停下,组外的核仍在运行。
完成上述自检后,多核调试工程才算真正导入成功。后续的同步断点、跨核跟踪与性能分析,都建立在这一步的正确性之上。把工程导入当作一次“建立可观测性”的过程,而不是一次简单的连接操作,能显著减少后续调试中的误判。