4. HSS 与设备树配置实战

在 PolarFire SoC 的启动链路中,HSS(Hart Software Services)是上电后最先运行的固件,它承担着硬件初始化、Hart 管理、时钟与 DDR 配置、外设早期初始化,以及加载并跳转到 U-Boot 的职责。理解 HSS 的源码结构,并掌握设备树(Device Tree)的修改方法,是让自定义板卡跑通 Linux 的关键一步。本节围绕“HSS 是什么、源码怎么组织、设备树改哪里、如何编译部署”四个问题展开,并给出可直接参考的配置示例。

一、HSS 在启动链中的位置与作用

PolarFire SoC 上电后,E51 监控核首先执行 HSS。HSS 由两部分组成:运行在 E51 上的 hss 主固件,以及运行在 U54 应用核上的 u54_1 等引导程序。HSS 完成的主要工作包括:初始化 MSS(微控制器子系统)时钟、DDR、eNVM/SD 控制器;解析设备树,把硬件描述传递给后续阶段;从 eNVM、SD 卡或 QSPI 加载 U-Boot 镜像;最后通过 SBI(Supervisor Binary Interface)把控制权交给 U-Boot。因此,HSS 是“硬件到操作系统”的桥梁,设备树则是这座桥梁的“施工图”。

二、HSS 源码结构

HSS 源码通常位于 hart-software-services/ 目录下,核心结构如下:

hart-software-services/
├── application/          # HSS 主应用与各服务
│   ├── hss/              # E51 主固件入口
│   ├── u54_1/            # U54 引导程序
│   └── ...
├── baremetal/            # 裸机驱动与库
├── boards/               # 板级配置(含设备树)
│   ├── icicle-kit-es/
│   │   ├── fpga_design_config/
│   │   └── ...
│   └── mpfs-video-kit/
├── configs/              # 编译配置
├── tools/                # 构建与打包脚本
└── Makefile

其中 boards/ 是适配自定义板卡时最常修改的目录。每个板卡目录下包含设备树文件(.dts 或 .dtsi)、FPGA 设计配置以及板级参数。HSS 在编译时会根据 CONFIG_BOARD 选择对应板卡目录,因此新增板卡时,需要复制一份现有板卡目录并重命名。

三、设备树修改要点

设备树描述的是“硬件长什么样”,HSS 和 U-Boot 都依赖它。适配自定义板卡时,重点修改以下几类节点:

  • 内存节点:memory@80000000 的 reg 属性需与实际 DDR 容量一致,例如 2GB 应写为 0x0 0x80000000 0x0 0x80000000。
  • 时钟节点:clk 相关节点的频率要与板卡晶振匹配,否则 UART、SD 等外设波特率会出错。
  • 串口节点:serial@20000000 的 status 设为 okay,并确认 current-speed 为 115200。
  • MMC/SD 节点:mmc@20008000 需根据实际使用的控制器使能,并配置 bus-width。
  • 以太网节点:mac@30000000 的 PHY 地址、phy-mode 要与原理图一致。

下面是一个简化的设备树片段示例,展示如何把 DDR 容量改为 2GB 并使能 UART:

/dts-v1/;
/ {
    #address-cells = <2>;
    #size-cells = <2>;
    compatible = "microchip,mpfs";
    model = "MyCustomBoard";

    memory@80000000 {
        device_type = "memory";
        reg = <0x0 0x80000000 0x0 0x80000000>;
    };

    soc {
        serial@20000000 {
            compatible = "ns16550a";
            reg = <0x0 0x20000000 0x0 0x1000>;
            clock-frequency = <150000000>;
            current-speed = <115200>;
            status = "okay";
        };
    };
};

修改完成后,建议用 dtc 工具做一次语法检查:dtc -I dts -O dtb -o test.dtb myboard.dts,若无报错再进入编译流程。

HSS 启动链与设备树适配关系 E51 上电 执行 HSS 主固件 硬件初始化 时钟 / DDR / 外设 解析设备树 传递硬件描述 加载 U-Boot 跳转并移交控制权 自定义板卡设备树修改要点 memory reg 容量 0x80000000 clk clock-frequency 匹配晶振 serial status okay 115200 mmc bus-width 控制器使能 mac phy-mode PHY 地址 编译与部署流程 make BOARD=myboard 生成 hss.elf / .bin 烧录 eNVM / SD 启动验证

四、编译 HSS 与 U-Boot

HSS 使用 Makefile 构建,编译前需设置交叉编译工具链。以 RISC-V 工具链为例:

export CROSS_COMPILE=riscv64-unknown-elf-
export PATH=/opt/riscv/bin:$PATH
cd hart-software-services
make BOARD=myboard

编译成功后,在 build/ 目录下会生成 hss.elf、hss.bin 以及 u54_1.elf 等文件。若使用 SD 卡启动,还需将 hss.bin 与 U-Boot 镜像一起打包为 payload.bin。U-Boot 的编译则在其源码目录执行:

make microchip_mpfs_icicle_defconfig
make -j$(nproc)

生成的 u-boot.bin 需与 HSS 的 hss.bin 按启动介质要求合并。例如 SD 卡启动时,通常将 hss.bin 写入偏移 0,u-boot.bin 写入后续偏移,具体偏移量参考板卡手册。

五、部署与验证

部署方式主要有两种:通过 FlashPro 烧录 eNVM,或通过 SD 卡启动。以 SD 卡为例,将打包好的 payload.bin 写入 SD 卡起始扇区,插入板卡后上电。串口终端应依次看到 HSS 版本信息、DDR 初始化日志、U-Boot 启动信息。若卡在 HSS 阶段,优先检查设备树中的 DDR 容量和时钟频率是否与实际硬件一致;若 U-Boot 能启动但找不到存储设备,则检查 MMC 节点的 status 和 bus-width。验证通过后,说明 HSS 与设备树已正确适配自定义板卡。

修改设备树后,建议先用 dtc 做语法检查,再编译 HSS。若启动失败,可通过 HSS 的串口日志定位是 DDR、时钟还是外设节点配置错误。