2. S32G芯片启动与多核引导流程

S32G 是一颗典型的多核异构实时控制与应用处理协同芯片:内部同时包含 Cortex-M7 实时核、Cortex-A53 应用核、HSE 安全子系统以及丰富的通信外设。上电之后,这些核并不是同时开始执行用户代码,而是由芯片内部的 BootROM 按固定顺序逐级“唤醒”,再由 HSE 完成安全校验,最后才把控制权交给用户镜像。理解这条启动链,是设计 S32G 双核协同系统、划分初始化职责、排查“上电不启动”类问题的前提。

一、启动链的整体顺序

S32G 的启动可以概括为四个阶段:BootROM 阶段、HSE 安全启动阶段、M7 引导阶段、A53 引导阶段。它们之间存在严格的先后依赖:BootROM 必须先完成基本时钟与启动介质探测,HSE 才能接管安全校验;HSE 校验通过后,M7 才能从被授权的镜像地址取指;M7 完成实时域初始化后,才由它或 HSE 触发 A53 的释放与启动。任何一级失败,后续核都不会被释放。

需要特别注意的是,S32G 的 BootROM 是固化在芯片内部的只读代码,用户无法修改其行为,只能通过外部启动配置(如 BOOT_CFG 引脚、eFuse、启动头)影响它的选择。因此“启动设计”的本质,是在 BootROM 给定的框架内,正确安排 HSE、M7、A53 的镜像布局与握手关系。

S32G 上电启动链:BootROM → HSE → M7 → A53 ① BootROM 上电复位 / 时钟初始化 读取 BOOT_CFG 引脚 探测启动介质 加载启动头 → HSE ② HSE 安全启动 读取镜像 + 签名 AES/ECC 校验 校验通过 → 授权 失败 → 锁定不释放 ③ M7 实时核 从授权地址取指 时钟/引脚/中断初始化 CAN/ETH 实时外设 释放 A53 复位 ④ A53 应用核 Linux / RTOS MMU / Cache DDR 初始化 应用服务启动 协同初始化任务分工 BootROM 时钟、启动介质、 启动头解析 HSE 密钥管理、镜像验签、 安全状态与授权 M7 实时外设、中断、 核间通信、释放 A53 A53 MMU/Cache、DDR、 应用与网络服务 M7 ↔ A53 协同握手(核间通信) M7 写共享内存标志 触发 MU 中断 A53 读取并确认

二、BootROM 阶段做了什么

上电复位后,芯片首先执行固化 BootROM。它完成三件事:第一,根据复位配置建立最基本的系统时钟,使内部总线可以工作;第二,采样 BOOT_CFG 引脚或读取 eFuse,确定从哪个介质启动(QSPI NOR、SD/eMMC、串行下载等);第三,从该介质读取启动头(Boot Header),解析出 HSE 固件、M7 镜像、A53 镜像的地址与长度,并把 HSE 固件加载到其专用 RAM 中。

BootROM 本身不做镜像验签,它只负责“把正确的镜像搬到正确的位置,并把控制权交给 HSE”。因此启动头中的地址、长度、校验字段必须与镜像实际布局一致,否则会出现“BootROM 找不到镜像”或“HSE 固件加载失败”的早期故障。

三、HSE 安全启动阶段

HSE(Hardware Security Engine)是 S32G 内部独立的安全子系统,拥有自己的内核、RAM 和密钥存储。BootROM 把 HSE 固件加载完成后,HSE 开始运行,并接管后续镜像的验证工作。典型流程是:HSE 读取 M7 与 A53 镜像及其签名,使用 eFuse 中烧录的公钥或对称密钥进行验签/解密;校验通过后,HSE 将对应核标记为“已授权”,并允许其从指定地址取指。

如果验签失败,HSE 会阻止该核释放,芯片停留在安全锁定状态。这一机制意味着:在开发阶段如果频繁修改镜像,必须同步更新签名,否则会出现“代码明明烧进去了,但核不启动”的现象。排查时应优先确认签名是否与当前镜像匹配、密钥是否正确烧录。

