嵌入式Linux驱动开发 设备树overlay与动态配置 - 第1节
1. 设备树基础概念
设备树(Device Tree,DT)是一种描述硬件资源的数据结构,它以树状层次结构将处理器、内存、外设、中断控制器、GPIO 控制器等硬件组件组织起来,供操作系统(尤其是 Linux 内核)在启动时解析并初始化驱动。设备树源文件(.dts)经过设备树编译器(dtc)编译为二进制设备树 Blob(.dtb),由 Bootloader 传递给内核。
核心要点:设备树不是代码,而是数据。它把“硬件是什么、连接在哪里、资源如何配置”从内核源码中剥离出来,变成一份独立于内核版本的硬件描述文件。
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 |
注意:虽然设备树和 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 驱动开发的基础。