4. U-Boot 移植与配置

Agilex SoC 的启动链是 BootROM → U-Boot SPL → ATF(BL31)→ U-Boot proper → Linux,其中 U-Boot 承担了 DDR 初始化、外设早期初始化、镜像加载与启动参数传递等关键职责。与通用 ARM 开发板不同,Agilex 的 U-Boot 移植必须同时处理 HPS(Hard Processor System)侧的 DDR 控制器、SDM(Secure Device Manager)握手、FPGA 配置加载以及多级启动镜像的拼接。本节围绕板级文件、设备树、DDR 初始化、启动参数与脚本定制五个方面展开,给出可直接参考的移植路径。

一、板级文件:从 Altera 参考板派生

U-Boot 源码中 Altera Agilex 相关板级目录位于 board/altera/ 下,常见参考板包括 socfpga_agilex、socfpga_agilex_socdk 等。移植到自定义板卡时,推荐以最接近的参考板为基线派生,而不是从零创建。核心文件包括:

  • board/altera/socfpga_agilex/:板级初始化代码,含 spl.c、board.c、Makefile、Kconfig。
  • configs/socfpga_agilex_defconfig:默认配置,定义 CONFIG_TARGET_SOCFPGA_AGILEX、CONFIG_SPL_* 等。
  • arch/arm/dts/socfpga_agilex.dtsi:SoC 级设备树,描述 HPS 外设、时钟、复位、DDR 控制器节点。
  • arch/arm/dts/socfpga_agilex_socdk-u-boot.dtsi:U-Boot 专用补充节点,如 u-boot,dm-pre-reloc 标记。

派生时需修改 Kconfig 中的 TARGET_* 名称、defconfig 中的 DEFAULT_DEVICE_TREE,并在 board/altera/ 下新增目录。板级 board_init() 中通常需要调用 socfpga_bridges_reset() 释放 HPS-FPGA 桥接,以及 cm_basic_init() 完成时钟管理器基础配置。

二、设备树:HPS 外设与 U-Boot 专用节点

Agilex 的 U-Boot 设备树分为三层:SoC 级 socfpga_agilex.dtsi、板级 socfpga_agilex_.dts、U-Boot 补充 -u-boot.dtsi。板级 dts 中需要根据实际硬件修改:

  • memory@0 节点:DDR 容量与起始地址,Agilex HPS 通常为 0x0 起始,容量 2GB/4GB/8GB 可选。
  • mmc0:SD/MMC 控制器,指定 bus-width、sdhci-caps-mask、no-1-8-v 等。
  • gmac0/gmac1:以太网,配置 phy-mode(rgmii/sgmii)、phy-handle、snps,reset-gpio。
  • uart0:调试串口,指定 clock-frequency 与 current-speed。
  • qspi:QSPI 闪存,用于存放 U-Boot 与 FPGA 配置镜像。

U-Boot 专用节点需在 -u-boot.dtsi 中为 SPL 阶段使用的设备添加 u-boot,dm-pre-reloc;,否则 SPL 无法在重定位前访问该设备。例如串口、时钟、DDR 控制器节点必须标记。若遗漏,典型现象是 SPL 阶段串口无输出或 DDR 初始化失败后无任何日志。

三、DDR 初始化:SPL 中的关键路径

Agilex 的 DDR 初始化由 SPL 调用 sdram_init() 完成,实际参数来自 Altera 提供的 sequencer 与 iocsr 配置。移植时最关键的输入是 Quartus 工程导出的 board_config 文件(如 socfpga_agilex_socdk_board_config.h),其中包含 DDR 时序参数、IO 延迟、PHY 设置。这些参数由 Quartus 的 EMIF IP 根据具体 PCB 走线生成,不能手工猜测。

典型流程为:在 Quartus 中配置 HPS 与 EMIF,生成 u-boot-spl.dtsi 与 board_config,将其放入 U-Boot 源码对应目录,重新编译 SPL。若 DDR 参数错误,SPL 会在 sdram_init() 后卡死或打印 DDR: Failed to init。可通过串口观察 SPL 是否输出 DDR: 前缀日志判断进度。

四、启动参数与脚本定制

U-Boot proper 阶段通过 bootargs 向 Linux 传递参数,Agilex 常用参数包括:

setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait \
  earlycon=uart8250,mmio32,0xffc02000 \
  fpga_manager.fpga_firmware=agilex.rbf"

