3、U-Boot源码获取与编译:从官方仓库获取源码、配置默认板型、编译流程解析
好,咱们进入正题。这一章要解决的是「怎么把U-Boot弄到手,并且让它跑起来」的问题。
很多新手上来就卡在这一步——源码下载了,make一敲,报一堆错。别急,我带你一步步走通。
3.1 从官方仓库获取源码
U-Boot的官方仓库在 denx.de 的Git服务器上。我个人习惯用 git://git.denx.de/u-boot.git 这个地址。
克隆命令很简单:
git clone git://git.denx.de/u-boot.git
cd u-boot
嗯,这里要注意。如果你在公司内网,或者网络环境不太好,建议用 https:// 协议:
git clone https://git.denx.de/u-boot.git
为什么?因为有些防火墙会封掉git协议端口。我在项目里遇到过,明明网络通着,就是克隆不下来,换成https秒搞定。
克隆完成后,你会看到一堆分支和标签。我个人建议先切到一个稳定的发布版本,比如 v2024.01:
git checkout v2024.01
为什么要用发布版?因为主线上的代码可能正在开发中,说不定哪天就编译不过了。你想想看,做产品移植,稳定第一。
3.2 配置默认板型
源码拿到了,接下来要配置。U-Boot支持几百种开发板,每种板子都有自己的配置。
先看看你的板子有没有现成的支持:
ls configs/ | grep <你的芯片型号>
比如我用的是 stm32mp157,就会看到:
stm32mp15_defconfig
stm32mp15_basic_defconfig
stm32mp15_trusted_defconfig
配置命令很简单:
make stm32mp15_defconfig
执行后,U-Boot会生成 .config 文件。这个文件里记录了所有配置选项,说白了就是你的板子「长什么样」。
核心概念: defconfig 是板级配置的「模板」,.config 是最终生效的「实际配置」。两者之间通过 make menuconfig 可以微调。
如果你需要调整配置,比如打开某个驱动:
make menuconfig
这个界面是图形化的,用方向键操作。我曾经在调一个网卡驱动时,就是在这里把 CONFIG_ETH_DESIGNWARE 勾上,才让网络跑起来的。
3.3 编译流程解析
配置好了,编译就简单了:
make -j$(nproc)
-j$(nproc) 表示用所有CPU核心并行编译,能快不少。我第一次编译时没加这个参数,等了快10分钟,后来同事提醒才加上,速度直接翻倍。
编译完成后,你会得到几个关键文件:
| 文件 | 说明 |
|---|---|
u-boot.bin |
纯二进制镜像,直接烧写到Flash |
u-boot.img |
带U-Boot头部的镜像,用于网络启动 |
u-boot-spl.bin |
SPL(第一阶段引导),用于启动主U-Boot |
u-boot.dtb |
设备树文件,描述硬件信息 |
这里有个坑:如果你的板子需要SPL,那 u-boot-spl.bin 才是烧写到Flash的第一个文件。主U-Boot由SPL加载到内存中运行。
注意: 编译前一定要确认交叉编译工具链。比如ARM板子,需要设置 CROSS_COMPILE=arm-linux-gnueabihf-。我见过有人用x86的gcc编译ARM代码,结果一堆「未定义的指令」错误。
3.4 编译流程的底层逻辑
你可能好奇,make 背后到底干了什么?我画了一张图,帮你理清思路:
这张图展示了编译的三个主要阶段。实际执行时,Makefile会递归调用子目录的Makefile,一层层编译。
如果你想知道具体编译了哪些文件,可以加 V=1 参数:
make V=1 -j$(nproc)
这样会打印出每条编译命令。我在调试编译错误时,经常用这个参数来定位问题。
3.5 常见问题与避坑
小技巧: 如果你改了配置,想重新编译,记得先 make clean 清理旧文件。不然可能残留旧的 .o 文件,导致奇怪的问题。
我曾经犯过一个错误:改了设备树,但没重新编译,结果板子启动时设备树还是旧的,外设全没初始化。折腾了半天才发现是缓存问题。
另外,如果你用的是 git 管理的源码,建议每次编译前先 git status 看看有没有未提交的修改。这样出了问题也好回退。
嗯,这一章的内容就到这里。源码获取、配置、编译,这三步走通了,你的U-Boot移植之路就迈出了最关键的一步。