2. STM32MP硬件与启动链解析
STM32MP1 系列是 ST 推出的异构多核微处理器,内部同时集成 Cortex-A7 应用核与 Cortex-M4 实时核。做 OTA 与 A/B 升级,必须先弄清“上电之后到底谁先跑、从哪读、把什么交给谁”。因为升级的本质,就是替换启动链中某一环所加载的镜像,并保证替换后仍能被下一环正确找到。本节围绕存储布局与启动链展开,把 ROM Code、FSBL、SSBL、U-Boot、Linux 内核这条链路讲清楚。
一、存储布局:启动介质与分区
STM32MP1 的启动介质可以是 eMMC、SD 卡、NOR/NAND Flash,也可通过 USB/UART 进入工程模式。以最常见的 eMMC/SD 为例,介质上通常划分两类区域:一类是 ROM Code 直接读取的“启动分区”,另一类是 Linux 使用的“用户分区”。
ROM Code 只认固定的分区名与偏移,典型约定如下(以 ST 官方 Starter Package 布局为例,具体数值随版本可能调整):
| 分区/区域 | 典型内容 | 读取者 |
|---|---|---|
| fsbl1 / fsbl2 | TF-A BL2(FSBL) | ROM Code |
| ssbl | U-Boot(SSBL) | TF-A BL2 |
| bootfs | 内核镜像、设备树、initramfs | U-Boot |
| rootfs | 根文件系统 | Linux 内核 |
| userfs | 用户数据 | 应用 |
注意 fsbl1 与 fsbl2 是互为备份的两份 FSBL,这正是 A/B 思想在启动链最底层的体现:ROM Code 先尝试 fsbl1,校验失败则回退到 fsbl2。理解这一点,对后面设计 OTA 的“双备份”策略非常关键。
二、启动链全景
STM32MP1 的启动是一条逐级接力的链:ROM Code → FSBL(TF-A BL2)→ SSBL(U-Boot)→ Linux 内核 → 用户空间。每一级都负责初始化一部分硬件、校验并加载下一级镜像,然后把控制权交出去。
三、ROM Code:不可更改的第一棒
ROM Code 是芯片出厂固化的只读代码,用户无法修改。它上电后按 BOOT 引脚配置选择启动介质,然后从介质固定位置读取 FSBL 头部,校验签名与完整性。若校验通过,就把 FSBL 加载到片上 SRAM 并跳转执行;若失败,则尝试备份 FSBL 或切换到下一个启动介质。
对 OTA 的启示:ROM Code 阶段几乎不可干预,因此升级方案必须保证“它要读的那份 FSBL 始终有效”。这也是为什么 A/B 升级通常把 FSBL 也纳入双备份管理,而不是只备份内核。
四、FSBL(TF-A BL2):把 DDR 带起来
FSBL 在 STM32MP1 上通常由 Trusted Firmware-A 的 BL2 阶段承担。它运行在片上 SRAM 中,核心任务是初始化 DDR、时钟、电源,然后从 ssbl 分区加载 U-Boot 到 DDR 并跳转。由于此时 DDR 尚未工作,FSBL 自身必须足够小,能塞进有限的 SRAM。
FSBL 还会加载 BL32(OP-TEE)和 BL33(U-Boot),形成完整的可信启动链。在 A/B 升级中,FSBL 往往需要读取启动槽位标志,决定加载哪个槽位的 SSBL。
五、SSBL(U-Boot):启动策略的中枢
U-Boot 是启动链中最“可编程”的一环,也是 OTA 方案最常介入的地方。它负责:
- 读取环境变量,确定当前启动槽位(如 A 或 B);
- 从 bootfs 分区加载内核镜像与设备树到 DDR;
- 组装 bootargs,把 rootfs 分区、槽位信息传给内核;
- 跳转到内核入口。
一个典型的 U-Boot 启动脚本片段如下(示例,实际路径与分区名以工程为准):
setenv bootargs "root=/dev/mmcblk0p6 rootwait rw"
load mmc 0:4 ${kernel_addr_r} /boot/zImage
load mmc 0:4 ${fdt_addr_r} /boot/stm32mp157c-dk2.dtb
bootz ${kernel_addr_r} - ${fdt_addr_r}
在 A/B 升级设计中,这里通常会引入槽位变量,例如 bootslot=a,并据此选择对应的 rootfs 分区。升级完成后,只需切换该变量并重启,即可完成槽位切换。
六、Linux 内核与用户空间
内核被 U-Boot 加载后,解析设备树、初始化驱动,最后按 bootargs 中的 root= 参数挂载根文件系统,启动 init 进程。用户空间的 OTA 服务、升级代理、健康检查程序都在这一层运行。
至此,整条启动链闭合。做 OTA 时,我们实际是在这条链的某个环节“换文件 + 改标志”,并依赖下一环能正确识别新文件。理解每一环的职责与交接方式,才能判断升级该改哪里、校验该做在哪、回滚该由谁触发。