3. PolarFire SoC启动流程

PolarFire SoC 的启动不是“上电即跳 Linux”这么简单,而是一条由硬件复位逻辑、片上只读代码、非易失存储、HSS 固件和镜像解析器共同组成的多级链路。理解这条链路的关键,是分清每一级“谁在跑、代码在哪里、下一步从哪里取、失败时如何回退”。只有把 BootROM、eNVM、sNVM、HSS 和启动模式放在同一张图上,才能解释为什么同一块板子既能进 U-Boot、又能进 Linux,还能在镜像损坏时停在 HSS 提示符。

一、复位后的第一段代码:BootROM 与启动模式采样

PolarFire SoC 的 E51 监控核在复位释放后,首先执行固化在芯片内部的 BootROM。BootROM 不依赖外部存储,它做三件事:采样启动模式引脚、初始化最小必要时钟与存储控制器、按启动模式选择镜像来源。启动模式通常由板级跳线或 eNVM 中的配置字决定,常见组合包括从 eNVM 启动、从 sNVM 启动、从外部 SPI Flash 启动,以及通过 JTAG/调试器加载。BootROM 只认“镜像头 + 校验”,不解析 Linux 内核,因此它必须把控制权交给一个格式正确的 HSS 镜像。

这里有一个容易混淆的点:eNVM 和 sNVM 都是片上非易失存储,但角色不同。eNVM 容量较大,通常存放 HSS 固件、U-Boot 甚至小型裸机程序;sNVM 容量小,常用于存放启动配置、设备序列号、密钥或安全启动相关元数据。BootROM 可以按启动模式从 eNVM 或 sNVM 读取镜像,但真正承担“启动操作系统”职责的是 HSS,而不是 BootROM 本身。

PolarFire SoC 从复位到 Linux/裸机入口的启动链路 复位释放 E51 核取指 BootROM 采样启动模式 / 校验镜像头 启动模式选择 eNVM / sNVM / SPI Flash JTAG 调试加载 非易失存储 eNVM:HSS / U-Boot sNVM:配置 / 密钥 HSS 固件 初始化 DDR / 外设 / 时钟 解析镜像 / 加载下一级 镜像格式 头部 + 载荷 + 校验 HSS / U-Boot / 裸机 U-Boot / 裸机入口 跳转到入口地址 准备内核启动参数 Linux 内核 解压 / 挂载根文件系统 进入用户空间 校验失败 / 无镜像 停在 HSS 提示符 或等待 JTAG 加载 关键判断:BootROM 只负责“找到并校验 HSS 镜像”;HSS 负责“初始化硬件并加载下一级”;镜像格式决定每一级能否被正确解析。 eNVM 与 sNVM 是镜像来源,不是执行主体;启动模式决定 BootROM 从哪个来源取镜像。

二、HSS:真正把系统“带起来”的固件

HSS(Hart Software Services)是 PolarFire SoC 启动链的中枢。它通常由 BootROM 从 eNVM 加载到 L2 缓存或片上 SRAM 中运行,随后完成 DDR 训练与初始化、时钟树配置、外设引脚复用、MMC/QSPI 控制器初始化等。HSS 还负责多核管理:E51 监控核保持运行,U54 应用核在需要时才被释放。HSS 的镜像本身遵循特定格式,头部包含入口地址、载荷长度、校验和以及目标执行区域等信息。BootROM 校验通过后,才会把控制权交给 HSS 入口。

在实际工程中,HSS 通常以 .elf 或 .bin 形式提供,并通过 SoftConsole 或 Libero SoC 的“Generate HSS Image”流程生成可烧录镜像。一个典型的 HSS 镜像头部会包含 magic number、版本号、载荷偏移、载荷大小和 CRC。如果 CRC 不匹配,BootROM 会拒绝跳转,系统停在 BootROM 错误状态或等待调试器介入。因此,烧录 eNVM 时不能只写载荷,必须写入完整镜像头。

三、eNVM 与 sNVM 的分工

eNVM 是 PolarFire SoC 内部的大容量非易失存储,通常划分为多个区域:HSS 区、U-Boot 区、环境变量区、裸机应用区。sNVM 则更小,常用于存放启动配置字、设备唯一 ID、安全启动公钥哈希或用户自定义参数。BootROM 在启动时会读取 sNVM 中的配置字来判断启动模式,也可能从 sNVM 读取安全启动相关元数据。两者在地址空间和访问方式上都不同,不能混用。