其中 earlycon 的地址必须与设备树中 uart0 的 reg 一致;fpga_manager.fpga_firmware 指定 FPGA 配置文件,由 Linux 的 FPGA Manager 在启动后加载。若使用 QSPI 启动,root= 应改为 /dev/mtdblock* 或使用 initramfs。

启动脚本通常放在 include/configs/socfpga_agilex.h 的 CONFIG_BOOTCOMMAND 中,或使用 boot.scr。推荐将启动逻辑写入 boot.scr,便于现场修改而无需重编译 U-Boot。示例脚本:

setenv bootargs "console=ttyS0,115200 root=/dev/mmcblk0p2 rw rootwait"
fatload mmc 0:1 ${kernel_addr_r} Image
fatload mmc 0:1 ${fdt_addr_r} socfpga_agilex_custom.dtb
booti ${kernel_addr_r} - ${fdt_addr_r}

脚本编译使用 mkimage -A arm64 -O linux -T script -C none -d boot.cmd boot.scr,放入 FAT 分区即可。

Agilex U-Boot 移植关键路径与配置对象 启动链 BootROM U-Boot SPL DDR + 时钟 ATF (BL31) U-Boot proper bootargs / boot.scr Linux Kernel 板级文件(board/altera/) spl.c / board.c Kconfig / Makefile configs/*_defconfig 设备树三层结构 socfpga_agilex.dtsi(SoC) socfpga_agilex_<board>.dts -u-boot.dtsi(pre-reloc) DDR 初始化输入 Quartus EMIF IP → board_config.h u-boot-spl.dtsi(时序/IO 延迟) sdram_init() → DDR: 日志 启动参数与脚本 bootargs: console / root / earlycon fpga_manager.fpga_firmware=agilex.rbf boot.scr: fatload Image + dtb → booti mkimage -T script -d boot.cmd boot.scr 关键验证点 ① SPL 串口输出 "DDR: " 前缀 ② U-Boot proper 能识别 mmc / gmac ③ bootargs 中 earlycon 地址与 dts 一致 ④ Linux 启动后 /proc/device-tree 可读 移植顺序建议 1. 派生板级目录与 defconfig → 2. 修改板级 dts 与 -u-boot.dtsi → 3. 导入 Quartus board_config 完成 DDR → 4. 配置 bootargs 与 boot.scr → 5. 串口验证 SPL/U-Boot/Linux 三级日志 → 6. 固化到 QSPI 或 SD 卡 注:图中参数为教学示例,实际值以 Quartus 工程与板卡硬件为准。

五、移植顺序与验证要点

建议按以下顺序推进,每步都有明确的观察点:

  1. 派生板级目录与 defconfig:复制参考板目录,重命名 TARGET_*,修改 DEFAULT_DEVICE_TREE。编译后确认 u-boot-with-spl.sfp 生成。
  2. 修改板级 dts 与 -u-boot.dtsi:按实际硬件调整 memory、mmc、gmac、uart 节点,为 SPL 所需设备添加 u-boot,dm-pre-reloc。
  3. 导入 Quartus board_config 完成 DDR:将 EMIF 生成的参数文件放入对应目录,重新编译 SPL。串口应出现 DDR: 日志且不卡死。
  4. 配置 bootargs 与 boot.scr:确认 earlycon 地址与 dts 中 uart0 的 reg 一致,root= 指向正确分区。
  5. 串口验证三级日志:SPL 输出 DDR 与时钟信息,U-Boot proper 输出板级信息与启动脚本执行过程,Linux 输出 earlycon 与根文件系统挂载信息。
  6. 固化到 QSPI 或 SD 卡:使用 quartus_pfg 或 mkpimage 生成启动镜像,写入 QSPI;或直接将 boot.scr、Image、dtb 放入 SD 卡 FAT 分区。
常见排障:若 SPL 无任何串口输出,优先检查 -u-boot.dtsi 中 uart0 是否标记 u-boot,dm-pre-reloc,以及 CONFIG_DEBUG_UART 是否使能。若 DDR 初始化失败,核对 board_config 是否与当前 PCB 版本匹配,必要时用 Quartus 重新生成。若 Linux 启动后无 earlycon 输出,检查 earlycon 地址是否与 dts 中 uart0 的 reg 一致,Agilex 常见为 0xffc02000。