四、M7 与 A53 的启动顺序与职责划分

在 S32G 的典型协同设计中,M7 先启动,A53 后启动。原因在于 A53 运行 Linux 等应用系统时,需要 DDR、MMU、Cache 等复杂初始化,而这些初始化往往依赖 M7 先建立稳定的时钟与外设环境。M7 启动后通常完成以下工作:

  • 初始化实时域时钟、引脚复用与中断控制器;
  • 配置 CAN、LIN、以太网等实时通信外设;
  • 建立与 A53 的核间通信通道(MU、共享内存);
  • 完成必要的安全与看门狗配置;
  • 通过寄存器或 MU 消息释放 A53 复位,触发 A53 启动。

A53 被释放后,从 HSE 授权的地址开始执行引导代码(如 U-Boot SPL 或 ATF),完成 DDR 训练、MMU/Cache 配置,随后加载操作系统。A53 启动完成后,通过核间通信向 M7 发送“应用域就绪”信号,双方进入协同运行状态。

五、协同初始化的关键握手

M7 与 A53 的协同初始化依赖明确的握手协议。常见做法是:在共享内存中定义一组状态标志,M7 完成实时域初始化后写入“M7_READY”,再通过 MU 向 A53 发送中断;A53 启动后读取该标志,确认 M7 已就绪,再写入“A53_READY”并回送中断。双方都确认对方就绪后,才允许跨核数据通路开始工作。

下面给出一个共享内存握手结构的示例,用于说明字段划分方式(示例参数,非实测值):

/* 共享内存握手结构示例(地址与字段为教学示例) */
typedef struct {
    volatile uint32_t m7_ready;      /* M7 写 0x5A5A0001 表示就绪 */
    volatile uint32_t a53_ready;     /* A53 写 0x5A5A0002 表示就绪 */
    volatile uint32_t m7_heartbeat;  /* M7 周期递增,用于活性检测 */
    volatile uint32_t a53_heartbeat; /* A53 周期递增 */
    volatile uint32_t error_code;    /* 任一侧异常时写入错误码 */
} ipc_handshake_t;

/* M7 侧:初始化完成后 */
ipc->m7_ready = 0x5A5A0001;
MU_SendMsg(MU_A53, 0, IPC_MSG_M7_READY);

/* A53 侧:启动完成后 */
ipc->a53_ready = 0x5A5A0002;
MU_SendMsg(MU_M7, 0, IPC_MSG_A53_READY);

实际调试时,可以通过观察 m7_ready 与 a53_ready 是否按预期置位,快速判断启动卡在哪一级:若 m7_ready 始终为 0,说明 M7 未完成初始化或未通过 HSE 校验;若 m7_ready 已置位而 a53_ready 长期为 0,则应检查 A53 镜像地址、DDR 初始化以及 MU 中断配置。

启动排查建议:先确认 BootROM 是否成功加载启动头,再确认 HSE 验签是否通过,最后检查 M7 是否释放 A53。按“BootROM → HSE → M7 → A53”的顺序逐级定位,比直接怀疑应用代码更高效。

六、启动配置中的常见注意点

第一,启动头中的镜像地址必须与链接脚本、烧录工具配置一致,任何一处偏移都会导致取指异常。第二,HSE 固件与用户镜像的签名必须成对更新,不能只替换镜像而沿用旧签名。第三,M7 释放 A53 的时机应放在实时域关键外设初始化完成之后,避免 A53 启动后访问尚未就绪的资源。第四,核间通信的共享内存区域应在双方地址映射中保持一致,并注意 Cache 一致性处理。

把这条启动链理解清楚之后,后续的镜像布局、HSE 密钥配置、M7/A53 任务划分才有稳定的基础。启动顺序不是可随意调整的软件流程,而是由芯片硬件与安全机制共同约束的固定路径,设计时必须顺着这条路径安排各核的初始化职责。