3. Versal启动流程与引导镜像构建

Versal ACAP 的启动过程与 Zynq-7000、Zynq UltraScale+ 有本质区别:它不再由单一 FSBL 主导,而是由固化在芯片内的 BootROM 与运行在 PMC(Platform Management Controller)中的 PLM(Platform Loader and Manager)协同完成。理解这两级引导的分工,是构建 BOOT.BIN 的前提。

BootROM 与 PLM 的职责划分

上电或复位后,PMC 内的 BootROM 首先执行。它只做三件事:采样启动模式引脚、初始化最小必要的外设接口(QSPI、SD/eMMC、USB、JTAG 等)、从所选启动设备读取 PDI(Programmable Device Image)头部并校验。BootROM 不解析完整的镜像内容,它只负责把 PLM 固件加载到 PMC RAM 并跳转执行。

PLM 接管后承担真正的平台管理职责:解析 PDI 中的分区表、按顺序加载 PLM 自身扩展、PMU 固件、PL 配置比特流(PDI 中的 PL 段)、以及各处理单元的镜像(Cortex-A72 的 APU、Cortex-R5 的 RPU)。PLM 还负责电源域管理、时钟配置、复位释放顺序,并在加载完成后把控制权交给 APU 或 RPU 的入口地址。因此,PLM 是 Versal 启动链的中枢,任何镜像分区的顺序、地址、目标处理器都由 PLM 依据 PDI 元数据决定。

Versal 启动链:BootROM → PLM → 各处理单元 BootROM(固化) 1. 采样启动模式引脚 2. 初始化启动外设 3. 校验 PDI 头,加载 PLM 启动模式选择 MODE[3:0] 引脚采样 QSPI / SD / eMMC USB / JTAG / PCIe 决定 PDI 读取来源 PLM(PMC 内运行) 解析 PDI 分区表 电源域 / 时钟 / 复位管理 按序加载各分区 PLM 扩展分区 PMU 固件分区 PL 比特流分区 APU / RPU 镜像分区 APU(Cortex-A72) 运行 Linux / U-Boot RPU(Cortex-R5) 实时裸机 / RTOS PL(可编程逻辑) 由 PDI 比特流配置 加载 PLM 模式决定来源 读取 PDI 跳转 加载 配置 关键点: • BootROM 只负责加载 PLM,不解析完整镜像;PLM 才是启动链的中枢,按 PDI 分区表顺序加载。 • 启动模式引脚在复位释放瞬间被采样,决定 PDI 从 QSPI、SD、eMMC、USB 还是 JTAG 读取。 • BOOT.BIN 本质是 PDI 的封装,包含 PLM、PMU 固件、PL 比特流、APU/RPU 镜像等分区。

启动模式选择

Versal 通过 MODE[3:0] 引脚在复位释放瞬间的电平组合选择启动设备。常见配置为:MODE[3:0]=0000 对应 JTAG,0001 对应 QSPI32,0010 对应 SD 1.8V,0011 对应 eMMC 1.8V,0100 对应 USB。实际板卡上通常用拨码开关或电阻上下拉实现。开发阶段建议保留 JTAG 模式作为兜底,因为当 BOOT.BIN 损坏导致启动失败时,JTAG 模式可以绕过 BootROM 的启动设备读取,直接用 Vitis 通过 JTAG 下载 PLM 和镜像进行调试。

需要注意,Versal 的启动模式采样发生在 PMC 上电复位释放的极短窗口内,引脚状态必须稳定。若使用拨码开关,应在复位释放前完成设置;若使用 GPIO 动态控制,必须保证在 PMC 复位释放前建立稳定电平,否则 BootROM 会采样到错误模式。

BOOT.BIN 的组成结构

BOOT.BIN 是 Vitis 打包生成的启动镜像文件,其内部是 PDI 格式。一个典型的 Versal Linux 启动镜像包含以下分区,顺序由 Vitis 的 BIF(Boot Image Format)文件决定:

  • PLM 分区:由 Vitis 从 PMC 硬件设计自动生成,包含 PLM 固件和 CDO(Configuration Data Object)序列,负责电源、时钟、复位初始化。
  • PMU 固件分区:PMU(Platform Management Unit)固件,负责平台监控、错误管理和部分电源管理任务,通常由 Vitis 自动生成。
  • PL 比特流分区:若设计包含 PL 逻辑,需将 .bit 或 .pdi 格式的比特流加入,PLM 会在启动时配置 PL。
  • APU 镜像分区:通常是 U-Boot 的 ELF 或 BIN 文件,PLM 将其加载到 DDR 指定地址并跳转执行。
  • RPU 镜像分区(可选):若使用 Cortex-R5 实时核,需加入对应的 ELF 镜像。

