1. 设备树基础概念
1.1 什么是设备树 (Device Tree)
设备树(Device Tree,DT)是一种描述硬件资源的数据结构,它使用节点(node)和属性(property)的树形层次来向操作系统(尤其是Linux内核)传递板级硬件信息。设备树源文件(.dts)经过设备树编译器(dtc)编译为二进制设备树(.dtb),由引导加载程序传递给内核。
核心定义:设备树是一个硬件描述文件,它将原本硬编码在Linux内核中的板级硬件细节(如内存地址、中断号、GPIO引脚、时钟频率等)分离出来,以结构化文本的形式提供给内核。
一个典型的设备树节点结构如下:
/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>; /* 256MB RAM */
};
leds {
compatible = "gpio-leds";
led0: led@0 {
label = "usr0";
gpios = <&gpio1 21 GPIO_ACTIVE_HIGH>;
linux,default-trigger = "heartbeat";
};
};
};
关键术语:节点(node)用
{ } 表示,属性(property)用 key = value; 表示。每个节点可以有子节点,形成树形结构。
1.2 设备树的作用
设备树在嵌入式Linux系统中承担三大核心作用:
| 作用 | 说明 | 传统方式(无设备树) | 设备树方式 |
|---|---|---|---|
| 硬件描述 | 描述CPU、内存、外设、中断、GPIO等硬件资源 | 硬编码在 arch/arm/mach-xxx 板级文件中 |
统一在 .dts 文件中描述 |
| 硬件抽象 | 同一内核镜像支持多个不同板卡 | 每个板卡需重新编译内核 | 只需更换 .dtb 文件 |
| 资源传递 | 将中断号、寄存器地址、GPIO引脚等传递给驱动 | 通过 platform_data 结构体传递 |
通过设备树节点属性自动解析 |
设备树解决了嵌入式Linux中板级代码泛滥的问题。在ARM Linux早期,每个板卡都需要在 arch/arm/mach-* 目录下添加大量C语言板级文件,导致内核维护成本极高。设备树将硬件描述与内核代码解耦,实现了一次编译,多处运行。
注意:设备树不是万能硬件抽象层。它只描述硬件存在什么以及如何连接,不描述硬件如何工作。设备驱动仍然需要在内核中实现。
1.3 设备树与平台设备 (platform device) 的关系
设备树与平台设备的关系是嵌入式驱动开发中的核心概念。简单来说:设备树是硬件描述源,平台设备是内核中的设备对象。
在引入设备树之前,平台设备通过以下方式创建:
/* 传统方式:在板级文件中静态定义 platform_device */
static struct platform_device my_device = {
.name = "my_driver",
.id = -1,
.num_resources = 2,
.resource = my_resources,
};
/* 然后在板级初始化函数中注册 */
platform_device_register(&my_device);
引入设备树后,上述过程被自动化:
/* 设备树描述 */
my_device: my-device@48000000 {
compatible = "my_driver";
reg = <0x48000000 0x1000>;
interrupts = <42>;
};
/* 内核自动完成:of_platform_populate() 扫描设备树节点
* 为每个 compatible 匹配的节点创建 platform_device */
两者的对应关系如下表所示:
| 维度 | 设备树 (Device Tree) | 平台设备 (platform device) |
|---|---|---|
| 本质 | 硬件描述数据(文本/二进制) | 内核运行时对象(struct platform_device) |
| 生命周期 | 编译时生成,启动时加载 | 内核运行时创建和销毁 |
| 创建方式 | 编写 .dts 文件 | 由内核 of_platform 框架自动创建 |
| 资源来源 | reg, interrupts, gpios 等属性 | 从设备树解析后填充 resource 结构体 |
| 匹配机制 | compatible 属性 | of_match_table 与 compatible 匹配 |
核心流程:设备树节点 →
of_platform_populate() → platform_device → platform_driver 匹配 → probe() 执行。驱动开发者只需关注设备树描述和驱动 probe 逻辑,无需手动注册设备。
调试技巧:在
/sys/devices/platform/ 目录下可以查看所有已注册的平台设备。使用 ls /sys/firmware/devicetree/base/ 可以查看内核当前使用的设备树内容,这是验证设备树是否被正确加载的快速方法。