1. 最小 HPS 系统的启动链路回顾
以 Agilex 7 SoC 为例,一个完整的 HPS 启动链大致可以画成下面这样(示意图):

各阶段的典型职责大致如下:
-
BootROM / SDM器件内部固化的最早启动逻辑,根据引脚配置选择启动介质,加载第一阶段镜像(通常是包含 FSBL 的配置数据或 Flash 前几块区域)。
-
**FSBL(First Stage Boot Loader)**运行在 HPS 上,完成:
- HPS 时钟 / 复位 / 外设的基础初始化;
- DDR 控制器(HPS EMIF)的初始化和校准;
- 根据指定介质(SD/eMMC/QSPI/NAND)加载 SSBL。
-
**SSBL(Second Stage Boot Loader,通常是 U‑Boot)**负责:
- 提供命令行、脚本、网络(TFTP)等功能;
- 加载 Linux 内核和设备树;
- 传递启动参数(bootargs),跳转到内核入口。
-
Linux 内核 + 设备树 + RootFS
完成操作系统层面的初始化,挂载根文件系统,启动 init 进程,最终给出 Shell 或图形界面。
在“最小 HPS 系统”的语境下,我们不追求外设的丰富度,只要求:
- DDR 可用且稳定(FSBL 初始化成功);
- 选定的启动介质可访问(SSBL 及 Linux 能够从中读取镜像);
- 能通过串口看到完整的启动日志,并登录系统。
2. 为自定义硬件准备最小软件栈
有了第 3 篇中的硬件系统(HPS + DDR),接下来就要准备软件栈。根据项目情况,可以有不同的策略。
2.1 直接沿用 GSRD 的 U‑Boot / Linux(推荐起步方式)
如果上一篇你是先用官方 GSRD 在开发板上跑通了系统,然后再改成“最小 HPS 硬件”,那么可以沿用 GSRD 的软件栈,只做最小修改:
- 保留原来的:
- U‑Boot 源码和配置;
- Linux 内核和根文件系统;
- Yocto 或 Buildroot 工程;
- 将第 3 篇生成的 硬件 handoff 文件(如
.sopcinfo/ HPS handoff)导入,更新:- DDR 参数(容量、起始地址);
- 设备树中的内存节点;
- 必要的 HPS 外设配置。
这样可以最大程度复用官方验证过的启动链路,只把“硬件差异”通过 handoff / 设备树调整进去。
2.2 完全自定义的软件栈(适合深度定制)
如果项目对系统有较强的定制需求,也可以从零构建软件栈:
- 使用 Intel 提供的示例 BSP、或者开源工程(如 linux-socfpga / u-boot-socfpga);
- 使用 Yocto / Buildroot / 自己的构建脚本来生成:
- FSBL;
- U‑Boot;
- Linux 内核;
- 根文件系统(rootfs)。
无论是沿用 GSRD 还是从零构建,最终我们都需要拿到几类“成品文件”:
- FPGA 配置:
.sof(SRAM Object File); - 含有 FSBL 的 HPS 启动镜像(可能集成在比特流或独立二进制中);
- U‑Boot 镜像:如
u-boot.bin/u-boot-spl.bin; - Linux 内核:
zImage/Image; - 设备树:
.dtb; - 根文件系统:如
rootfs.ext4/initramfs.cpio.gz等。
接下来要做的,就是把这些东西“打包”成一个或若干可以烧录到板子上的镜像。
3. 使用 Programming File Generator 打包 jic
在自定义硬件上带起 HPS 系统的一种常见做法是:
利用 Quartus 的 Programming File Generator(Convert Programming Files),把
sof + FSBL + SSBL + 内核 + 根文件系统打包成一个jic文件,然后一次性烧录到 Flash 中。
3.1 Convert Programming Files 基本流程
在 Quartus 中:
- 打开
File -> Convert Programming Files...; - 在
Programming file type中选择JIC(JTAG Indirect Configuration); - 选择目标器件和 Flash 类型(如 EPCQ / EPCQ-L / 第三方 SPI Flash 等);
- 在
Input files to convert区域中按顺序添加:- FPGA 配置文件
.sof; - HPS 相关镜像(FSBL/SSBL/U‑Boot/内核/RootFS),通常是一个或多个
.bin;
- FPGA 配置文件
- 为每个输入文件设置:
- 存放在 Flash 中的偏移地址;
- 必要的选项(如是否压缩、是否带校验等)。
不同 SoC 器件的 jic 结构会略有差异,推荐直接参考对应的《Embedded Software Design Guide》中的示例布局。
3.2 一个典型的 jic 内容布局示意
可以把 jic 文件看作是“往 Flash 里排数据”的描述文件,例如:
[Flash 起始]
|-- FPGA 配置比特流(含 FSBL)
|-- U-Boot / SSBL
|-- Linux 内核 + 设备树
|-- 根文件系统(可选 / 可外置)
[Flash 结束]
烧录完成后,上电时的过程通常是:
- BootROM / SDM 从 Flash 指定位置加载 FPGA 配置比特流(其中包含 FSBL);
- FPGA 完成配置,HPS 触发 FSBL 运行;
- FSBL 从 Flash 其它偏移读取 U‑Boot,加载到 DDR;
- U‑Boot 继续从 Flash 或其它介质读取内核和根文件系统,最终启动 Linux。
3.3 选择启动介质与模式
在使用 jic 方案时,还需要配合板卡上的拨码/引脚设置 HPS 的启动介质:
- 让 BootROM / SDM 知道:
- 从哪块 Flash / SD 卡启动;
- 是否先配置 FPGA 再启动 HPS,还是先 HPS 后 FPGA;
- 对应的启动模式一般在器件手册中有详细说明(如 AS、JTAG、SD/eMMC、QSPI、NAND 等)。
在“最小 HPS 系统”的阶段,可以选一种最简单、最稳妥的组合,例如:
- 用 JTAG 将
jic烧录到板载 QSPI Flash; - 设置启动模式为:先从 QSPI 加载 FPGA 配置(带 FSBL),再从 QSPI 加载 U‑Boot / Linux。
4. 板上启动与基本验证
在硬件 + 软件都准备好以后,就可以在板子上做一次“从 0 到 Shell” 的完整启动。
4.1 烧录 jic 到板载 Flash
使用 Quartus Programmer:
- 通过 USB‑Blaster 连接 JTAG;
- 选择目标链上的 SoC 设备;
- 添加刚刚生成的
*.jic文件; - 勾选
Program/Configure,执行烧录; - 烧录成功后,断电重启(或复位)板子。
4.2 串口观察启动日志
使用串口终端(如 minicom / PuTTY)连接开发板 UART:
- 设置波特率(一般为 115200 或 921600,视板卡而定);
- 上电后观察输出:
- BootROM / SDM 初始信息(有的器件看不到);
- FSBL 初始化日志(DDR 初始化 / 校准是否成功);
- U‑Boot 启动信息(版本号、设备枚举等);
- Linux 内核启动日志(驱动加载、设备树解析、挂载根文件系统);
- 最终出现类似
login:的登录提示。
如果在 FSBL 阶段就中断(常见表现是串口停在 DDR 初始化附近),大概率是:
- HPS EMIF 配置与板卡 DDR 不匹配;
- 硬件连线问题(DQ/DQS/CLK/ADDR 等);
- DDR 供电/时钟不稳定。
这时需要回到第 3 篇的硬件配置,结合波形和板级测量排查问题。
4.3 登录系统并做最小自检
进入 Linux 后,可以做几项基本检查:
free -h/cat /proc/meminfo:确认 DDR 容量与预期一致;dmesg:确认启动中没有严重错误(如 DDR ECC 错误、挂载失败等);cat /proc/cpuinfo:确认 HPS 内核信息;ls /dev:确认基础设备节点(UART、MMC、网口等)。
到这一步,说明“最小 HPS 系统”已经真正完整跑起来了。
5. 利用 Signal Tap 间接观测 HPS 专用引脚
在调试 HPS 启动问题时,很多人本能会想到用 Signal Tap 抓信号。但有一个现实限制:
HPS 专用引脚的信号(例如部分启动相关引脚)本质上不经过 FPGA 逻辑,因此无法直接用 Signal Tap 探测。
不过,我们仍然可以用一些“曲线救国”的办法,间接观察这些信号。
5.1 将 HPS 专用引脚信号路由到 FPGA 端
思路是:
- 在硬件设计中,将 HPS 专用引脚的信号(或者与之相关的状态)通过某种方式送入 FPGA 逻辑;
- 在 FPGA 逻辑中再将这些信号接入 Signal Tap 采集端口;
- 通过分析 FPGA 端看到的波形,反推 HPS 侧的行为。
具体实现方式会因器件和引脚类型而不同,例如:
- 对部分时钟/复位信号,可以在板级硬件上做简单的分配或缓冲,把同一个信号送到 FPGA 普通 I/O;
- 对部分由 HPS 控制的片选 / 片上总线信号,可以在 Platform Designer 中通过桥接把状态寄存器暴露给 FPGA,再使用 Signal Tap 观测寄存器变化。
5.2 结合 JTAG-to-Avalon / System Console 进行寄存器级调试
除了波形级调试,还可以借助:
- JTAG‑to‑Avalon Master:从 PC 端通过 JTAG 访问 FPGA 地址空间;
- System Console:在 Tcl 环境下读写各种 Avalon 端口、寄存器。
配合 HPS↔FPGA 的桥接,可以做一些有用的事情:
- 在 HPS 不正常启动时,从 FPGA 侧检查 DDR 控制器某些状态寄存器;
- 手工发起一些访问,看是否能正确到达 HPS 或 DDR 区域。
这些手段虽然不如 JTAG 直连 HPS 核心那样“直观”,但在没有高阶调试器的情况下,足够帮助定位大部分硬件层面的启动问题。
6. 小结
本篇围绕“最小 HPS 系统”的软件与启动部分,完成了从抽象到落地的闭环:
- 搭建在第 3 篇基础上的自定义硬件,准备 FSBL / U‑Boot / Linux / 根文件系统等软件组件;
- 利用 Quartus 的 Programming File Generator,将
sof + 各种镜像打包成jic并烧录到 Flash; - 上电通过串口观察完整启动过程,确认 DDR 和启动链路正常;
- 利用 Signal Tap + JTAG‑to‑Avalon / System Console,在必要时对 HPS 启动相关信号做“间接观测”和寄存器级调试。
到这里,一个不依赖官方 GSRD,仅依赖芯片和板卡本身的最小 HPS 系统已经打通。从工程实践的角度看,它具备了:
- 可移植到不同自定义板卡的通用性;
- 足够精简的 IP 结构(HPS + DDR),便于分析和维护;
- 后续可以逐步在 FPGA 侧挂载自定义逻辑,通过 HPS↔FPGA 桥接进行控制和数据交互。