2. 嵌入式Linux启动流程

在嵌入式Linux系统中,“上电到进入用户空间”并不是一步完成的,而是一条由多个阶段接力执行的启动链。RK3588 作为一颗典型的 ARM64 多核 SoC,其启动过程可以概括为:BootROM → 一级引导(TPL/SPL)→ U-Boot → Linux Kernel → rootfs → init/用户空间。理解每一级的职责边界,是后续构建 rootfs、打包固件、排查“卡在启动阶段”问题的前提。

一、启动链的整体结构与各级职责

嵌入式系统与 PC 的最大区别在于:PC 有 BIOS/UEFI 固件负责初始化并寻找引导设备,而嵌入式 SoC 通常把最初始的引导代码固化在芯片内部的 ROM 中,称为 BootROM。它无法被修改,只能被“配合”。RK3588 的启动链正是围绕 BootROM 的加载规则展开的。

各级职责可以这样划分:

  • BootROM:芯片上电后最先运行的固化代码。负责最基本的时钟、电源域初始化,然后根据启动模式(eMMC、SD、SPI Flash、USB 等)从对应介质读取一级引导程序到片内 SRAM 并校验、跳转执行。
  • TPL/SPL(一级引导):运行在片内 SRAM 中,空间很小。主要任务是初始化 DDR 控制器,把完整的 U-Boot 从存储介质搬运到 DDR 中,然后跳转。
  • U-Boot:功能完整的引导加载程序。负责更全面的硬件初始化(网络、存储、显示等),提供命令行交互,加载内核镜像、设备树和根文件系统,并把控制权交给内核。
  • Linux Kernel:解压并启动内核,初始化内存管理、调度、驱动子系统,挂载 rootfs,最后启动第一个用户空间进程。
  • rootfs:根文件系统,提供 /bin、/etc、/lib 等目录和 init 程序,是用户空间程序运行的基础。
RK3588 嵌入式 Linux 启动链与介质流向 BootROM 固化 · 不可改 选启动介质 TPL / SPL 片内 SRAM 初始化 DDR U-Boot DDR 中运行 加载内核/DTB Linux Kernel 驱动 · 调度 挂载 rootfs rootfs + init /bin /etc /lib 用户空间 存储介质与加载对象 eMMC / SD / SPI Flash:存放 idbloader.img(含 TPL+SPL)、u-boot.itb、boot.img(kernel+dtb)、rootfs 分区 USB / MaskROM 模式:BootROM 通过 USB 接收 loader,用于量产烧录与救砖 关键交接点 BootROM → SPL:SRAM 地址跳转 SPL → U-Boot:DDR 已可用 U-Boot → Kernel:bootargs + DTB RK3588 特点 支持 eMMC/SD/SPI/USB 多启动 FIT 镜像(u-boot.itb / boot.img) ATF + OP-TEE 参与安全启动 常见卡点 DDR 初始化失败 → 无串口输出 DTB 不匹配 → 内核 panic rootfs 挂载失败 → VFS 报错

二、从 U-Boot 到内核:加载顺序与参数传递

U-Boot 阶段是开发者介入最多的一环。它从存储介质读取内核镜像与设备树,并把启动参数通过 bootargs 传给内核。RK3588 常见的启动命令如下:

# U-Boot 中查看与设置启动参数
printenv bootargs
setenv bootargs console=ttyFIQ0,1500000n8 root=/dev/mmcblk0p6 rw rootwait
saveenv

# 从 eMMC 加载内核与 DTB 并启动
load mmc 0:4 ${kernel_addr_r} Image
load mmc 0:4 ${fdt_addr_r} rk3588s-board.dtb
booti ${kernel_addr_r} - ${fdt_addr_r}

其中 root= 指定根文件系统所在分区,rootwait 表示等待存储设备就绪后再挂载。若 rootfs 分区号写错,内核会报 VFS: Cannot open root device 并进入 panic。这是 rootfs 部署阶段最常见的错误之一。

三、内核与 rootfs 的衔接

内核启动后会依次完成:解压自身、建立页表、初始化调度与中断、探测驱动、挂载 rootfs、执行 /sbin/init(或 /init)。rootfs 的 init 程序负责启动系统服务、挂载其他分区、拉起 shell 或应用。因此 rootfs 不是“可有可无的文件集合”,而是启动链的最后一棒。

内核命令行中的 root=、rootfstype=、init= 三个参数,直接决定 rootfs 能否被正确挂载和初始化。构建 rootfs 时,必须保证其文件系统类型与内核配置中的驱动一致。

四、典型场景与误区复盘

假设一块 RK3588 开发板上电后串口无任何输出。排查顺序应遵循启动链:先确认 BootROM 是否进入下载模式(MaskROM),再确认 SPL 是否成功初始化 DDR,然后看 U-Boot 是否打印版本信息,最后看内核是否解压。若 U-Boot 有输出但内核无输出,问题通常在内核镜像地址、DTB 或 bootargs。

阶段 运行位置 核心职责 典型失败现象
BootROM 芯片内部 ROM 选介质、读一级引导、校验跳转 完全无输出,需进 MaskROM
TPL/SPL 片内 SRAM 初始化 DDR、搬运 U-Boot 串口打印 DDR 初始化失败
U-Boot DDR 硬件初始化、加载内核与 DTB 停在 U-Boot 命令行
Kernel DDR 驱动、调度、挂载 rootfs Kernel panic、VFS 报错
rootfs eMMC/SD/NFS 提供 init 与用户空间 init 找不到、服务起不来
调试建议:保留一路串口日志,从 BootROM 到 init 的每一级都会打印关键信息。把日志按阶段切分,能快速定位是“引导问题”还是“rootfs 问题”。
常见误区:把 rootfs 构建与内核配置割裂对待。实际上,rootfs 的文件系统类型、init 路径、动态库架构都必须与内核和目标平台匹配,否则启动链会在最后一环断裂。

总结来说,RK3588 的启动是一条严格接力的链路:BootROM 负责“找到并信任”一级引导,SPL 负责“把 DDR 打开”,U-Boot 负责“把内核请进来”,内核负责“把 rootfs 挂起来”,rootfs 负责“把系统跑起来”。每一级的输出都是下一级的输入,任何一环的参数或镜像不匹配,都会让整条链停在半途。