一、Bring-Up 概念
Bring-Up 指的是在一个新硬件平台上开始启动系统的整个过程,通常包括 BootROM 启动,加载 SPL/全量 U-Boot,并最终启动 Linux 内核和用户端文件系统。这是所有嵌入式开发中最基础的一段。
如果把开发板比作一个人,Bring-Up 就是从 “命不在之” 到 "可跑 Linux + App"的一段周期,需要硬件和软件多方面配合。
二、全过程随时间阶段解析
以 i.MX8M Plus 开发板为例,其启动过程为:
ROM Boot → SPL (Secondary Program Loader) → U-Boot → Linux Kernel → File System → Application
2.1 Rom Boot Stage
- 作用:固化在主算的 BootROM ROM 中,不可更改
- 过程:搜索启动设备,如 SD/eMMC/NAND/USB/Serial Downloader
- 加载 SPL:将 SPL 加载至 OCRAM 运行
2.2 SPL Stage
- 作用:是 U-Boot 的前端缩约版,负责 DRAM 初始化,加载主 U-Boot
- 代码路径:
u-boot-spl/
或spl/
- 基本流程:
board_init_f(); // CPU, UART, DRAM 初始化
board_init_r(); // 加载主 U-Boot 进 DRAM
2.3 U-Boot Stage
- 作用:接管 SPL,支持 CLI 指令组,装载 Kernel 和 dtb/initrd
- 设备初始化:包括网卡,USB,PCIe,MMC/eMMC
- 代码路径:
common/
,cmd/
,board/
,drivers/
2.4 Linux Kernel 启动
- U-Boot 传递 kernel 和 dtb 给内核
- U-Boot 通过 bootargs 传递文件系统路径
- kernel 执行连接后加载根文件系统
2.5 RootFS 和 Application
- Kernel 按 bootargs 指定 rootfs 路径 mount 根文件系统
- init程序 启动,调用 systemd/busybox/init
- 运行应用程序
三、实际 Bring-Up 示例(以 i.MX8MP 为例)
3.1 DRAM 初始化代码(SPL)
void spl_dram_init(void)
{
struct dram_timing_info *dram_timing = &dram_timing_ddr4_32bit_1GB;
ddr_init(dram_timing);
}
这段代码实现 DRAM 调用初始化配置,是 bring-up 重点。
3.2 U-Boot 指令启动 Kernel
setenv bootargs console=ttymxc1,115200 root=/dev/mmcblk1p2 rootwait rw
load mmc 1:1 ${loadaddr} Image
load mmc 1:1 ${fdt_addr} imx8mp-evk.dtb
booti ${loadaddr} - ${fdt_addr}
setenv bootargs
:设置启动参数load
:加载内核和 dtbbooti
:启动 Linux 内核
3.3 设备树加载配置(DTB)
&uart2 {
status = "okay";
};
这表示开启 UART2 作为 console 设备
四、关键问题与答案
Q1: SPL 和 U-Boot 为什么分离?
- 因为 ROM Boot 只能读 OCRAM,这些内存宽度有限,需要简版 SPL 先做 DRAM init
Q2: 如何确定 U-Boot 启动成功?
- 看 serial log 中是否出现 “U-Boot SPL…”, 和 U-Boot CLI 控制口 prompt:
=>
Q3: 如何修改 SPL 配置?
configs/imx8mp_evk_defconfig
board/freescale/imx8mp_evk/
中的 board_init_f 代码
Q4: 如何分析 Kernel 启动失败?
- 看 Kernel panic log
- 确认 rootfs 路径正确
- 确认 dtb 和 Kernel 版本匹配
五、总结
Bring-Up 是嵌入式 Linux 开发里最第一步跳跃点,它需要精通 bootloader 和硬件平台,同时懂得 Linux Kernel 启动和设备树配置。
完整的 bring-up 不仅是 “启动起来” ,而是超过“能跑起来”,观察成功的启动日志,确认系统在正确的 DRAM 、clock 、UART 、kernel 、rootfs 上运行。