2. 多核架构与启动模型

多核调试的第一个认知门槛,不是“怎么连上第二个核”,而是先判断目标芯片到底运行在哪种多核模型下。AMP、SMP、BMP 三种模型在启动顺序、地址空间、操作系统实例和核间职责上差异很大,直接决定了 TRACE32 应该用 SYStem.CPU 逐个核配置,还是用 SMP 模式统一接管,以及断点、单步、内存访问会落在哪个核上。

三种模型的本质差异

AMP(Asymmetric Multiprocessing,非对称多处理):每个核运行独立的程序或操作系统实例,核之间没有统一的调度器。典型场景是主核跑 Linux 或 RTOS,从核跑裸机实时任务或另一个 RTOS。各核可以有自己的异常向量表、栈和地址映射,核间通过共享内存、Mailbox、IPI 或硬件信号量通信。启动上通常由 BootROM 先释放主核,主核初始化 DDR、时钟、外设后,再通过写核启动寄存器(如 ARM 的 CPUxWAIT/CPUxRST、RISC-V 的 hart 释放地址)逐个释放从核。

SMP(Symmetric Multiprocessing,对称多处理):所有核共享同一份操作系统镜像和同一套地址空间,由 OS 调度器把线程动态分配到任意核。核之间是对等的,没有固定的主从职责。启动时通常由一个核(Boot CPU)完成早期初始化,其余核在 OS 的 SMP 启动阶段被唤醒并进入调度。调试视角下,SMP 的关键是“一个逻辑视图对应多个物理核”,断点命中后需要判断是哪个核触发。

BMP(Bound Multiprocessing,绑定多处理):介于两者之间。它共享同一个 OS 镜像和地址空间,但线程或进程被绑定到指定核上运行,调度器不做跨核迁移。BMP 常见于对确定性、缓存局部性或实时性有要求的场景,例如把中断处理线程绑定到固定核。启动流程与 SMP 接近,但配置上多了 CPU 亲和性绑定。

AMP / SMP / BMP 启动模型与调试接管方式 AMP 非对称多处理 主核 Core0 BootROM → DDR/时钟 → OS-A 写核启动寄存器 从核 Core1 裸机 / RTOS-B,独立向量表 从核 Core2 裸机 / RTOS-C,独立栈 核间通信 共享内存 / Mailbox / IPI 硬件信号量 TRACE32 接管 SYStem.CPU 逐核声明 CORE.ASSIGN 分配核号 各核独立断点/单步 需分别加载符号表 SMP 对称多处理 Boot CPU Core0 早期初始化 → 唤醒其余核 OS SMP 启动流程 Core1 / Core2 / Core3 进入调度器,等待任务 共享资源 同一 OS 镜像 / 同一地址空间 统一调度器,线程可迁移 TRACE32 接管 SYStem.CPU 声明多核 SYStem.Mode SMP 统一视图 断点命中显示触发核号 单步需指定核或全停 符号表只需加载一次 内存视图全局一致 适合 Linux / 通用 RTOS BMP 绑定多处理 Boot CPU Core0 初始化 → 唤醒 → 设置亲和性 绑定线程到指定核 Core1 / Core2 / Core3 固定运行绑定线程,不迁移 共享 + 绑定 同一 OS 镜像 / 同一地址空间 CPU 亲和性决定线程归属 TRACE32 接管 SYStem.Mode SMP 基础上 结合 OS 亲和性视图 断点需关注绑定核 单步可限定目标核 符号表共享 适合确定性实时场景 中断线程绑定固定核 判断顺序:先看 OS 实例数 → 再看地址空间是否共享 → 最后看线程是否绑定核,据此选择 TRACE32 接管模式

主核与从核的职责划分

在 AMP 中,主核通常承担“系统启动者”和“资源管理者”的角色:上电后从 BootROM 开始执行,完成 PLL、DDR、时钟树、引脚复用、外设控制器等基础初始化,建立堆栈和异常向量,然后加载从核镜像到指定地址,最后写核启动寄存器释放从核。从核被释放后,从自己的入口地址开始执行,通常只做与自身任务相关的初始化,例如配置本地定时器、使能本地中断、建立核间通信通道,然后进入主循环或等待 IPI。