BIF 文件是描述这些分区及其加载地址、目标处理器的文本文件。例如:

the_ROM_image:
{
  [destination_cpu = pmc, exception_level = el-3]
  plm.elf
  [destination_cpu = pmc, exception_level = el-3]
  pmu.elf
  [destination_cpu = pl, image_type = cdo]
  pl.pdi
  [destination_cpu = a72-0, exception_level = el-2]
  u-boot.elf
}

其中 destination_cpu 指定分区加载到哪个处理器,exception_level 指定异常等级,image_type 指定镜像类型。Vitis 的 bootgen 工具读取 BIF 后生成 BOOT.BIN。

FSBL 与 PMU 固件集成

在 Zynq 时代,FSBL 是用户可修改的启动第一阶段。但在 Versal 中,PLM 取代了 FSBL 的角色,且 PLM 由 Vitis 从硬件设计自动生成,用户通常不直接修改 PLM 源码。用户可定制的部分主要是:在 BIF 中调整分区顺序、指定 APU/RPU 镜像的加载地址、以及通过 CDO 文件在 PLM 执行前插入自定义的寄存器配置。

PMU 固件同样由 Vitis 自动生成,它运行在 PMC 内的 MicroBlaze 上,负责监控和错误处理。在 BIF 中,PMU 固件通常作为独立分区加入,PLM 会在加载自身扩展后加载 PMU 固件。若用户需要自定义 PMU 行为,可通过 Vitis 的 PMU 固件工程修改,但大多数 Linux 启动场景使用默认固件即可。

PLM 和 PMU 固件都运行在 PMC 内部,不占用 APU 或 RPU 资源。它们由 Vitis 根据硬件设计(XSA)自动生成,用户无需手动编写,但需要理解它们在 BIF 中的位置和加载顺序。

使用 Vitis 创建自定义启动镜像并验证

实际操作流程如下。首先在 Vitis 中创建 Platform Project,导入 Versal 的 XSA 文件,Vitis 会自动生成 PLM、PMU 固件和对应的 BIF 模板。然后创建 Application Project,例如 U-Boot 或裸机程序,编译生成 ELF 文件。

接着编辑 BIF 文件,将 PLM、PMU、PL 比特流和 APU 镜像按正确顺序和地址写入。关键参数包括:APU 镜像的加载地址(通常为 DDR 起始地址 0x0000_0000 或 0x0010_0000)、PL 比特流的 image_type = cdo、以及各分区的 destination_cpu。配置完成后,在 Vitis 中右键 BIF 文件选择 "Create Boot Image",或直接调用 bootgen:

bootgen -image versal_linux.bif -arch versal -o BOOT.BIN -w on

生成的 BOOT.BIN 需要写入启动设备。对于 SD 卡启动,直接将 BOOT.BIN 复制到 FAT32 分区根目录;对于 QSPI 启动,使用 Vitis 的 Program Flash 功能或 program_flash 命令写入。验证时,将板卡设为对应启动模式,上电后通过串口观察 PLM 日志。正常启动会依次打印 PLM 版本、分区加载信息、PL 配置完成、APU 跳转地址,最后出现 U-Boot 或 Linux 内核日志。若卡在 "Loading PLM" 或 "PDI header validation failed",通常说明 BOOT.BIN 损坏或启动模式引脚设置错误;若 PLM 加载成功但 APU 无输出,应检查 APU 镜像的加载地址和异常等级是否与链接脚本一致。

BOOT.BIN 中的分区顺序不可随意调换。PLM 必须最先加载,PMU 固件紧随其后,PL 比特流在 APU 镜像之前。若 APU 镜像被放在 PL 比特流之前,PLM 可能在 PL 未配置时跳转 APU,导致依赖 PL 的外设初始化失败。

最后,建议在开发阶段同时保留 JTAG 启动模式。当 BOOT.BIN 验证失败时,可通过 JTAG 直接下载 PLM 和 U-Boot 到 DDR,逐步排查是镜像打包问题还是硬件启动模式问题。这种"JTAG 兜底 + SD 验证"的组合,是 Versal 启动调试中最实用的手段。