1. 启动流程概述:从按下电源键到操作系统加载

大家好,我是这次课程的主讲工程师。今天咱们聊聊嵌入式系统里最基础、也最容易踩坑的一个话题——启动流程。

你按下电源键的那一刻,系统里发生了什么?

说实话,我早年做第一块开发板时,以为启动就是“上电→跑代码”这么简单。结果板子焊好,上电后屏幕一片漆黑,串口也没输出。折腾了两天才发现,是复位时序没配好。嗯,从那以后,我对启动流程就再也不敢马虎了。

1.1 按下电源键:硬件层面的第一反应

你按下电源键,系统并不是立刻开始跑代码。硬件要先完成几件事:

  • 电源稳定:电源管理芯片(PMIC)开始工作,输出各路电压。CPU核心、DDR、外设IO,电压不同,上电顺序也有讲究。
  • 时钟起振:晶振开始震荡,产生系统时钟。我遇到过晶振起振慢的情况,导致复位信号释放时时钟还没稳定——系统直接跑飞。
  • 复位释放:复位信号从低电平拉高,CPU从复位向量地址开始取指。

关键点:复位向量地址是CPU上电后第一条指令的存放位置。ARM Cortex-M系列通常是0x00000000,x86则是0xFFFFFFF0。这个地址指向的,就是BootROM或Flash的起始位置。

1.2 BootROM:芯片出厂就写好的“第一段代码”

CPU复位后,首先执行的是芯片内部固化的BootROM代码。这段代码是芯片出厂时写死的,用户改不了。

BootROM的任务很简单:

  • 初始化最基本的硬件:CPU、时钟、内存控制器
  • 检测启动介质:是从NAND Flash启动?还是SD卡?还是UART下载?
  • 加载下一级Bootloader到SRAM或DDR中

我做过一个项目,BootROM里有个bug——检测SD卡时,如果卡没插好,会死循环。结果生产线上有5%的板子启动不了。排查了三天,最后发现是卡槽接触不良。后来我们在硬件上加了个卡检测引脚,才彻底解决。

避坑指南:我曾经在选型时忽略了BootROM支持的启动介质列表。结果芯片买回来才发现,它不支持从SPI NAND启动,而我们设计的就是SPI NAND方案。最后只能改板子,多花了两周时间。

1.3 Bootloader:从固件到操作系统的桥梁

BootROM加载完Bootloader后,控制权就交给了它。Bootloader是用户可定制的,常见的有U-Boot、GRUB、Coreboot等。

Bootloader要做的事:

  1. 初始化DDR:配置内存控制器,让DDR可用。这一步很关键,参数配错了系统直接挂。
  2. 初始化存储设备:比如eMMC、NAND Flash、SD卡
  3. 加载操作系统内核:从存储设备读取内核镜像到内存中
  4. 传递启动参数:比如内核命令行、设备树(DTB)地址
  5. 跳转到内核入口:把控制权交给操作系统

你想想看,Bootloader其实就是一个“小操作系统”。它有自己的驱动、文件系统支持,甚至网络协议栈。U-Boot里还能执行脚本,做复杂的启动逻辑。

1.4 内核启动:操作系统的“初始化”

内核拿到控制权后,开始做自己的初始化:

  • 解压内核:如果内核是压缩的,先解压到内存中
  • 初始化MMU:开启内存管理单元,建立页表
  • 初始化中断控制器:配置GIC(通用中断控制器)
  • 初始化定时器:系统时钟滴答开始工作
  • 初始化设备驱动:根据设备树或ACPI表,逐个初始化外设
  • 挂载根文件系统:找到并挂载根分区
  • 启动init进程:用户空间的第一个进程,PID为1

注意:内核启动过程中,如果某个驱动初始化失败,内核可能panic(崩溃)。我调试过一个案例,是因为设备树里GPIO编号写错了,导致按键驱动初始化时访问了非法地址,系统直接重启。查了两天才定位到问题。

1.5 整体流程:一张图看懂

下面这张图,是我自己画的启动流程。你看一遍,基本就清楚了:

系统启动全流程 按下电源键 电源稳定 / 时钟起振 复位释放 BootROM 初始化CPU / 时钟 检测启动介质 Bootloader 初始化DDR / 存储 加载内核镜像 Linux内核 解压 / MMU / 中断 设备驱动初始化 用户空间 挂载根文件系统 启动init进程 各阶段关键动作 1. 硬件层:PMIC上电 → 晶振起振 → 复位释放 2. BootROM:固化代码 → 检测启动介质 → 加载BL 3. Bootloader:DDR初始化 → 存储驱动 → 加载内核 4. 内核:解压 → MMU → 中断 → 驱动 → 挂载根FS 5. 用户空间:init进程 → 系统服务 → 应用程序 常见问题: • 复位时序不对 → 系统无法启动 • DDR参数错误 → 内核崩溃 • 设备树配置错 → 驱动加载失败

1.6 启动过程中的几个关键时间点

做嵌入式系统,启动时间是硬指标。我整理了几个关键阶段的时间参考:

阶段 典型耗时 说明
硬件初始化 10~100ms 电源稳定、时钟起振、复位
BootROM 50~500ms 取决于启动介质检测速度
Bootloader 100ms~2s DDR初始化、存储读取、内核加载
内核启动 500ms~5s 驱动初始化、根文件系统挂载
用户空间 100ms~1s init进程、系统服务启动

优化建议:我曾经在一个车载项目中,要求启动时间小于2秒。我们做了几件事:去掉不必要的驱动、使用压缩内核、优化Bootloader的存储读取速度。最后把启动时间从4秒压到了1.8秒。说白了,启动优化就是“砍掉不需要的,加速必须的”。

1.7 小结

启动流程,说白了就是一条“接力赛”:硬件准备好基础环境,BootROM把接力棒交给Bootloader,Bootloader加载内核,内核初始化系统,最后交给用户空间。

每个环节都有坑。我见过因为复位电容选大了导致启动延迟的,也见过BootROM里启动介质优先级配错导致从错误设备启动的。嗯,这些坑后面章节会一个个展开讲。

记住一句话:启动流程不是玄学,是硬件和固件一步步协作的结果。你理解了每一步在做什么,出了问题就知道从哪里下手。

可可精品资料库