Lazy loaded image
Words 0Read Time 1 min
Invalid Date
notion image
IMX6ULL 从上电到 U-Boot _start 执行之前,Boot ROM 完成了所有底层硬件准备工作。本文基于 NXP IMX6ULL 参考手册,系统梳理 Boot ROM 的完整执行流程。

1. 硬件复位与 ROM 入口

ARM Cortex-A7 内核复位后从片内 ROM 地址 0x00000000 取第一条指令。此时:
  • DDR 尚未初始化,不可用
  • CPU 仅能使用片内 OCRAM(128KB,0x00900000–0x0091FFFF
  • 所有外设处于默认复位状态

2. 判定启动模式(Boot Mode)

Boot ROM 采样 BOOT_MODE[1:0] 引脚电平,决定执行路径:
BOOT_MODE[1:0]
模式
说明
00
Boot From Fuses
从 eFUSE 读取启动配置
01
Serial Downloader
进入 USB/UART 下载模式(用于烧写)
10
Internal Boot
正常启动路径,执行后续完整流程
11
Reserved
保留
开发阶段通常通过拨码开关选择 Internal Boot (10)。量产时可烧写 eFUSE 固化配置。

3. 读取启动设备配置(Boot CFG)

Internal Boot 模式下,Boot ROM 进一步读取 BOOT_CFG 引脚(或 eFUSE)确定:
  • 启动介质类型:SD、eMMC、NAND、QSPI NOR 等
  • 接口参数:总线宽度、时钟频率、地址模式
  • BT_FREQ:Boot ROM 内部时钟配置
📌
eFUSE(熔丝)只能烧写一次,不可逆。开发阶段推荐使用 GPIO 引脚配置启动方式。

4. 初始化时钟与启动设备

Boot ROM 执行以下硬件初始化:
  1. 最小化初始化存储控制器时钟 — 仅为启动设备(uSDHC / GPMI-NAND / QSPI)提供所需时钟,非完整时钟树配置(完整 PLL 与时钟树配置在 U-Boot board_early_init_f 中完成)
  1. 初始化启动设备控制器 — 根据 Boot CFG 初始化对应接口
  1. 开启 MMU 和 L1 Cache — 加速后续镜像加载过程
时序逻辑链: 上电复位后,CPU 由外部 24MHz 晶振(OSC)直接驱动,不经过 PLL。步骤 1–3(复位入口、采样 BOOT_MODE、读取 BOOT_CFG)均在此低速时钟下执行 — 引脚电平由 SRC 硬件锁存到寄存器,Boot ROM 读寄存器完成判断。步骤 4 仅为存储控制器做最小化时钟初始化,CPU 仍运行在 24MHz;完整的 PLL 配置与时钟树初始化由 U-Boot board_early_init_f 完成。
Boot ROM 在下载镜像时打开 L1 cache,在验证镜像时同时打开 L2 cache,验证完毕后关闭。

5. 加载并解析 IVT(Image Vector Table)

Boot ROM 从启动介质的固定偏移处读取 IVT 头部。不同介质的 IVT 偏移:
启动介质
IVT 偏移
SD/eMMC
1KB (0x400)
NAND
FCB 定义
QSPI NOR
4KB (0x1000)
IVT 结构定义了镜像的关键入口信息:
IVT 由 mkimage 工具在构建 .imx 文件时自动生成。

6. 处理 DCD(Device Configuration Data)

🔑
DCD 是 Boot ROM 最关键的一步 — 它负责初始化 DDR 内存控制器。
DCD 本质是一组寄存器写操作序列,Boot ROM 逐条执行:

核心任务

  • 配置 MMDC(Multi Mode DDR Controller)寄存器
  • 设置 DDR3/LPDDR2 时序参数(CAS Latency、tRCD、tRP、tRFC 等)
  • 执行 ZQ 校准(阻抗校准)
  • 完成 DDR 训练(Write Leveling、DQS Gating 等)

DCD 格式

执行约束

  • DCD 最大 1768 字节(受 OCRAM 空间限制)
  • 仅支持写操作和检查/等待操作
  • 只能访问特定的寄存器地址范围
DCD 执行完毕后,DDR 内存空间(0x80000000 起)正式可用。参考
IMX6ULL 完整内存映射布局表
了解完整地址布局。

7. 加载 U-Boot 镜像到 DDR

Boot ROM 根据 Boot Data 中的 startlength 字段,将完整的 .imx 镜像从启动介质拷贝到 DDR:
  • 目标地址:通常为 0x87800000(由 CONFIG_TEXT_BASE 决定)
  • 拷贝范围:从镜像起始到 Boot Data 指定的长度
  • 使用 DMA 或 PIO 方式传输,L1 cache 加速读取

DDR 加载地址:与启动介质无关

DDR 目标地址由 .imx 镜像内部的 Boot Data start 字段唯一决定,不随启动介质变化。无论从 SD、eMMC、NAND 还是 QSPI NOR 启动,Boot ROM 都将镜像拷贝到同一个 DDR 地址(典型值 0x87800000)。
这个地址在编译阶段由 U-Boot 的 CONFIG_TEXT_BASE 写入 Boot Data,mkimage 工具封装进 .imx 文件。Boot ROM 只是忠实执行镜像自身的声明。

不同介质的真正差异

差异不在 DDR 目标地址,而在镜像在介质上的存储格式、IVT 偏移和传输机制
启动介质
IVT 偏移
传输接口
镜像格式要求
SD / eMMC
1KB (0x400)
uSDHC 控制器,ADMA2 DMA 传输
原始 .imx 镜像直接写入固定扇区偏移
Raw NAND
由 FCB 定义
GPMI + BCH ECC 引擎
需要 FCB(Firmware Config Block)+ DBBT(Discovered Bad Block Table)前置结构;Boot ROM 自动处理坏块跳转和 ECC 纠错
QSPI NOR
4KB (0x1000)
QSPI 控制器,支持内存映射读取
.imx 镜像写入 NOR 指定偏移;虽然 NOR 支持 XIP,Boot ROM 仍将镜像完整拷贝到 DDR 执行
📌
核心结论: 启动介质决定的是"从哪里读、怎么读",而非"写到哪里"。DDR 加载地址完全由镜像自身的 Boot Data 定义,所有介质共享同一目标地址。

8. HAB 安全验证(可选)

如果使能了 HAB(High Assurance Boot),Boot ROM 额外执行:
  1. 解析 CSF(Command Sequence File)数据
  1. 使用 RSA 公钥验证镜像数字签名
  1. 校验镜像完整性(SHA-256 哈希)
验证结果:
  • 通过 → 继续启动
  • 失败 + Closed 模式 → 阻止启动
  • 失败 + Open 模式 → 记录事件,继续启动(开发用)

9. Plugin 机制(可选,替代 SPL)

iMX6ULL 默认不使用 SPL,而是支持 Plugin 机制。参考
iMX6ULL是否使用SPL?
了解完整对比。
Plugin 是一段加载到 OCRAM(0x00907000)的代码:
  1. Boot ROM 加载 plugin.bin 到 OCRAM
  1. Plugin 执行 DDR 初始化、时钟配置等
  1. Plugin 调用 ROM API(pu_irom_hwcnfg_setup())通知 Boot ROM 继续
  1. Boot ROM 完成后续镜像加载
💡
Plugin 与 DCD 的区别:DCD 只能执行寄存器写操作,Plugin 是完整的可执行代码,可实现更复杂的初始化逻辑。两者不能同时使用。

10. 清理状态 → 跳转 _start

Boot ROM 完成所有工作后,执行最终清理:
  1. 关闭 L1/L2 Cache
  1. 关闭 MMU
  1. 清理 CPU 流水线
  1. 跳转到 IVT entry 字段指向的地址
此地址即 U-Boot 的 _start(位于 arch/arm/cpu/armv7/start.S 中的 reset 标号)。
控制权正式移交给 U-Boot,进入
Uboot 启动第一阶段

完整时序总结

参考资料

  1. NXP i.MX 6ULL Applications Processor Reference Manual — Chapter 8: System Boot
  1. NXP i.MX 6 Linux High Assurance Boot (HAB) User's Guide
  1. NXP AN12056: HAB Code-Signing Tool
  1. U-Boot 源码:tools/imximage.c(IVT/DCD 生成逻辑)
上一篇
Data Structure and Algorithm
下一篇
用面试拷问嵌入式技术栈

Comments
Loading...