4. U-Boot 优化:从裁剪到加速,让启动飞起来
U-Boot 是系统启动的第一道关卡。它跑得快不快,直接决定了你按下电源键后,用户要等多久才能看到 Logo。我见过不少项目,内核和根文件系统已经优化得很极致了,结果 U-Boot 愣是花了 3 秒多,白白浪费了宝贵的启动时间。
说白了,U-Boot 优化的核心就四个字:少干活,快干活。这一章,我们就来聊聊怎么做到这一点。
4.1 U-Boot 配置裁剪:减负就是加速
U-Boot 默认配置里塞了很多你可能永远用不到的功能。比如网络协议栈、文件系统支持、各种稀奇古怪的驱动。这些代码虽然不一定会执行,但编译进去后,U-Boot 的镜像体积会变大,加载和初始化时间都会变长。
我个人习惯,拿到一个新板子,第一件事就是做配置裁剪。目标是把 U-Boot 的二进制体积控制在 512KB 以内,甚至更小。
4.1.1 裁剪步骤
- 关闭不必要的命令:比如
fatload、ext2load、tftp、ping等。如果你的产品量产时不需要通过网络更新固件,这些都可以关掉。 - 精简文件系统支持:只保留你实际使用的文件系统类型。比如只用 FAT32 来存放内核和设备树,那就把 ext4、btrfs 的支持都去掉。
- 去掉调试功能:
CONFIG_DEBUG、CONFIG_LOG这些在发布版本里一定要关掉。它们会往串口打印大量信息,拖慢速度。
关键配置项示例(在 menuconfig 中操作)
# 关闭不必要的命令
CONFIG_CMD_BOOTM=n
CONFIG_CMD_FAT=n
CONFIG_CMD_EXT4=n
CONFIG_CMD_NET=n
CONFIG_CMD_PING=n
# 关闭调试
CONFIG_DEBUG=n
CONFIG_LOG=n
# 精简驱动
CONFIG_DM_MMC=n # 如果不用 MMC
CONFIG_DM_USB=n # 如果不用 USB
我的经验:裁剪时别太激进。我曾经把 CONFIG_CMD_BOOTM 关掉了,结果内核启动不起来,查了半天才发现是少了这个命令。建议每次裁剪后都做一次完整的启动测试。
4.2 Fastboot 模式:量产和调试的利器
Fastboot 是 Google 提出的一种协议,用于在设备启动早期与主机通信。在 Tina Linux 中,U-Boot 支持 Fastboot 模式,这对量产烧录和现场调试非常有用。
为什么说它快?因为 Fastboot 直接通过 USB 传输数据,不需要经过网络协议栈,也没有文件系统的开销。说白了,就是裸数据传输。
4.2.1 启用 Fastboot
在 U-Boot 配置中启用 Fastboot 支持:
CONFIG_USB_FUNCTION_FASTBOOT=y
CONFIG_CMD_FASTBOOT=y
然后在 U-Boot 命令行中进入 Fastboot 模式:
# fastboot usb 0
主机端就可以用 fastboot flash 命令烧录分区了。
注意:Fastboot 模式会占用 USB 设备。如果你的产品需要同时使用 USB 做其他事情(比如 ADB),需要做好切换逻辑。我记得有个项目,量产时 Fastboot 和 ADB 冲突了,导致烧录一半设备断开,最后不得不改硬件设计。
4.3 U-Boot 环境变量优化:别让配置拖后腿
U-Boot 环境变量存储在 Flash 或 EMMC 的特定分区里。每次启动时,U-Boot 都要读取这些变量。如果变量太多,或者存储位置太慢,就会增加启动时间。
4.3.1 精简环境变量
默认的环境变量里有很多调试用的变量,比如 bootargs 里可能有一长串内核参数。我的建议是:
- 只保留必要的变量:比如
bootcmd、bootargs、fdt_addr、kernel_addr。 - 合并变量:把多个
setenv命令合并成一个bootcmd脚本。
优化前后的 bootcmd 对比
| 优化前(慢) | 优化后(快) |
|---|---|
|
|
你看,优化后的版本把多个 setenv 和 fatload 合并到了一个 bootcmd 里。这样 U-Boot 只需要执行一次环境变量解析,而不是多次。
4.3.2 存储位置优化
环境变量默认存储在 SPI Flash 或 NAND 上。这些存储介质的读取速度通常比 EMMC 慢。如果你的板子有 EMMC,可以考虑把环境变量移到 EMMC 上。
CONFIG_ENV_IS_IN_MMC=y
CONFIG_SYS_MMC_ENV_DEV=0
CONFIG_SYS_MMC_ENV_PART=0
避坑指南:我曾经把环境变量从 SPI Flash 移到 EMMC 后,启动时间缩短了 200ms。但要注意,EMMC 的初始化时间比 SPI Flash 长,所以这个优化不是绝对的。建议实际测量后再决定。
4.4 U-Boot 驱动延迟优化:把等待时间砍掉
U-Boot 在初始化过程中,会逐个初始化各个硬件驱动。有些驱动在初始化时会有固定的延时,比如等待 PHY 稳定、等待时钟锁定等。这些延时往往是硬编码的,但很多时候并不需要那么长。
4.4.1 常见的驱动延迟点
| 驱动类型 | 常见延迟 | 优化建议 |
|---|---|---|
| Ethernet PHY | 等待自协商完成(通常 2-3 秒) | 如果不需要网络启动,可以跳过 PHY 初始化 |
| MMC/SD 卡 | 等待卡检测(通常 100-500ms) | 使用 CONFIG_MMC_DEFAULT_DEV 指定默认设备,跳过检测 |
| USB | 等待设备枚举(通常 1-2 秒) | 如果不需要 USB 启动,可以关闭 USB 初始化 |
| 时钟/锁相环 | 等待锁定(通常 10-100ms) | 检查数据手册,确认最小锁定时间,减少等待 |
4.4.2 实战:优化 PHY 延迟
我记得有个项目,U-Boot 启动花了 4 秒,其中 PHY 自协商就占了 2.5 秒。我们的产品根本不需要网络启动,所以直接跳过了 PHY 初始化。
在 board_init() 或 board_early_init() 中,添加条件判断:
#ifndef CONFIG_CMD_NET
// 跳过 PHY 初始化
return 0;
#endif
这样,U-Boot 就不会去等待 PHY 自协商了。启动时间直接从 4 秒降到了 1.5 秒。
注意:跳过驱动初始化要谨慎。如果你后续需要通过 U-Boot 的网络功能更新固件,那 PHY 初始化就不能省。建议在量产版本中关闭,在调试版本中保留。
4.5 本章知识体系
下面这张图总结了 U-Boot 优化的四个核心方向,以及它们之间的关系:
嗯,到这里,U-Boot 优化的四个核心方向就讲完了。配置裁剪是基础,Fastboot 是工具,环境变量优化是细节,驱动延迟优化是硬骨头。每个方向都能帮你省下几百毫秒甚至几秒的启动时间。
记住,优化不是一蹴而就的。我建议你每次只做一个改动,然后测量启动时间,确认效果后再做下一个。这样出了问题也容易回退。