1. 课程导入与调试环境总览
Linux 启动链调试是嵌入式系统开发中最具挑战性的工作之一。当一块搭载 SoC 的板卡上电后,从 BootROM 的第一条指令到用户空间 init 进程运行,中间要经历多级引导、内核解压、设备树解析、驱动初始化、根文件系统挂载等数十个关键阶段。任何一个环节出错,系统都可能停在黑屏、串口无输出或内核 panic 的状态。传统调试手段——串口打印、LED 指示、JTAG 单步——在启动早期往往力不从心:串口驱动尚未初始化时无法输出,内核崩溃后打印缓冲区可能丢失,而纯 JTAG 又缺乏对 Linux 软件语义的理解。TRACE32 作为 Lauterbach 的硬件辅助调试工具,恰好填补了这一空白:它通过芯片的调试接口直接访问 CPU 寄存器、内存和总线,不依赖目标系统软件栈,因此可以在 BootROM 阶段就建立控制权,并一路跟踪到内核与用户空间。
本课程的目标,是让学员掌握用 TRACE32 对 Linux 启动链进行全流程调试的工程方法。所谓“全流程”,指的是从复位向量开始,经过一级引导(如 BootROM)、二级引导(如 U-Boot SPL、U-Boot proper)、内核解压与启动、直到 init 进程和关键用户态服务的完整路径。适用场景包括:新板卡首次点亮时定位启动卡死点;内核升级后出现早期 panic 的根因分析;设备树配置错误导致驱动 probe 失败的排查;以及安全启动、多核启动、低功耗唤醒等复杂场景下的启动行为验证。需要强调的是,TRACE32 不是替代串口或 ftrace 的万能工具,而是与它们互补——串口提供高层日志,ftrace 提供内核态函数流,TRACE32 则提供从复位开始的、不依赖目标软件的底层可见性。
整体工作流可以概括为“连接—加载—控制—观察—分析”五个环节,但实际执行时并非线性。首先通过 JTAG/SWD 或 Aurora 等调试接口连接目标板,配置正确的 CPU 类型、时钟频率和内存映射;然后加载符号文件(ELF、vmlinux、System.map)和启动脚本,使 TRACE32 能够把物理地址翻译成函数名和源码行;接着设置复位向量处的断点,让 CPU 在第一条指令前停下,从而获得对启动过程的完全控制权;之后通过单步、断点、内存窗口、寄存器窗口和跟踪缓冲区观察启动行为;最后结合调用栈、反汇编和变量值分析问题根因。这个流程中,符号加载和内存映射配置是最容易被忽视却最影响效率的步骤——如果地址映射错误,断点会打在不存在的物理地址上,表现为“断点不触发”或“系统跑飞”。
工具链组成方面,TRACE32 侧包括硬件调试模块(如 PowerDebug、PowerTrace)、软件平台(TRACE32 软件及各类架构支持包)、以及针对 Linux 的 OS Awareness 组件。目标侧则需要调试接口的物理连接、可选的 ETM/ETB 跟踪硬件、以及被调试的启动镜像和符号文件。主机侧通常还需要串口终端、TFTP/NFS 服务器用于加载镜像,以及交叉编译工具链用于生成带调试信息的二进制。一个典型的调试环境连接关系如下:主机通过 USB 或以太网连接 PowerDebug,PowerDebug 通过 JTAG 连接目标 SoC;目标板的串口连接到主机串口终端;主机同时运行 TFTP 服务向目标提供内核和文件系统镜像。这种“调试通道 + 串口通道 + 网络通道”的三通道结构,是 Linux 启动调试的标准配置。
理解这张拓扑图对后续实操至关重要。图中主机侧的 TRACE32 软件通过 USB 或以太网与调试模块通信,调试模块再通过 JTAG 等接口访问目标 SoC 的调试逻辑。这条“调试通道”独立于目标系统的串口和网络通道,因此即使目标系统尚未启动、串口驱动未加载,TRACE32 依然可以读写内存和寄存器。目标板下方的启动链展示了从 BootROM 到用户空间的五个典型阶段,TRACE32 的观测能力覆盖全部阶段——这是它相对于纯软件调试手段的核心优势。
在实际工程中,建议按以下顺序搭建环境:先确认调试模块与目标板的物理连接和供电正常,用 TRACE32 的 SYStem.CPU 命令选择正确的 CPU 类型,用 SYStem.JtagClock 设置合适的 JTAG 时钟(通常从较低频率如 1MHz 开始,稳定后再提高);然后执行 SYStem.Up 让调试器接管 CPU;接着用 Data.LOAD.Elf 加载 vmlinux 或 U-Boot 的 ELF 文件,用 MMU 相关命令配置地址转换;最后在复位向量地址处设置断点并复位目标板,验证能否在第一条指令处停下。如果断点不触发,优先检查 CPU 类型、JTAG 时钟和复位配置,而不是怀疑断点地址本身。
start_kernel 断点。如果 BootROM 或 SPL 阶段已经卡死,内核断点永远不会触发,而调试器不会给出明确提示。先验证复位向量可控,再逐步向后推进,是更可靠的策略。