当前位置:首页>Linux>一块嵌入式Linux板子上电以后竟然偷偷干了这么多事

一块嵌入式Linux板子上电以后竟然偷偷干了这么多事

  • 2026-10-11 06:04:32
一块嵌入式Linux板子上电以后竟然偷偷干了这么多事

——从BootROM到用户应用,别再把启动流程看成一串黑盒日志


如果你第一次接触嵌入式 Linux,大概率见过这种场景:板子一上电,串口终端里哗啦啦刷一堆日志,先是 U-Boot,然后是 kernel,然后是各种驱动打印,最后出来一个 login 或者 shell。

你看着它启动成功了,好像也挺开心。但真让你解释“刚才到底发生了什么”,很多人就开始含糊:

BootROM 是谁?

U-Boot 为什么要存在?

内核是从哪加载的?

设备树是什么时候用上的?

RootFS 又是什么时候挂载的?

这些东西如果没连起来,后面你学设备树、驱动、文件系统、启动优化、系统裁剪,都会像在看一堆散点。

所以这篇不讲某个具体芯片的启动寄存器,也不钻 U-Boot 源码。我们先把嵌入式 Linux 上电启动的主线概念理清楚。

一块 Linux 板子从上电到跑应用,本质上是在一步步把“裸硬件”变成“可运行应用的系统环境”。


一、先看全流程

一块典型嵌入式 Linux 板子,上电以后大概会走这条链路:

后面所有启动问题,基本都能挂回这条链路上。

板子没反应,可能卡在 BootROM 或 Bootloader;内核起不来,可能是 kernel、设备树、启动参数问题;内核起来但进不了系统,可能是 RootFS 挂载失败;系统起来但应用没跑,可能是 init 脚本或 systemd 服务问题。

也就是说,启动流程不是一坨日志,而是一条有阶段、有交接的链路。


二、第一站:BootROM,芯片上电后的第一口气

BootROM 是芯片内部固化的一小段代码。它不是你编译出来烧进去的,也不是 Linux 的一部分,而是芯片厂商在芯片里预置好的启动代码。

它的任务很朴素:芯片刚上电时,CPU 总得从某个地方开始执行第一条指令。这个“第一个地方”,通常就是 BootROM。

BootROM 会根据芯片的启动配置,决定从哪里找下一阶段程序。比如:

  • SD 卡 、eMMC、 Flash
  • USB 下载模式、UART 下载模式

你可以把 BootROM 理解成门卫。板子一上电,它先醒,看看启动拨码、熔丝位或引脚配置,然后决定“我该从哪里把下一段程序请进来”。

这也是为什么有些板子能从 SD 卡启动,有些能从 eMMC 启动,有些短接某个引脚就进入烧录模式。这些都和 BootROM 的启动策略有关。


三、第二站:Bootloader,最常见的是U-Boot

BootROM 能做的事情通常很有限。它不适合直接把 Linux 内核完整拉起来,所以它一般会加载一个更强的启动程序,也就是 Bootloader。

在嵌入式 Linux 里,最常见的 Bootloader 是 U-Boot。

U-Boot 主要干几件事:

工作
作用
初始化DDR
让系统有可用内存
初始化基础外设
串口、存储、网口等
加载内核镜像
从 Flash、eMMC、SD、网络等位置读取 kernel
加载设备树
把板级硬件描述交给内核
设置启动参数
比如 rootfs 在哪里、console 用哪个串口
跳转到内核
把控制权交给 Linux Kernel

这里最关键的是 DDR 初始化。Linux 内核运行起来需要比较大的内存,BootROM 阶段通常还没把 DDR 完整配置好,所以 U-Boot 要先把这件事搞定。

换个比喻,BootROM 像门卫,U-Boot 就像开工前的现场负责人。它先把水电、仓库、通道准备好,再把真正干活的队伍,也就是 Linux 内核,请进场。


四、第三站:Kernel,真正的操作系统核心开始接管

U-Boot 把内核加载到内存后,会把控制权交给 Linux Kernel。到这里,系统才开始真正进入 Linux 世界。

Kernel 启动时会做很多事,比如:

  • 初始化 CPU 和内存管理
  • 建立调度器
  • 初始化中断系统
  • 启动内核线程
  • 根据设备树匹配驱动
  • 初始化文件系统、网络、设备模型

这些听起来很多,但你可以先抓住主线:

内核启动的过程,就是 Linux 开始接管硬件和系统资源的过程。

在 RTOS 里,你可能自己写外设初始化、任务创建、驱动初始化。到了 Linux,很多系统级初始化由内核完成,而且它不是按你业务代码的顺序跑,而是按内核框架和驱动模型来组织。

