3. U-Boot配置系统

说到U-Boot的配置系统,我刚开始接触的时候也觉得挺绕的。说白了,它就是一套让你能「选功能、定参数」的机制。你想想看,一块开发板要支持NAND Flash,另一块要用eMMC,总不能每次都改源码吧?

U-Boot的配置系统,核心就三样东西:Kconfig、defconfig、menuconfig。这三兄弟配合起来,让你不用碰C代码,就能把U-Boot定制得服服帖帖。

3.1 Kconfig:配置的「骨架」

Kconfig是什么?它其实是一种配置描述语言。U-Boot里每个模块、每个驱动,都会有一个Kconfig文件。这个文件里定义了「有哪些选项可以配置」。

举个例子,你想知道某个驱动能不能被编译进U-Boot,就去翻它的Kconfig。比如NAND驱动的Kconfig里,会有类似这样的内容:

config NAND_SUNXI
    bool "Support for Allwinner NAND controller"
    depends on ARCH_SUNXI
    help
      Say Y here to enable support for the NAND controller
      found on Allwinner SoCs.

这里每一行都有讲究:

  • config NAND_SUNXI:这是配置项的名字,编译的时候会变成CONFIG_NAND_SUNXI这个宏。
  • bool:表示这是一个开关选项,要么Y(选中),要么空(不选)。
  • depends on:依赖关系。只有ARCH_SUNXI被选中了,这个选项才会出现。
  • help:帮助信息,告诉你这个选项是干嘛的。

我个人习惯,拿到一块新板子,第一件事就是去board/和drivers/目录下扫一遍Kconfig。这样能快速摸清这个平台支持哪些外设。

小技巧:Kconfig支持select关键字,可以强制选中另一个选项。比如某个驱动依赖DMA,可以用select DMA自动把DMA打开。但小心别搞出循环依赖,我曾经就被这个坑过。

3.2 defconfig:板级的「配置快照」

defconfig文件,说白了就是一份「配置清单」。它记录了某块开发板的所有配置选项。U-Boot源码里,每个官方支持的板子都有一个对应的defconfig文件。

比如configs/orange_pi_zero_defconfig,打开看看:

CONFIG_ARM=y
CONFIG_ARCH_SUNXI=y
CONFIG_MACH_SUN8I_H3=y
CONFIG_DRAM_CLK=408
CONFIG_MMC=y
CONFIG_MMC_SUNXI=y
CONFIG_USB=y
CONFIG_USB_EHCI_HCD=y

这里每一行都是一个配置项。注意看,CONFIG_DRAM_CLK=408这种是带数值的,不是简单的开关。

我在项目中遇到过一个问题:明明在menuconfig里配好了,编译出来却不生效。后来发现,是因为我改了.config文件,但没同步到defconfig里。记住,defconfig才是最终版本,.config只是临时文件。

注意:修改配置后,记得用make savedefconfig把当前配置保存回defconfig。否则下次make distclean后,你的配置就丢了。

3.3 menuconfig:图形化的配置界面

说实话,直接改defconfig文件挺累的。尤其是选项多的时候,记不住哪个依赖哪个。这时候menuconfig就派上用场了。

在U-Boot根目录下执行:

make menuconfig

你会看到一个蓝底白字的界面。上下键移动,回车进入子菜单,空格切换选项。嗯,操作起来有点像老式的BIOS设置界面。

menuconfig的好处是:

  • 依赖关系自动处理:你选了一个选项,它依赖的选项会自动被选中。
  • 搜索功能:按/键,输入关键字,能快速定位到配置项。
  • 实时查看帮助:选中一个选项,按?就能看到它的帮助信息。

我曾经调试一个USB启动问题,在menuconfig里搜USB,把所有相关的选项都过了一遍。最后发现是CONFIG_USB_EHCI_HCD没开,导致USB控制器根本没初始化。

核心流程:menuconfig修改后,配置会保存到.config文件。然后make的时候,.config会被转换成include/autoconf.mk,最终变成C代码里的宏定义。

3.4 配置系统的完整流程

为了让你看得更清楚,我画了一张流程图:

U-Boot配置系统完整流程 Kconfig 文件 定义所有配置选项 defconfig 文件 板级配置快照 menuconfig 图形化配置界面 .config 文件 当前配置(临时) autoconf.mk Makefile可用的宏 编译 生成U-Boot 修改配置 savedefconfig 核心文件 交互工具 输出产物

流程其实很简单:

  1. Kconfig 定义了「有哪些选项」。
  2. defconfig 定义了「某块板子选了哪些」。
  3. 你可以用 menuconfig 临时调整配置,结果存到 .config。
  4. 编译时,.config 被转换成 autoconf.mk,供Makefile使用。
  5. 最后,用 savedefconfig 把当前配置写回defconfig,永久保存。
我的习惯:每次调完配置,先用make menuconfig确认没问题,然后make savedefconfig,最后把生成的defconfig文件复制到configs/目录下。这样既保留了临时修改,又更新了板级配置。

嗯,配置系统这块,说白了就是「定义-选择-生成」三个步骤。Kconfig负责定义,defconfig和menuconfig负责选择,编译系统负责生成。搞懂了这三者的关系,U-Boot的配置对你来说就不再是黑盒了。

一句话总结:Kconfig是菜单,defconfig是点好的菜,menuconfig是临时加菜,.config是当前这桌的菜单,autoconf.mk是后厨用的配料单。

可可精品资料库