一个常见的教学示例划分如下:eNVM 起始地址 0x20200000 存放 HSS 镜像,偏移 0x00080000 存放 U-Boot 镜像,偏移 0x00100000 存放裸机应用;sNVM 起始地址 0x21000000 存放启动配置字。这些地址属于示例,实际应以具体器件手册和 Libero 配置为准。烧录时通常使用 FlashPro Express 或 fpgenprog 工具,将 .spi 或 .bin 文件写入对应区域。

四、镜像格式与启动模式的关系

镜像格式决定了“谁能被谁加载”。BootROM 只识别 HSS 镜像格式;HSS 识别 U-Boot 镜像格式和裸机镜像格式;U-Boot 识别 Linux 内核镜像格式(如 FIT、Image、zImage)。如果启动模式设为从 eNVM 启动,BootROM 会从 eNVM 固定偏移读取 HSS 镜像头;如果设为从 sNVM 启动,则从 sNVM 读取配置和镜像;如果设为 JTAG 启动,BootROM 会等待调试器通过 JTAG 写入镜像到 SRAM 并跳转。启动模式通常由板上的模式引脚在上电复位时采样,采样值锁存在寄存器中供 BootROM 读取。

镜像格式的校验失败是启动失败最常见的原因之一。例如,HSS 镜像头中的载荷长度与实际写入长度不一致,BootROM 会认为镜像不完整;CRC 不匹配,BootROM 会拒绝跳转。此时串口通常没有任何输出,因为 HSS 还没开始运行。排查时应先确认烧录地址、镜像头字段和启动模式是否一致,再用 JTAG 读取 BootROM 状态寄存器判断卡在哪一步。

五、从 HSS 到 Linux/裸机入口的交接

HSS 完成硬件初始化后,会根据镜像头中的入口地址跳转到下一级。如果下一级是 U-Boot,HSS 会把 U-Boot 镜像从 eNVM 或 QSPI 加载到 DDR 指定地址,然后释放 U54 核并跳转。U-Boot 继续加载 Linux 内核、设备树和根文件系统,最终启动 Linux。如果下一级是裸机程序,HSS 直接跳转到裸机入口,裸机程序从 main 开始执行。无论哪种路径,HSS 都会保留 E51 监控核用于系统管理,U54 核则按需释放。

实际调试时,可以通过串口观察 HSS 打印的启动日志,确认它是否成功初始化 DDR、是否找到下一级镜像、跳转地址是否正确。如果 HSS 打印停在“Loading next image”之后没有后续输出,通常说明下一级镜像格式或入口地址有问题。此时可以用 hss-payload 工具检查镜像头,或通过 JTAG 读取 U54 核的 PC 值判断是否已经跳转。

启动链路排查顺序建议:先确认启动模式引脚采样值,再确认 BootROM 是否能读到 HSS 镜像头,然后确认 HSS 是否完成 DDR 初始化,最后确认下一级镜像入口地址和校验是否正确。串口无输出时优先怀疑 BootROM 阶段;串口有 HSS 日志但无后续输出时优先怀疑镜像格式或入口地址。

六、启动模式与镜像格式的对应关系

启动模式 镜像来源 BootROM 行为 典型镜像格式
eNVM 启动 eNVM 固定偏移 读取 HSS 镜像头并校验 HSS .bin / .elf
sNVM 启动 sNVM 配置区 读取配置字和镜像元数据 HSS + 配置字
SPI Flash 启动 外部 QSPI Flash 通过 SPI 控制器读取镜像 HSS .spi
JTAG 启动 调试器写入 SRAM 等待 JTAG 写入并跳转 任意可执行镜像

理解这张对应关系后,就能解释很多现场现象:比如 eNVM 中只烧了 U-Boot 而没有 HSS,BootROM 找不到合法 HSS 镜像头,系统自然无法启动;又比如启动模式引脚被误设为 JTAG,BootROM 会一直等待调试器,串口不会有任何输出。启动链路的每一级都依赖上一级的正确交接,任何一级的镜像格式、地址或校验出错,都会导致整条链路中断。