3. STM32MP启动流程与BootROM

STM32MP1 系列(如 STM32MP157、STM32MP135)是一类异构多核处理器:内部同时集成 Cortex-A7(或 Cortex-A35)应用核与 Cortex-M4 实时核。上电之后,芯片并不会直接跳到 Linux 内核,而是经历一条由硬件固化代码、片上 ROM、外部启动介质、多级引导程序共同组成的启动链。理解这条链,是排查“板子上电无输出”“TF-A 卡在 BL2”“U-Boot 找不到内核”等问题的前提。

一、BootROM:芯片上电后的第一段代码

BootROM 是 ST 在芯片出厂时固化在片内只读存储器中的一段不可修改代码,位于启动链的最前端。它的职责非常明确:

  • 读取启动模式引脚(BOOT0~BOOT2)的电平组合,判断从哪种介质启动;
  • 初始化最基础的时钟与所选启动介质控制器(如 SDMMC、QSPI、FMC、USB、UART);
  • 从介质固定偏移处加载第一级引导程序(FSBL)到片内 SYSRAM;
  • 校验 FSBL 头部(STM32 Header)中的签名、版本、加载地址、入口地址等字段;
  • 校验通过后跳转到 FSBL 入口执行。

需要特别注意的是:BootROM 只认识“STM32 头部 + 镜像”这种格式,它并不理解 ELF、不理解文件系统,也不理解 U-Boot。因此 FSBL 必须被封装成 BootROM 能识别的镜像(通常由 STM32CubeProgrammer 或 tf-a 的 fiptool 生成)。若头部校验失败,BootROM 会尝试下一个启动介质,全部失败后进入串口/USB 的 ROM 下载模式(DFU),此时可通过 CubeProgrammer 恢复。

二、启动模式选择与启动引脚

STM32MP1 通过 BOOT0、BOOT1、BOOT2 三个引脚在上电复位时的电平组合决定启动源。以常见的 STM32MP157 为例,典型映射关系如下(具体以对应型号参考手册为准):

BOOT2BOOT1BOOT0启动介质
000NOR / 并行 FMC
001eMMC / SD 卡(SDMMC)
010NAND
100QSPI NOR
110串口 / USB 下载(DFU)

这些引脚通常在复位释放瞬间被采样,之后即可复用为普通 GPIO。开发板上一般用拨码开关或跳线帽选择启动介质,量产板则通过电阻上下拉固定。调试阶段最常见的做法是:先用 SD 卡启动验证镜像,再烧写到 eMMC 或 QSPI 固化。

三、FSBL 与 SSBL:两级引导的分工

STM32MP1 的启动链采用“两级引导”结构:

  • FSBL(First Stage Boot Loader):由 BootROM 加载到 SYSRAM 执行,容量受限(通常 256KB 以内)。在 ST 官方方案中,FSBL 就是 TF-A 的 BL2。它负责初始化 DDR、时钟树、电源、安全外设,然后从启动介质加载 SSBL 到 DDR。
  • SSBL(Second Stage Boot Loader):即 U-Boot(通常为 u-boot.stm32 或 u-boot-spl.stm32 之后的完整 U-Boot)。它运行在 DDR 中,负责加载 Linux 内核、设备树、根文件系统,并把控制权交给内核。

因此,STM32MP1 的典型启动链可以概括为:

BootROM → TF-A BL2 (FSBL) → TF-A BL32/BL33 (OP-TEE / U-Boot) → Linux Kernel

四、TF-A 与 U-Boot 在启动链中的角色

TF-A(Trusted Firmware-A) 是 ARM 官方推荐的 A 核安全启动固件,在 STM32MP1 上被拆分为多个 BL 阶段:

  • BL2:即 FSBL,运行于 SYSRAM,初始化 DDR 与安全环境;
  • BL32:OP-TEE OS,运行于安全世界(Secure World),提供 TrustZone 服务;
  • BL33:即 U-Boot,运行于非安全世界(Non-Secure World)。

U-Boot 作为 BL33,承担内核加载任务。它读取 bootcmd,从 eMMC、SD、网络或 USB 加载 Image、stm32mp157c-xxx.dtb 与根文件系统,最后通过 booti 或 bootz 跳转到内核入口。若启用了 FIT 镜像,U-Boot 还会校验内核与设备树的签名。

STM32MP1 启动链与介质映射 BootROM 片内固化 · 只读 BOOT0/1/2 启动模式选择 启动介质 SD / eMMC QSPI NOR NAND / FMC USB / UART TF-A BL2 (FSBL) SYSRAM · 初始化 DDR 加载 TF-A BL32 OP-TEE · Secure TF-A BL33 U-Boot · Non-Secure Linux Kernel Image + DTB 根文件系统 booti 阶段 0 阶段 1 (FSBL) 阶段 2 (SSBL) 阶段 3

五、启动介质与镜像布局

不同启动介质对镜像布局有不同要求。以 SD 卡/eMMC 为例,ST 官方推荐的分区布局为:

分区 0: 0x00000000 ~ 0x000000FF  GPT 头
分区 1: 0x00000100 ~ 0x00000FFF  fsbl1 (TF-A BL2)
分区 2: 0x00001000 ~ 0x00001FFF  fsbl2 (备份)
分区 3: 0x00002000 ~ 0x00003FFF  fip (BL32+BL33)
分区 4: 0x00004000 ~ 0x00007FFF  u-boot-env
分区 5: 0x00008000 ~ ...          bootfs (内核+DTB)
分区 6: ...                        rootfs

BootROM 会从偏移 0x100 处读取 FSBL,因此烧写时不能简单地把 tf-a.stm32 拷到卡根目录,而要用 dd 或 CubeProgrammer 按偏移写入。QSPI NOR 启动时,FSBL 位于 0x0 偏移,FIP 位于 0x40000 偏移,具体以 ST 的 Flashlayout 文件为准。

六、典型排障思路

当板子上电无任何串口输出时,可按以下顺序排查:

  1. 确认 BOOT 引脚电平与目标介质一致,用万用表测量复位释放瞬间的电平;
  2. 确认 FSBL 头部有效,可用 STM32CubeProgrammer 读取介质前 0x200 字节,检查是否有 0x53544D32("STM2")魔数;
  3. 确认 DDR 初始化参数与板卡匹配,DDR 配置错误会导致 BL2 卡死且无输出;
  4. 确认 FIP 包中 BL32/BL33 均已包含,可用 fiptool info fip.bin 查看;
  5. 若 U-Boot 能启动但找不到内核,检查 bootcmd、bootargs 与分区名是否与 Flashlayout 一致。
调试阶段建议保留 SD 卡启动通道,并在 U-Boot 中打开 CONFIG_BOOTDELAY=3,便于通过串口中断进入命令行,快速验证内核与设备树。

掌握 BootROM 的加载规则、启动引脚映射、FSBL/SSBL 的分工以及 TF-A 与 U-Boot 的衔接关系,就能在启动失败时快速定位问题发生在哪一级,而不是盲目重烧镜像。