U-Boot概述:从历史到启动流程

大家好,我是你们的讲师。今天咱们开始第一讲,聊聊U-Boot到底是什么,它在嵌入式系统里扮演什么角色,以及它上电后都干了些什么。

说实话,我最早接触U-Boot是在2008年,那时候做一款基于ARM9的工控板。板子刚焊好,上电后串口啥输出都没有,折腾了两天才发现是U-Boot的配置没改对。从那以后,我就跟这个“小玩意儿”结下了不解之缘。

U-Boot的历史与作用

U-Boot,全称是“Universal Boot Loader”。它最初是从德国DENX软件实验室的Wolfgang Denx发起的。你想想看,2000年初那会儿,嵌入式芯片五花八门,每个厂家都有自己的启动代码,移植起来特别痛苦。U-Boot的出现,说白了就是想把这事儿统一了。

它的核心作用就三个:

  • 初始化硬件:CPU、内存、串口、Flash,这些外设上电后都是“裸”的,U-Boot得先把它们“唤醒”。
  • 加载操作系统:从Flash、网络或者SD卡里把内核镜像读出来,放到内存里,然后跳过去执行。
  • 提供调试接口:通过命令行,你可以修环境变量、烧写固件、测试内存。我当年调试一块DDR3的板子,就是靠U-Boot的md和mw命令一点点排查出来的。

重要概念:U-Boot本身也是一个“小操作系统”。它有命令行、文件系统支持、网络协议栈。只不过它运行在实模式或非保护模式下,功能比Linux精简得多。

U-Boot在嵌入式系统中的位置

咱们来看一张图,你就明白了。

嵌入式系统启动层次结构 BootROM(芯片内部固化) SPL(Secondary Program Loader) U-Boot(完整版) Linux内核 芯片上电后最先执行 初始化DDR、加载U-Boot 提供命令行、加载内核 真正的操作系统

嗯,这里要注意。U-Boot并不是直接跑在芯片最底层的。芯片内部有一个很小的BootROM,它先运行,然后加载SPL(如果你用现代芯片的话),SPL再加载完整的U-Boot。我见过不少新手直接跳过SPL去改U-Boot,结果板子起不来,其实就是SPL配置没对上。

个人经验:我在调试i.MX6ULL板子时,遇到过SPL阶段DDR初始化失败的问题。当时串口只打印了一个“CC”就卡住了。后来发现是DDR时序参数配错了。所以,SPL阶段的调试信息非常关键,建议你一开始就把串口输出打开。

U-Boot启动流程概览

U-Boot的启动流程,我习惯把它分成三个阶段:

  1. 第一阶段:汇编阶段
    • 设置CPU模式(通常是SVC模式)
    • 关闭中断、MMU、Cache
    • 初始化栈指针
    • 拷贝U-Boot自身到RAM(如果是从Flash启动)
  2. 第二阶段:C语言初始化
    • 调用board_init_f():初始化时钟、串口、DDR
    • 重定位U-Boot到DDR的高地址
    • 调用board_init_r():初始化剩余外设
  3. 第三阶段:命令行循环
    • 进入main_loop()
    • 检查是否有自动启动命令(比如bootcmd环境变量)
    • 如果没有,进入交互式命令行

为什么会分成这么多个阶段?说白了,就是硬件资源有限。一开始CPU只能访问片内SRAM,容量很小,放不下完整的U-Boot。所以先跑一小段汇编,把DDR初始化好,再把完整的U-Boot拷贝过去,最后跳转到C代码里。

避坑指南:我曾经在重定位阶段踩过一个坑。U-Boot重定位后,原来的代码段会被覆盖。如果你在重定位前调用了某个函数指针,而这个指针指向的地址没有更新,那就会跑飞。解决办法是确保所有函数指针在重定位后重新计算地址,或者使用RELOCATE宏。

来看一段典型的启动日志,你就知道流程长什么样了:

U-Boot 2023.04 (Apr 10 2024 - 14:30:00 +0800)

CPU:   i.MX6ULL rev1.1 at 792 MHz
Board: MY-IMX6ULL
DRAM:  512 MiB
MMC:   FSL_SDHC: 0, FSL_SDHC: 1
In:    serial
Out:   serial
Err:   serial
Net:   FEC0
Hit any key to stop autoboot:  0
=>

看到没?先是打印版本信息,然后是CPU、板子、内存大小,接着是外设初始化,最后进入命令行。如果卡在“DRAM:”后面没反应,那八成是DDR初始化有问题。我当年调试一块板子,就是卡在这里,最后发现是DDR的ODT配置不对。

小结

这一章咱们把U-Boot的来龙去脉理清楚了。它不是什么神秘的东西,就是一个负责把硬件“伺候”好,然后把操作系统请进来的程序。它的启动流程虽然分了好几步,但每一步都有明确的目的。

下一章咱们会深入U-Boot的源码结构,看看那些.c和.h文件到底是怎么组织起来的。到时候我会拿一个实际项目里的配置来拆解,保证你一看就懂。

核心要点回顾:

  • U-Boot是通用引导加载程序,负责硬件初始化和加载OS
  • 它位于BootROM和Linux内核之间
  • 启动流程分汇编、C初始化、命令行三个阶段
  • SPL是现代芯片中U-Boot的前置加载器
可可精品资料库