这也是为什么看 Linux 启动日志时,你会看到各种驱动、总线、文件系统、网络模块陆续打印。它们不是乱刷,而是在内核接管系统的过程中逐步被初始化。


五、设备树什么时候登场?

设备树,也就是 Device Tree,是嵌入式 Linux 里非常关键的东西。它通常由 U-Boot 加载,然后传给内核。

那设备树到底干嘛?

设备树负责告诉内核:这块板子的硬件长什么样。

比如:

  • 有哪些外设、挂在哪条总线上
  • 寄存器地址是多少、中断号是多少
  • GPIO 怎么连、时钟怎么接
  • 哪些设备启用,哪些禁用

为什么不直接写死在驱动里?

因为同一个芯片可以做很多块不同的板子。UART 可能接到不同引脚,I2C 上挂的设备可能不同,屏幕、网口、按键、电源管理芯片都可能换。

如果这些都写死在驱动里,每换一块板就改驱动,那驱动会非常痛苦。

设备树的价值就是把“硬件描述”和“驱动逻辑”分开:

内容
放哪里
这块板有什么硬件
Device Tree
这个硬件怎么工作
Driver

所以学习 Linux 驱动时,会经常遇到 compatible、reg、interrupts 这些字段。它们不是为了折磨你,而是在帮内核完成“设备和驱动怎么匹配”这件事。


六、RootFS:内核启动后,总得有个家

内核起来以后,还不等于系统能用了。

它还需要挂载根文件系统,也就是 RootFS。

RootFS 里面有什么?

一般包括:

  • /bin、/sbin 里的基础命令
  • /lib 里的库
  • /etc 里的配置
  • /dev 里的设备节点
  • /proc、/sys 这类虚拟文件系统挂载点
  • 应用程序、脚本、服务配置

如果说 Kernel 是系统的大脑,那 RootFS 就像系统的生活区。没有 RootFS,内核可能已经启动了,但它找不到用户态程序,也就没法真正进入可用状态。

很多启动失败都会卡在这里,比如:

  • VFS: Unable to mount root fs
  • root 参数写错
  • 文件系统格式不支持
  • 存储设备驱动没起来
  • /sbin/init 找不到

所以看到板子“内核起来了但进不了系统”,别急着怀疑应用,先看 RootFS 有没有挂上。


七、init/systemd:用户空间的第一棒

RootFS 挂载成功以后,内核会启动用户空间的第一个进程。传统上这个进程叫 init,很多现代 Linux 系统会用 systemd。

这个进程很关键,因为它是用户空间的起点。

它负责继续拉起系统服务,比如:

  • 挂载其他文件系统、初始化网络
  • 启动日志服务、后台守护进程、业务应用
  • 提供登录 shell

所以如果系统能进内核,但应用没跑,问题可能不在内核,而在 init 脚本、systemd service、启动顺序、环境变量、权限这些用户空间问题上。

这就是 Linux 和 RTOS 很不一样的地方。

RTOS 里你写任务创建,系统上来就按你的固件逻辑跑。Linux 里,内核先把系统环境搭起来,然后由用户空间启动各种服务和应用。


八、启动问题怎么定位

理解这条链路以后,启动问题就不再是一坨日志了。

你可以按阶段判断:

现象
优先怀疑
串口完全没输出
供电、晶振、BootROM、启动介质
只看到U-Boot
内核镜像、启动命令、存储读取
内核解压后卡住
设备树、内核配置、串口console
驱动初始化报错
设备树、驱动、时钟、中断、引脚
Unable to mount root fs
RootFS、root参数、存储驱动
进入系统但应用没起
init脚本、systemd服务、权限、路径

这张表比死背启动日志有用。

因为你知道每一段是谁交给谁,哪里没交接成功,就顺着那一段查。


九、最后总结一下

嵌入式 Linux 上电启动,不是一口气从硬件跳到应用。

它是一棒接一棒:

BootROM 找到 Bootloader,Bootloader 准备环境并加载 Kernel,Kernel 接管系统并挂载 RootFS,init/systemd 拉起用户空间,最后你的应用才开始跑。

可以把它记成这条主线:

上电 -> BootROM -> U-Boot -> Kernel + Device Tree -> RootFS -> init/systemd -> App

这条线一旦立住,再想想你学习的 U-Boot、设备树、驱动、RootFS、Buildroot,就不会觉得它们是散的。


相关文章


你第一次看 Linux 启动日志时,最懵的是 U-Boot、设备树,还是 RootFS 挂载失败?

最新文章

随机文章