3. U-Boot源码结构:顶层目录、board目录、arch目录、drivers目录功能解析
U-Boot的源码组织遵循清晰的模块化分层原则。理解顶层目录、board、arch和drivers四大核心目录的功能,是进行移植工作的第一步。本章将逐一解析这些目录的职责与协作关系,帮助你在庞大的代码库中快速定位关键文件。
3.1 顶层目录:构建系统的骨架
U-Boot顶层目录包含了构建系统、通用配置、文档以及核心初始化逻辑。以下是必须掌握的关键子目录与文件:
| 目录/文件 | 功能说明 | 移植关注点 |
|---|---|---|
| Makefile | 顶层构建入口,定义编译规则、链接脚本、目标架构等。 | 通常无需修改,但需确认交叉编译工具链路径。 |
| Kconfig / configs/ | Kconfig是配置系统核心;configs/目录存放各板卡的默认配置文件(如xxx_defconfig)。 |
移植时需在此创建或修改板级defconfig。 |
| include/ | 全局头文件,包括configs/(板级配置头文件)、asm-*(架构相关头文件链接)等。 |
板级配置头文件(如include/configs/myboard.h)是移植核心。 |
| common/ | 通用核心代码,如命令行解析、环境变量、启动流程(board_f.c, board_r.c)。 |
理解board_init_f和board_init_r的调用顺序。 |
| lib/ | 通用库函数,如字符串操作、CRC校验、时间函数等。 | 一般无需修改。 |
| tools/ | 主机端工具,如mkimage(制作U-Boot镜像)、fdtgrep等。 |
用于打包和验证镜像。 |
| doc/ | 文档与设备树绑定说明。 | 查阅README和device-tree-bindings/。 |
移植提示: 在顶层目录执行
make <board>_defconfig 时,系统会从 configs/ 读取默认配置,并生成 .config 文件。这是移植的第一步。
3.2 board目录:板级硬件初始化的主场
board/目录按照厂商和板卡名称组织,存放与具体硬件平台强相关的初始化代码。这是移植工作中修改最频繁的区域。
- 目录结构:
board/<vendor>/<board_name>/,例如board/ti/am335x/。 - 核心文件:
board.c:板级初始化函数,如board_init()、board_late_init()、dram_init()。Kconfig:板级配置选项。MAINTAINERS:维护者信息。Makefile:编译当前板卡源码的规则。
- 关键函数:
dram_init():必须实现,用于初始化DDR控制器并填充gd->ram_size。board_init():早期板级初始化,如配置GPIO、时钟、调试串口。board_early_init_f():在board_init_f早期调用的极简初始化。
常见错误: 移植新板卡时,如果忘记在
board/ 下创建对应的目录和 board.c,链接阶段会报 undefined reference to 'board_init' 错误。
3.3 arch目录:架构与SoC核心代码
arch/目录封装了与CPU架构和SoC内部模块相关的底层代码。它按架构(如arm、riscv、x86)和SoC厂商进一步细分。
| 子目录 | 功能说明 | 移植关注点 |
|---|---|---|
| arch/arm/cpu/ | ARM架构CPU核心代码,包括异常向量表、MMU、缓存、启动汇编(start.S)。 |
start.S 是U-Boot的第一条指令入口,负责设置CPU模式、初始化栈、重定位。 |
| arch/arm/mach-<soc>/ | SoC级代码,如 mach-sunxi/(全志)、mach-imx/(NXP i.MX)。 |
包含SoC特有的时钟、复位、DDR控制器驱动初始化。 |
| arch/arm/include/asm/ | 架构相关头文件,如 arch/arm/include/asm/arch-<soc>/ 包含SoC寄存器定义。 |
DDR控制器寄存器地址和位域定义通常在此。 |
| arch/arm/dts/ | 设备树源文件(.dts)和头文件(.dtsi)。 |
移植时必须创建或修改板级.dts文件。 |
关键路径: 对于ARM平台,DDR初始化的核心代码通常位于
arch/arm/mach-<soc>/ 或 drivers/ram/ 中。例如,全志H3的DDR初始化在 arch/arm/mach-sunxi/dram_sun8i_h3.c。
3.4 drivers目录:外设驱动的仓库
drivers/目录按照设备类型分类,包含了U-Boot支持的所有外设驱动。移植时,你需要确保所需驱动被正确启用并适配。
- 核心子目录:
drivers/serial/:串口驱动(调试信息输出关键)。drivers/mmc/:MMC/SD卡驱动(启动介质)。drivers/net/:网络接口驱动(网络启动与下载)。drivers/spi//drivers/i2c/:总线驱动。drivers/ram/:DDR控制器驱动(部分SoC的DDR初始化在此)。drivers/mtd/:NAND Flash、SPI Flash等存储驱动。
- 驱动模型(DM): 现代U-Boot使用Driver Model,驱动通过设备树匹配。移植时需在设备树中添加正确的
compatible属性。
调试技巧: 如果串口无输出,首先检查
drivers/serial/ 中对应的串口驱动是否被编译进U-Boot,以及设备树中串口节点的 status = "okay"; 是否设置。
3.5 目录协作关系与启动流程
下图展示了U-Boot启动过程中,顶层目录、board、arch和drivers之间的协作关系:
3.6 移植实战:快速定位关键文件
假设你要为一块基于 NXP i.MX6ULL 的板卡移植U-Boot,以下是定位关键文件的步骤:
- 创建板级目录:
board/mycompany/myboard/,复制参考板board/freescale/mx6ullevk/中的文件。 - 配置头文件: 创建
include/configs/myboard.h,参考include/configs/mx6ullevk.h,修改DDR参数、环境变量等。 - 设备树: 创建
arch/arm/dts/myboard.dts,包含imx6ull.dtsi,并添加板级外设节点。 - 默认配置: 创建
configs/myboard_defconfig,指定目标架构、板卡、设备树文件。 - DDR初始化: 在
board/mycompany/myboard/中实现dram_init(),或确认drivers/ram/中是否有对应驱动。
核心原则: 移植的本质是“复制-修改-验证”。先找到一个与目标板最接近的参考板,然后逐步替换
board/、include/configs/ 和 arch/arm/dts/ 中的关键文件。