嵌入式Linux驱动开发:设备树overlay与动态配置 - 第1节

1.1 什么是设备树(Device Tree)

设备树(Device Tree,DT)是一种描述硬件资源的数据结构,它以树状层次结构将处理器、内存、外设、中断控制器、GPIO 控制器等硬件组件组织起来,供操作系统(尤其是 Linux 内核)在启动时解析并初始化驱动。设备树源文件(.dts)经过设备树编译器(dtc)编译为二进制设备树 Blob(.dtb),由 Bootloader 传递给内核。

核心要点:设备树不是代码,而是数据。它把“硬件是什么、连接在哪里、资源如何配置”从内核源码中剥离出来,变成一份独立于内核版本的硬件描述文件。
设备树层次结构示例 / (根节点) cpus memory chosen cpu@0 cpu@1 soc serial@... i2c@... spi@... 根节点 顶层节点 设备节点

1.2 为什么需要设备树

在设备树出现之前(Linux 2.6 ~ 3.x 早期),ARM 架构的板级硬件描述采用 Board File 方式:每个开发板对应一个 arch/arm/mach-xxx/board-xxx.c 文件,里面硬编码了所有外设的地址、中断号、时钟等资源。这种模式带来了严重问题:

  • 代码膨胀: 每增加一块新板卡,就要新增或修改一个 C 文件,内核源码中充斥着大量重复的硬件描述。
  • 耦合度高: 硬件变更(如换一个 UART 或调整 GPIO 分配)需要重新编译内核,无法做到内核与板级配置分离。
  • 维护困难: 不同厂商、不同 SoC 的板级文件风格各异,社区难以统一维护。

设备树解决了上述痛点,带来了以下关键价值:

维度 Board File 时代 设备树时代
硬件描述位置 内核源码 .c 文件 独立 .dts 源文件
内核编译 每改一次硬件需重新编译内核 只需重新编译 DTB,内核不变
多板支持 每个板子一个 board-*.c 同一内核镜像 + 不同 DTB 即可
驱动与硬件解耦 驱动中混杂板级信息 驱动通过 compatible 匹配设备节点
社区维护成本 高(大量重复代码) 低(设备树文件可复用、可继承)
一句话总结:设备树让“硬件描述”与“内核代码”解耦,实现了“一套内核镜像,适配多种硬件平台”的目标,是嵌入式 Linux 从 ARM 时代走向通用化、可维护性的关键架构改进。

1.3 设备树与 ACPI 的区别

ACPI(Advanced Configuration and Power Interface)是 x86/x86_64 平台上主流的硬件描述与电源管理标准,与设备树在理念和实现上有显著差异。下表从多个维度进行对比:

对比维度 设备树(Device Tree) ACPI
主要应用平台 ARM、RISC-V、PowerPC 等嵌入式/非 x86 架构 x86/x86_64(PC、服务器)
描述形式 纯文本 .dts → 二进制 .dtb,树状结构 AML(ACPI Machine Language)字节码,表格式结构
运行时解析 内核在启动时一次性解析 DTB,构建 device_node 树 内核通过 ACPI 解释器执行 AML,支持动态命名空间
电源管理 弱(设备树本身不定义电源管理方法,依赖驱动实现) 强(内置 D-state、C-state、热插拔、电池管理等)
动态配置 支持 Overlay(运行时加载/卸载设备节点) 支持 DSDT 替换、热插拔 ACPI 事件
硬件枚举 Bootloader 传递 DTB 地址,内核直接解析 BIOS/UEFI 在启动时构建 ACPI 表,内核读取
复杂度 相对简单,学习曲线平缓 非常复杂,规范文档数千页
开源工具链 dtc(设备树编译器)、libfdt、dt-utils iasl(ACPI 编译器)、acpidump、acpixtract
设备树 vs ACPI:启动流程对比 设备树启动流程 Bootloader 加载 DTB 到内存 内核解析 DTB → device_node 树 驱动匹配 compatible → 初始化 ACPI 启动流程 UEFI/BIOS 构建 ACPI 表(RSDP) 内核 ACPI 解释器执行 AML 驱动通过 ACPI ID 匹配 → 初始化 ARM/嵌入式 x86/服务器 设备树:静态描述 + 内核解析 | ACPI:动态字节码 + 解释器执行
注意:虽然设备树和 ACPI 都用于硬件描述,但两者不可互换。在 ARM 服务器领域(如 ARM64),部分平台开始支持 ACPI 以兼容企业级操作系统,但嵌入式场景仍以设备树为主。本课程后续内容全部基于设备树展开。

1.3.1 何时选择设备树?何时选择 ACPI?

  • 选择设备树:嵌入式 Linux 产品(路由器、机顶盒、工控板、IoT 设备)、ARM/RISC-V 开发板、FPGA SoC、需要 Overlay 动态配置的场景。
  • 选择 ACPI:x86 PC/服务器、需要高级电源管理(Suspend-to-RAM、CPU 调频)、需要热插拔 PCIe/USB 设备、需要与 Windows 双启动的硬件。
  • 混合场景:部分 ARM64 服务器同时提供设备树和 ACPI 支持,由 firmware 根据 OS 需求选择传递哪种表。
学习建议:如果你是嵌入式 Linux 驱动开发者,设备树是必修课。理解设备树的节点、属性、绑定规则和 Overlay 机制,是掌握现代 ARM Linux 驱动开发的基础。