1. 设备树概述:起源、作用与基本概念
1.1 为什么需要设备树?——从“硬编码”到“描述驱动”的演进
在早期的 Linux 内核中,板级硬件信息(如内存基地址、中断号、GPIO 映射、外设寄存器地址等)被直接硬编码在 arch/arm/mach-xxx 或 arch/powerpc/platforms/xxx 的 C 语言源文件中。这种“硬编码”方式带来了三个致命问题:
- 代码膨胀:每增加一款开发板,内核就需要新增大量板级文件,导致内核源码体积急剧膨胀。
- 维护灾难:不同厂商、不同 SoC 的板级代码混杂在一起,修改一处硬件配置可能影响多个平台。
- 无法通用:同一份内核镜像无法同时支持多款硬件平台,必须为每块板子单独编译内核。
核心痛点:操作系统内核与硬件平台之间缺乏一个“标准化的硬件描述接口”。设备树(Device Tree)正是为了解决这一痛点而诞生的——它将硬件信息从内核代码中剥离出来,形成一份独立的数据结构,由 Bootloader 传递给内核。
1.2 设备树的起源与历史
| 时间 | 事件 | 影响 |
|---|---|---|
| 2005 年 | PowerPC 架构率先引入设备树(Open Firmware 衍生) | 解决了 PowerPC 平台板级代码混乱的问题 |
| 2008 年 | ARM Linux 社区开始讨论引入设备树 | ARM 平台板级文件数量已超过 3000 个,维护成本极高 |
| 2011 年 | Linux 3.0 内核正式支持 ARM 设备树 | ARM 平台开始逐步淘汰 mach-xxx 硬编码方式 |
| 2014 年 | Linux 3.16 内核要求所有新 ARM 平台必须使用设备树 | 设备树成为 ARM 生态的强制标准 |
| 至今 | RISC-V、x86(ACPI 替代场景)、MIPS 等架构也广泛采用 | 设备树已成为嵌入式 Linux 硬件描述的事实标准 |
1.3 设备树的核心作用
设备树在嵌入式系统中的角色可以概括为以下四点:
- 硬件描述标准化:使用树形结构描述 CPU、内存、总线、外设、中断控制器、GPIO 控制器等所有硬件资源。
- 内核与硬件解耦:同一份内核镜像通过加载不同的设备树文件(.dtb),即可适配不同的硬件平台。
- 驱动匹配依据:内核驱动通过设备树中的
compatible属性与硬件节点进行匹配,实现“即插即用”。 - 配置灵活化:无需重新编译内核,仅修改设备树源文件(.dts)并重新编译生成 .dtb,即可调整硬件参数(如时钟频率、引脚复用、内存分区等)。
实战理解:设备树相当于一份“硬件说明书”,内核拿到这份说明书后,就知道如何初始化内存、如何配置中断、如何挂载驱动。没有设备树,内核就像“盲人摸象”,只能靠硬编码猜测硬件布局。
1.4 设备树的基本概念与文件体系
设备树涉及三个关键文件类型:
| 文件类型 | 扩展名 | 格式 | 作用 |
|---|---|---|---|
| 设备树源文件 | .dts | 文本(类似 C 语言结构体) | 开发者编写硬件描述的源文件 |
| 设备树头文件 | .dtsi | 文本(可被 .dts 包含) | SoC 级通用定义,可被多个板级 .dts 复用 |
| 设备树二进制文件 | .dtb | 二进制(扁平化) | 由 .dts 编译生成,供 Bootloader 加载并传递给内核 |
一个典型的设备树节点结构如下:
/dts-v1/;
/ {
model = "TI AM335x BeagleBone Black";
compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; /* 512 MB RAM */
};
&uart0: serial@44e09000 {
compatible = "ti,am3352-uart", "ns16550";
reg = <0x44e09000 0x2000>;
interrupts = <72>;
status = "okay";
};
};
1.5 设备树的工作流程(SVG 架构图)
1.6 设备树 vs 传统硬编码:对比分析
| 对比维度 | 传统硬编码(mach-xxx) | 设备树(Device Tree) |
|---|---|---|
| 硬件描述位置 | 内核 C 源文件 | 独立 .dts 文本文件 |
| 平台适配方式 | 修改内核代码,重新编译 | 修改 .dts,重新编译 .dtb |
| 多板支持 | 需要多份内核镜像 | 同一份内核 + 不同 .dtb |
| 驱动匹配机制 | platform_device 静态注册 | compatible 属性动态匹配 |
| 维护成本 | 高(代码耦合严重) | 低(硬件与驱动分离) |
| 社区趋势 | 已被淘汰 | ARM/RISC-V 强制标准 |
常见误区:设备树不是“驱动代码”,它只是硬件配置的“数据描述”。驱动仍然需要编写 C 代码,但驱动通过设备树获取硬件参数,而不是在代码中写死地址和中断号。初学者容易混淆“设备树配置”与“驱动逻辑”的边界。
1.7 本章小结
- 设备树解决了嵌入式 Linux 中“硬件描述与内核代码耦合”的历史问题。
- 它起源于 PowerPC,在 ARM 生态中成熟,现已成为 RISC-V 等新架构的标准。
- 核心文件体系:.dts(源文件)→ dtc 编译 → .dtb(二进制)→ Bootloader 加载 → 内核解析。
- 驱动通过
compatible属性与设备树节点匹配,实现硬件与驱动的解耦。 - 掌握设备树是嵌入式 Linux 驱动开发的必备技能,后续章节将深入节点、属性、中断、GPIO 等实战内容。