4. Versal启动与系统配置
Versal ACAP 的启动过程与 Zynq-7000、Zynq UltraScale+ MPSoC 有本质区别:它不再由单一的 BootROM 直接加载 FSBL,而是引入了一个运行在 PMC(Platform Management Controller,平台管理控制器)内部微处理器上的 PLM(Platform Loader and Manager,平台加载与管理器)作为整个芯片的“第一段固件”。理解 PLM 与 PMC 的职责边界,是掌握 Versal 启动、固件加载和调试方法的前提。
一、PMC 与 PLM:Versal 启动的根
PMC 是 Versal 内部一个独立于 NoC 和可编程逻辑的电源与系统管理域,它包含一个专用的微处理器、ROM、RAM、外设接口(QSPI、SD/eMMC、USB、以太网、JTAG 等)以及电源管理单元。芯片上电或复位后,PMC 内的 ROM 代码首先执行,从启动模式引脚指定的介质中读取 PLM 固件(通常为 plm.elf 或 plm.bin),将其加载到 PMC RAM 中并跳转执行。此后,PLM 成为整个启动流程的调度中心。
PLM 的主要职责包括:解析 PDI(Programmable Device Image,可编程器件镜像)中的分区表;按顺序加载 PL 配置数据、AI Engine 镜像、PS 端固件(如 TF-A、U-Boot、Linux);管理电源域的上电时序;提供与 JTAG、PMC 外设的通信接口。可以说,PLM 是 Versal 启动的“引导加载器 + 电源管理器 + 镜像解析器”三合一角色。
二、启动模式与启动介质选择
Versal 的启动模式由 MODE[3:0] 引脚在上电复位时采样决定,常见模式包括:
- JTAG 模式:PLM 不主动从外部介质加载,而是等待 JTAG 主机通过 PMC JTAG 接口下载 PLM 和 PDI。适合裸片首次调试、板卡 bring-up。
- QSPI24 / QSPI32 模式:从板载 QSPI Flash 读取 PLM 和 PDI,常用于量产固化。
- SD 模式(SD0/SD1):从 SD 卡读取
BOOT.BIN(由 PLM、PDI、固件打包而成),是开发阶段最常用的方式。 - eMMC 模式:从 eMMC 用户分区读取启动镜像。
开发阶段推荐使用 SD 启动,因为镜像替换方便;量产阶段则根据成本与可靠性选择 QSPI 或 eMMC。JTAG 模式通常与 SD 模式配合使用:先通过 SD 启动进入系统,再用 JTAG 连接进行在线调试。
三、固件加载顺序与 PDI 结构
Versal 的启动镜像通常以 PDI 为核心,PDI 内部由多个分区(Partition)组成,每个分区有类型、目标地址和校验信息。PLM 按分区表顺序处理:先加载 PL 的 bitstream 分区,再加载 AI Engine 的 CDO(Configuration Data Object),最后加载 PS 端的固件分区。典型的 SD 启动镜像 BOOT.BIN 由以下部分组成:
BOOT.BIN 组成(示例):
[0] plm.elf → PMC RAM
[1] pdi → PL 配置 + AIE CDO
[2] bl31.elf (TF-A) → DDR 中的 EL3 运行环境
[3] u-boot.elf → DDR 中的 U-Boot
[4] system.dtb → 设备树
其中 TF-A(Trusted Firmware-A)负责初始化 DDR、建立安全环境,并跳转到 U-Boot;U-Boot 再加载 Linux 内核与根文件系统。设备树(Device Tree)在这一阶段被传入内核,描述 PS 外设、PL 中的 IP、内存映射和中断连接。
四、Linux 启动流程与设备树
从 PLM 到 Linux 用户空间的完整链路可以概括为:PMC ROM → PLM → PL 配置/AIE → TF-A → U-Boot → Linux Kernel → RootFS。设备树在这一链路中承担“硬件描述”的角色:U-Boot 将 system.dtb 传递给内核,内核据此枚举串口、SD、以太网、QSPI、PL 端 AXI IP 等设备。对于 PL 中自定义的 IP,需要在设备树中增加对应的节点,并确保 compatible 字符串与驱动匹配。
五、JTAG 与 SD 启动调试方法
实际调试中,最常见的两种组合是“SD 启动 + JTAG 在线调试”和“纯 JTAG 启动”。SD 启动时,将 BOOT.BIN 写入 SD 卡第一分区(FAT32),插入板卡后上电,串口应输出 PLM 版本、PDI 分区加载日志和 U-Boot 启动信息。若串口无输出,首先检查启动模式引脚是否被正确拉高/拉低,其次确认 BOOT.BIN 是否由正确的 PLM 与 PDI 打包生成。
JTAG 调试通常使用 Vivado 或 Vitis 的 XSCT(Xilinx Software Command-line Tool)连接。典型操作如下:
# 连接 JTAG 目标
xsct
connect
targets -set -filter {name =~ "PMC"}
# 下载 PLM 到 PMC RAM
dow plm.elf
# 下载 PDI 配置 PL 与 AIE
dow -data system.pdi 0x20000000
# 下载 TF-A 与 U-Boot
dow bl31.elf
dow u-boot.elf
# 复位并运行
rst -processor
con
在 JTAG 模式下,PLM 由主机直接下载,因此可以绕过 SD 卡或 QSPI 中的镜像,快速验证新生成的 PDI 是否正确。若 PL 配置失败,XSCT 会报告分区校验错误或超时;若 TF-A 无法初始化 DDR,则 U-Boot 不会启动,此时应检查 DDR 参数是否与板卡匹配。
chosen 节点可通过 U-Boot 的 bootargs 传递内核命令行参数,例如 console=ttyAMA0,115200 root=/dev/mmcblk0p2 rw。调试串口无输出时,优先确认 stdout-path 是否指向正确的 UART 控制器。
六、常见启动故障与判断依据
| 现象 | 可能原因 | 排查方法 |
|---|---|---|
| 上电后串口无任何输出 | 启动模式引脚错误;PLM 未加载 | 测量 MODE 引脚电平;用 JTAG 连接 PMC 查看 PC 指针 |
| PLM 日志正常但 PL 配置失败 | PDI 分区损坏;PL 电源域未上电 | 检查 PDI 校验和;确认 PMC 电源管理寄存器状态 |
| U-Boot 启动后卡在 DDR 初始化 | DDR 参数与板卡不匹配 | 核对 TF-A 中的 DDR 配置;用 JTAG 读取 DDR 控制器寄存器 |
| 内核启动但根文件系统挂载失败 | bootargs 中 root= 设备名错误 | 在 U-Boot 中执行 printenv bootargs 并修正 |
| PL 端 IP 在 Linux 中不可见 | 设备树缺少对应节点或 compatible 不匹配 | 检查 /proc/device-tree;确认驱动已编译进内核 |
总体而言,Versal 启动调试应遵循“先 PMC/PLM,再 PL/AIE,后 PS/Linux”的层次顺序。只要 PLM 能正常输出日志,后续问题大多可定位到 PDI 分区、DDR 初始化或设备树配置三个环节。掌握 PLM 的加载逻辑与 PDI 的分区结构,就能在 JTAG 与 SD 两种调试路径之间灵活切换,快速定位启动失败的根本原因。