3. SoC 启动与复位调试

SoC 上电后的前几百毫秒,是软硬件协同调试中最难观测、也最容易出问题的阶段。此时 CPU 刚退出复位,DDR 尚未初始化,串口可能还没配置,操作系统和调试代理都不存在。一旦启动失败,现象往往只是“没有任何输出”或“电流停在某个值”,传统打印和断点手段几乎失效。本章围绕上电复位序列、BootROM 跟踪、启动模式选择、早期启动失败定位以及 TRACE32 脚本化复位控制展开,目标是让工程师能够在“黑屏”阶段建立可观测性。

上电复位序列与启动模式选择

典型 SoC 的复位并非单一信号,而是由电源管理芯片(PMIC)输出的多路电源就绪信号、外部复位输入、内部上电复位(POR)电路和看门狗复位共同作用的结果。以一颗常见的 ARM 架构 SoC 为例,其复位释放顺序大致为:核心电源稳定 → PLL 锁定 → 复位控制器释放 CPU 复位 → CPU 从复位向量取指。复位向量地址由芯片的启动模式引脚(Boot Mode Pin)在复位释放瞬间采样决定,常见组合如下表所示。

BOOT[2:0]启动介质典型用途
000BootROM(内部 ROM)正常量产启动
001SPI NOR Flash小容量固件
010eMMC主流存储启动
011SD 卡开发调试
100UART 下载工厂烧录/救砖
101USB 下载快速恢复
110/111保留/测试模式JTAG 直连

启动模式引脚的电平必须在复位释放前保持稳定,否则采样结果可能落在保留组合上,导致 CPU 进入未定义状态。调试时若发现“同一固件有时能启动、有时不能”,应优先用示波器检查 BOOT 引脚在复位释放沿附近的电平是否干净。

BootROM 跟踪与早期启动失败定位

BootROM 是固化在芯片内部的一段只读代码,负责初始化最基础的时钟、扫描启动介质、加载第一阶段引导程序(如 SPL 或 BL1)。它通常不提供源码,但会通过一组固定的“启动进度寄存器”或“启动状态码”暴露执行阶段。TRACE32 可以在 CPU 复位释放后立即接管,通过读取这些寄存器判断 BootROM 走到了哪一步。

例如,某 SoC 的 BootROM 状态寄存器位于 0x1E0000A0,其低 8 位含义为:0x01 表示时钟初始化完成,0x02 表示介质探测完成,0x03 表示镜像头校验通过,0x04 表示已跳转到 SPL。若读回值为 0x02,说明 BootROM 卡在镜像头校验,常见原因是存储介质中前 4KB 的头部签名或长度字段不合法。此时可用 TRACE32 直接 dump 介质前 64 字节,与 BootROM 期望的格式逐字段比对。

BootROM 阶段通常已使能看门狗。若在 BootROM 中长时间停留调试,需先通过 TRACE32 写看门狗喂狗寄存器,或临时关闭看门狗,否则会被复位打断。

TRACE32 脚本化复位控制

手动点击复位按钮难以复现“上电—复位释放—BootROM—SPL”这一完整时序。TRACE32 提供 SYStem.RESet、SYStem.Up、SYStem.Mode 等命令,可编写 .cmm 脚本实现可重复的复位控制。下面是一段示例脚本,用于在复位释放后立即停住 CPU 并读取启动状态。

; reset_boot_trace.cmm
SYStem.Mode Down
SYStem.CPU CortexA53
SYStem.JtagClock 10MHz
SYStem.Mode Prepare
SYStem.RESet
SYStem.Up
; 复位释放后立即停住
Break.Set 0xFFFF0000 /Program
Go
WAIT !STATE.RUN()
; 读取 BootROM 状态寄存器
PRINT "BOOT_STATUS = " %Hex(Data.Long(0x1E0000A0))
; dump 介质头部
Data.Dump 0x00000000 /Long
ENDDO

脚本中 SYStem.Mode Prepare 让调试器在复位释放前完成 JTAG 连接准备,SYStem.RESet 触发目标复位,SYStem.Up 在复位释放后接管 CPU。关键点是 Break.Set 设在复位向量处,使 CPU 一退出复位就停在第一条指令,从而保留最原始的启动现场。

启动失败定位的典型路径

早期启动失败通常表现为三类:完全无输出、输出乱码、输出停在某一行。完全无输出时,先用 TRACE32 确认 CPU 是否真的在取指——若 PC 停在复位向量且反复重启,多半是看门狗或电源问题;若 PC 已跑飞,则检查启动模式引脚和复位向量映射。输出乱码通常是 UART 时钟源或分频配置错误,可在 SPL 中打印时钟寄存器验证。输出停在某一行,则结合 BootROM 状态码和 SPL 的打印点,定位到具体初始化步骤。

SoC 上电复位与启动跟踪链路 PMIC 上电 多路电源就绪 POR / 复位控制器 释放 CPU 复位 BOOT[2:0] 采样 复位释放沿锁存 BootROM 时钟初始化 介质探测 / 头部校验 启动状态寄存器 0x1E0000A0 01→02→03→04 SPL / BL1 DDR 初始化 加载 U-Boot TRACE32 SYStem.RESet SYStem.Up Break.Set 复位向量 读状态 / Dump 介质 失败判读 无输出 → 查复位/看门狗 乱码 → 查 UART 时钟 卡住 → 查状态码 电源/复位 BootROM 状态寄存器 SPL TRACE32 判读分支

上图把电源、复位、启动模式采样、BootROM、状态寄存器、SPL 以及 TRACE32 的介入点放在同一条链路上,便于对照定位。实际调试时,建议先用脚本在复位向量处停住,确认 PC 和启动模式采样值,再单步或设断点跟踪 BootROM 的状态码变化,最后进入 SPL 检查 DDR 初始化是否成功。这样即使没有任何串口输出,也能通过 JTAG 和状态寄存器还原启动过程。

不同 SoC 的 BootROM 状态寄存器地址和编码并不通用,必须查阅对应芯片的 TRM。本文中的 0x1E0000A0 和状态码仅为教学示例,实际使用时请以芯片手册为准。

把复位控制脚本化之后,每次启动失败都可以用同一条命令序列复现现场,避免手工操作引入的时序差异。进一步地,可以把状态码读取、介质头部 dump、PC 采样值打印合并到一个 .cmm 脚本中,形成“一键启动诊断”流程,显著缩短早期启动问题的定位时间。