1. 设备树基础概念

1.1 设备树的起源与历史背景

设备树(Device Tree,DT)是一种描述硬件资源的数据结构,最早源于 Open Firmware(IEEE 1275)规范。在嵌入式 Linux 早期(2.4 ~ 2.6 内核时代),ARM、PowerPC、MIPS 等架构的板级硬件描述大量依赖 board-*.c 和 mach-*.c 文件,每个开发板都需要在内核源码中硬编码物理地址、中断号、时钟频率等信息。这种模式导致内核源码树中充斥着大量重复、难以维护的板级代码。

痛点总结: 2005 年前后,仅 ARM 架构就有超过 300 个板级文件,每增加一个新板卡就需要修改内核源码并重新编译,严重阻碍了 SoC 厂商和 OEM 的迭代速度。

2011 年,Linux 内核主线正式引入 Flattened Device Tree(FDT),将硬件描述从内核源码中剥离,形成独立的 .dts / .dtsi 文件。这一变革使得同一份内核镜像可以支持多个硬件平台,只需更换设备树二进制(.dtb)即可适配不同板卡。

1.2 设备树的核心作用

设备树在嵌入式 Linux 启动流程中扮演 硬件拓扑描述者 和 资源清单提供者 的双重角色。其核心作用可归纳为以下四点:

作用维度 具体说明 典型示例
硬件枚举 描述 CPU、内存、外设控制器、总线拓扑等所有可编程硬件节点 cpus { cpu@0 { ... } }
资源分配 定义寄存器地址范围、中断号、DMA 通道、时钟频率等资源 reg = <0x1c00000 0x1000>
驱动绑定 通过 compatible 属性将设备节点与内核驱动匹配 compatible = "ti,am335x-uart"
配置解耦 将引脚复用、时钟频率、电压等级等板级参数从内核源码中分离 pinctrl-0 = &uart0_pins
关键认知: 设备树不是驱动,而是驱动的“配置文件”。驱动通过设备树获取硬件实例化参数,实现“一套驱动,多板适配”。

1.3 设备树与 ACPI 的对比

ACPI(Advanced Configuration and Power Interface)是 x86 和 ARM64 服务器领域的主流硬件描述标准,与设备树在理念和实现上有显著差异:

对比维度 设备树(DT) ACPI
起源 Open Firmware / 嵌入式社区 PC / 服务器工业标准
数据格式 文本(.dts)→ 二进制(.dtb) ASL 源码 → AML 字节码
运行时解析 Bootloader 加载 .dtb 到内存,内核直接解析 BIOS/UEFI 提供 ACPI 表,内核通过 AML 解释器解析
动态性 静态描述,运行时可通过 overlay 扩展 支持热插拔、电源状态动态协商
适用场景 嵌入式、IoT、消费电子、ARM SoC x86 服务器、桌面、ARM64 服务器
驱动匹配方式 compatible 字符串匹配 HID/CID + 设备 ID 匹配
社区生态 Linux 内核主线 + 设备树规范 UEFI 论坛 + 微软/Intel 主导
选型建议: 对于资源受限的嵌入式系统(如 Cortex-M 系列、低端 Cortex-A),设备树更轻量、更直接;对于需要 ACPI 电源管理和热插拔的服务器级 ARM64 平台,ACPI 是更合适的选择。两者在 ARM64 领域存在重叠,但内核社区明确推荐设备树为嵌入式首选。

1.4 设备树在嵌入式 Linux 中的核心地位

在当前的嵌入式 Linux 生态中,设备树已经从一个可选组件演变为 事实上的硬件描述标准。其核心地位体现在以下三个层面:

  1. 启动流程的必经环节: 从 Bootloader(U-Boot、TF-A)到内核启动,设备树是传递硬件信息的唯一通道。没有有效的 .dtb,内核无法完成内存映射、中断控制器初始化、时钟树建立等基础操作。
  2. 驱动开发的契约接口: 设备树节点中的 compatible、reg、interrupts、clocks 等属性构成了驱动与硬件之间的“契约”。驱动开发者只需按照设备树绑定文档编写驱动,即可适配任意符合该描述的硬件。
  3. 产品迭代的配置中心: 同一 SoC 的不同产品变体(如不同内存容量、不同外设组合)只需修改 .dts 文件,无需改动内核源码。设备树 overlay 机制还支持运行时动态加载,满足模块化产品的需求。
设备树在嵌入式 Linux 启动流程中的核心地位 Bootloader U-Boot / TF-A 设备树 .dtb 硬件拓扑 + 资源清单 Linux 内核 OF API 解析 设备驱动 probe() 回调 设备树的核心价值 ① 硬件描述与内核源码解耦:修改硬件只需更换 .dtb,无需重新编译内核 ② 驱动复用:同一驱动通过 compatible 匹配不同设备节点,适配多款硬件 ③ 社区标准化:设备树绑定文档(Documentation/devicetree/bindings/)成为硬件厂商的接口规范 ④ 启动效率:扁平化二进制格式(.dtb)解析速度快,适合资源受限的嵌入式环境

1.5 设备树文件体系与编译流程

设备树源文件采用 文本 → 二进制 的编译模型,整个文件体系包含以下类型:

文件后缀 全称 作用 示例
.dts Device Tree Source 顶层设备树源文件,描述具体板卡的硬件 imx6ull-evk.dts
.dtsi Device Tree Source Include 公共头文件,描述 SoC 通用部分或模块复用部分 imx6ull.dtsi
.dtb Device Tree Blob 编译后的二进制文件,供 Bootloader 加载 imx6ull-evk.dtb
.dtbo Device Tree Blob Overlay 设备树覆盖层,用于运行时动态添加/修改节点 mcp2515-can0.dtbo

编译命令示例:

# 将 .dts 编译为 .dtb
dtc -I dts -O dtb -o imx6ull-evk.dtb imx6ull-evk.dts

# 反编译 .dtb 为可读的 .dts
dtc -I dtb -O dts -o imx6ull-evk-decompiled.dts imx6ull-evk.dtb

# 编译设备树覆盖层
dtc -I dts -O dtb -@ -o mcp2515-can0.dtbo mcp2515-can0.dts
工程实践: 在 Linux 内核源码树中,设备树文件统一存放在 arch/<arch>/boot/dts/ 目录下。编译内核时,make dtbs 命令会递归编译所有 .dts 文件,生成对应的 .dtb。建议在开发阶段使用 dtc -I dtb -O dts 反编译验证生成的 .dtb 是否符合预期。

1.6 本章小结

设备树是嵌入式 Linux 从“硬编码时代”迈向“配置驱动时代”的关键技术。它通过标准化的树形数据结构,将硬件描述与内核源码解耦,使得驱动开发、板级适配、产品迭代的效率得到数量级提升。理解设备树的起源、作用、与 ACPI 的差异以及其在启动流程中的核心地位,是掌握后续设备树语法、绑定编写、驱动集成技巧的基石。