4. 板级配置

说到板级配置,很多刚入行的朋友会觉得不就是选个配置文件嘛,有什么好讲的?

嗯,我当年也这么想。直到有一次,我把A款芯片的defconfig烧到了B款板子上,结果整批板子都起不来。那叫一个惨。

说白了,板级配置就是告诉U-Boot:你跑在什么硬件上,外设怎么接,内存多大,时钟多少。搞错了,系统就罢工。

defconfig是什么?

defconfig,全称是default configuration。它是U-Boot的默认配置模板。

我个人习惯把它理解成「硬件平台的身份证」。里面记录了:

  • CPU架构(ARM、RISC-V、x86等)
  • SoC型号(比如i.MX6ULL、STM32MP157)
  • 外设使能(网口、串口、USB、SD卡等)
  • 内存大小和地址映射
  • 启动设备顺序

举个例子,我手头有块i.MX6ULL的开发板,它的defconfig文件长这样:

CONFIG_ARM=y
CONFIG_ARCH_MX6=y
CONFIG_TARGET_MX6ULL_14X14_EVK=y
CONFIG_DM=y
CONFIG_DM_GPIO=y
CONFIG_DM_MMC=y
CONFIG_DM_ETH=y
CONFIG_CMD_DHCP=y
CONFIG_CMD_PING=y
CONFIG_BOOTCOMMAND="run distro_bootcmd"

看到没?每一行都是一个开关。y表示启用,n表示禁用。我建议初学者先从官方提供的defconfig开始改,别自己从头写,容易漏东西。

核心要点:defconfig决定了U-Boot能识别哪些硬件,支持哪些命令。选错了,板子可能连串口都打印不出来。

设备树(Device Tree)的作用

设备树,英文叫Device Tree,简称DT。它是描述硬件信息的结构化数据。

你想想看,以前Linux内核里全是板级文件,每个板子一个.c文件,改个引脚都要重新编译内核。后来大家觉得太蠢了,就搞出了设备树。

设备树把硬件描述和内核代码分开了。内核只负责解析设备树,不直接写死硬件信息。这样换板子只需要换设备树,不用改内核。

一个典型的设备树节点长这样:

/ {
    model = "Freescale i.MX6ULL 14x14 EVK Board";
    compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

    chosen {
        stdout-path = &uart1;
    };

    memory {
        device_type = "memory";
        reg = <0x80000000 0x20000000>;  /* 512MB RAM */
    };

    &uart1 {
        pinctrl-names = "default";
        pinctrl-0 = <&pinctrl_uart1>;
        status = "okay";
    };
};

这里我解释几个关键字段:

  • compatible:兼容性字符串,内核用它来匹配驱动
  • reg:寄存器地址或内存范围
  • status:设备状态,okay表示启用,disabled表示禁用
  • pinctrl:引脚复用配置

小技巧:我在项目中经常遇到设备树里status写成了"ok"而不是"okay",结果外设死活不工作。检查了半天才发现是拼写错误。记住,设备树里是"okay",不是"ok"。

如何选择正确的板级配置?

这个问题其实没有标准答案,但我可以分享一些实战经验。

第一步:确认SoC型号

拿到一块板子,先看芯片上的丝印。i.MX6ULL、STM32MP157、全志H3……不同SoC的defconfig完全不同。

第二步:找到对应的defconfig

在U-Boot源码的configs/目录下,有大量defconfig文件。命名规则一般是:

<厂商>_<板子型号>_defconfig

比如:mx6ull_14x14_evk_defconfig、stm32mp157d_dk1_defconfig

第三步:检查设备树文件

设备树文件在arch/arm/dts/目录下。同一个板子可能有多个设备树变体,比如:

  • imx6ull-14x14-evk.dts(标准版)
  • imx6ull-14x14-evk-emmc.dts(eMMC版)
  • imx6ull-14x14-evk-nand.dts(NAND Flash版)

我曾经踩过一个坑:客户说板子启动不了,我远程看了半天,发现他选的是NAND版的设备树,但板子上焊的是eMMC。嗯,这种问题排查起来最头疼。

警告:不要随意修改defconfig里的CONFIG_DEFAULT_DEVICE_TREE字段。这个字段指定了U-Boot使用哪个设备树文件。改错了,U-Boot可能连内存都检测不到。

板级配置的完整流程

为了让你更直观地理解,我画了一张流程图:

板级配置选择流程 确认SoC型号 查找对应defconfig 选择设备树文件 编译验证 启动成功? 常见问题 1. defconfig与设备树不匹配 2. 内存大小配置错误 3. 引脚复用冲突 4. 时钟频率设置不对 5. 启动设备顺序错误 我曾经因为选错设备树, 导致网口驱动加载失败, 排查了整整两天。

实战中的避坑指南

做量产烧录这么多年,我总结了几条经验:

  1. 永远从官方defconfig开始——不要自己造轮子,官方提供的配置经过了充分测试。
  2. 设备树里的reg字段要核对——特别是内存地址和大小,写错了系统直接崩。
  3. 注意设备树的include关系——很多设备树会include公共的.dtsi文件,改的时候要小心。
  4. 编译后检查生成的dtb文件——用fdtdump命令可以查看dtb内容,确认是否包含你需要的节点。

我的建议:在量产前,至少用三块不同批次的板子做验证。因为不同批次的板子,硬件可能有细微差异,比如内存颗粒型号变了、晶振频率漂了。这些差异在设备树里都要对应调整。

好了,关于板级配置就讲到这里。记住一句话:defconfig是骨架,设备树是血肉,两者配合好了,U-Boot才能跑得稳。