职责划分的关键在于“谁拥有共享资源”。DDR 控制器、系统级时钟、全局中断控制器一般由主核初始化,从核只读取配置结果;而各核的 MPU/Cache、本地定时器、本地中断使能则由各核自行管理。如果从核在未确认 DDR 可用时就访问共享内存,会出现挂死或数据错误,这是 AMP 调试中最常见的启动故障之一。

在 SMP/BMP 中,主从职责被弱化。Boot CPU 只负责早期初始化和唤醒其余核,之后所有核进入同一个调度器。BMP 额外通过 CPU 亲和性把特定线程绑定到特定核,例如把网络中断下半部绑定到 Core2,把控制环绑定到 Core3,从而获得更可预测的响应时间。

TRACE32 调试视角的接管方式

TRACE32 对多核的支持核心是“先声明拓扑,再选择接管模式”。以常见的四核 ARM Cortex-A 为例,AMP 场景下典型配置如下:

; AMP:逐核声明与分配
SYStem.CPU CortexA53
SYStem.CONFIG.CORE 0. 0. 0. 0.     ; 声明物理核
SYStem.CONFIG.CORE 1. 0. 0. 1.
SYStem.CONFIG.CORE 2. 0. 0. 2.
SYStem.CONFIG.CORE 3. 0. 0. 3.
CORE.ASSIGN 0. 1. 2. 3.           ; 逻辑核号映射
SYStem.Mode Attach                ; 分别 attach 各核
Data.LOAD.Elf core0.elf /Core 0
Data.LOAD.Elf core1.elf /Core 1

每个核有独立的符号表和断点集合,单步只影响当前选中的核。调试时用 CORE.SELECT 切换当前核,用 CORE.LIST 查看各核状态。若从核一直停在入口未运行,应检查主核是否真正写了核启动寄存器,以及从核入口地址是否与镜像链接地址一致。

SMP 场景下则使用统一视图:

; SMP:统一接管
SYStem.CPU CortexA53
SYStem.CONFIG.CORE 0. 0. 0. 0.
SYStem.CONFIG.CORE 1. 0. 0. 1.
SYStem.CONFIG.CORE 2. 0. 0. 2.
SYStem.CONFIG.CORE 3. 0. 0. 3.
SYStem.Mode Attach
SYStem.Mode SMP                   ; 进入 SMP 统一视图
Data.LOAD.Elf linux.elf           ; 符号表只加载一次

此时断点命中后,TRACE32 会显示触发核号;单步默认只推进当前核,若希望全核同步停止,需要启用 SMP 全停模式。内存视图是全局一致的,因为所有核共享同一地址空间。BMP 的接管方式与 SMP 基本相同,区别在于分析线程行为时要结合 OS 的亲和性信息,判断某个线程是否只能在特定核上被观察到。

判断目标属于哪种模型,可以按三步走:第一,看有几个 OS 实例,多个实例通常是 AMP;第二,看地址空间是否共享,共享则排除 AMP;第三,看线程是否被绑定到固定核,绑定则是 BMP,不绑定则是 SMP。这个顺序能快速缩小 TRACE32 配置范围。

启动差异带来的调试影响

AMP 的启动是“主核串行释放从核”,因此从核的启动时刻取决于主核的执行进度。调试从核早期代码时,如果从核还没被释放,TRACE32 无法在其上设置有效断点,需要先在主核写核启动寄存器处设断点,确认释放动作发生后再切换到从核。SMP/BMP 的启动是“Boot CPU 唤醒其余核后共同进入调度”,从核在 OS SMP 启动阶段被唤醒,调试重点通常放在调度器初始化和核间中断路径上。

另一个差异是复位行为。AMP 中各核可以独立复位,主核复位不一定复位从核,调试时要确认复位源和复位范围;SMP/BMP 中通常整芯片复位,所有核一起回到 BootROM。理解这些差异,才能在 TRACE32 中正确设置断点、单步和内存访问,避免把“核没被释放”误判为“程序跑飞”。