4. 启动流程与Bootloader设计

S32G 的启动不是“上电即跑应用”这么简单,而是一条由硬件固化逻辑、安全子系统、引导加载程序和操作系统逐级接力的信任链。理解这条链,是设计网关固件升级、A/B 分区和 OTA 回滚的前提。本节按“BootROM → HSE 固件 → 引导加载程序 → 内核”的顺序展开,并给出可落地的分区与回滚设计。

4.1 多阶段启动的整体链路

S32G 上电后,最先运行的是芯片内部固化的 BootROM。它读取复位配置引脚(如 BOOT_CFG 相关引脚)确定启动介质:QSPI NOR、SD/eMMC、串行下载等。BootROM 只做最小化的工作——初始化必要时钟、从所选介质读取引导头(Boot Header),校验镜像格式与完整性,然后把控制权交给下一级镜像。它不解析文件系统,也不理解 U-Boot 或 Linux,因此引导头必须放在介质固定偏移处,且包含镜像长度、目标地址、校验信息等字段。

BootROM 之后通常进入 HSE(Hardware Security Engine)固件加载阶段。HSE 是 S32G 内部独立的安全核,负责密钥管理、加解密、安全启动校验和生命周期管理。HSE 固件本身需要先被加载并启动,之后才能为后续镜像提供签名验证、AES 解密等服务。在启用安全启动的产品中,BootROM 会校验 HSE 固件签名,HSE 再校验引导加载程序,形成逐级信任。若某级校验失败,启动会停在 BootROM 或 HSE 阶段,表现为无串口输出或固定错误码。

引导加载程序(通常为 U-Boot)是启动链中第一个“可编程”的环节。它初始化 DDR、时钟、外设,加载内核与设备树,并可根据环境变量选择启动哪个分区。对于网关产品,U-Boot 还承担 A/B 分区选择、启动计数、回滚判断等职责,是 OTA 机制的关键落点。

S32G 多阶段启动与信任链 BootROM 固化代码 读引导头/选介质 HSE 固件 安全核启动 密钥/签名/解密 U-Boot DDR/外设初始化 A/B 选择/回滚 Linux 内核 挂载 rootfs 启动应用 网关应用 CAN/Eth 转发 OTA 客户端 校验 校验 加载 加载 A/B 分区与 OTA 回滚机制 Slot A(当前运行) U-Boot A Kernel A RootFS A 状态:good / bootcount=0 Slot B(待升级/回滚) U-Boot B Kernel B RootFS B 状态:trial / bootcount=1 OTA 写入 B 分区 启动失败 → 回滚到 A

4.2 U-Boot 移植要点

S32G 的 U-Boot 移植通常从 NXP 官方 BSP 出发,重点修改以下几处。第一是 DDR 初始化参数:S32G 支持多片 DDR,需要根据实际板卡的容量、位宽、时序配置 DDR 控制器,参数错误会导致 U-Boot 在 DDR 校准阶段挂死。第二是启动介质配置:QSPI 启动需要正确设置 FMC 控制器和引导头偏移,eMMC 启动则要配置 USDHC 和分区表。第三是环境变量存储位置:建议将 env 放在独立分区或 eMMC 的 boot 分区,避免与内核镜像混放。

移植完成后,通过串口观察启动日志是判断阶段是否正常的最直接手段。典型日志会依次出现 BootROM 版本、HSE 固件加载信息、U-Boot 版本与 DDR 容量、内核解压与启动信息。若日志停在某一行,即可定位到对应阶段。例如停在 “Loading HSE firmware” 说明 HSE 镜像或签名有问题;停在 “DRAM:” 说明 DDR 参数需要调整。

4.3 A/B 分区与 OTA 回滚设计

A/B 分区的核心思想是:始终保留一个可启动的“已知良好”分区,新固件写入另一个分区,启动成功后再切换。具体实现依赖 U-Boot 环境变量与启动计数。常用变量包括 bootslot(当前槽位)、bootcount(启动尝试次数)、upgrade_available(是否有待验证升级)。典型逻辑如下:

# U-Boot 环境变量示例(A/B 回滚)
bootslot=A
bootcount=0
bootlimit=3
upgrade_available=0

# 启动脚本片段
if test "${upgrade_available}" = "1"; then
    if test ${bootcount} -ge ${bootlimit}; then
        # 连续失败,回滚到另一槽
        if test "${bootslot}" = "A"; then
            setenv bootslot B
        else
            setenv bootslot A
        fi
        setenv bootcount 0
        setenv upgrade_available 0
        saveenv
    fi
fi
# 根据 bootslot 加载对应分区内核

在 Linux 侧,OTA 客户端负责下载新镜像、校验签名、写入非当前槽位,然后设置 upgrade_available=1 并重启。新槽位首次启动时,系统服务需要在确认应用正常后执行“提交”操作:将 upgrade_available 清零、bootcount 清零,并标记该槽为 good。若启动过程中应用崩溃或看门狗复位,bootcount 会在每次启动时递增,达到 bootlimit 后 U-Boot 自动切回旧槽,实现回滚。

回滚能否成功,关键在于“提交”动作必须由应用层确认,而不是内核启动成功就提交。否则内核能启动但应用崩溃的场景将无法触发回滚。

4.4 安全启动与生命周期

若产品启用安全启动,BootROM 会校验 HSE 固件,HSE 校验 U-Boot,U-Boot 校验内核与 rootfs。签名密钥通常存放在 HSE 的密钥存储区,生命周期状态(如 OEM 生产、现场部署)决定哪些密钥可用。设计时需注意:一旦熔断进入安全生命周期,未签名镜像将无法启动,因此调试阶段应保留可回退的配置。OTA 升级的镜像也必须使用与安全启动匹配的签名格式,否则写入后无法启动,只能依赖 A/B 回滚恢复。

4.5 启动参数与调试检查表

观察点正常表现异常与排查方向
BootROM 阶段串口输出 BootROM 版本无输出:检查 BOOT_CFG 引脚、供电、时钟
HSE 固件提示 HSE firmware loaded失败:检查 HSE 镜像签名与生命周期
DDR 初始化打印 DDR 容量挂死:核对 DDR 时序与位宽参数
U-Boot 启动出现 U-Boot 提示符或自动启动反复重启:检查 bootcount 与 bootlimit
内核启动解压并挂载 rootfspanic:检查 bootargs 中 root= 指向的槽位
应用提交upgrade_available 清零未清零:下次启动仍按 trial 计数,可能误回滚

实际调试时,建议先用非安全启动模式打通 BootROM → U-Boot → 内核 → rootfs 全链路,再逐步启用 HSE 安全启动和 A/B 回滚。每启用一项,都通过串口日志和 fw_printenv 确认环境变量状态,确保回滚路径在真实故障下可被触发。