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 通过 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 启动场景使用默认固件即可。
使用 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 镜像的加载地址和异常等级是否与链接脚本一致。
最后,建议在开发阶段同时保留 JTAG 启动模式。当 BOOT.BIN 验证失败时,可通过 JTAG 直接下载 PLM 和 U-Boot 到 DDR,逐步排查是镜像打包问题还是硬件启动模式问题。这种"JTAG 兜底 + SD 验证"的组合,是 Versal 启动调试中最实用的手段。