嵌入式 Linux 设备树 (DTS) 全面解析

Evek Golden Lv4

在 ARM Linux 3.x 内核之前,描述硬件信息(如 I2C 总线上挂了什么设备,GPIO 是哪根)通常是在 C 代码文件(arch/arm/mach-xxx/board-xxx.c)中写死的。这导致 Linus Torvalds 大发雷霆:“This is the whole ARM thing. It’s a f*cking pain in the ass.”

于是,设备树(Device Tree)被引入,用于将硬件描述从内核源码中剥离出来。

1. 什么是设备树?

设备树源文件 (.dts) 是一个 ASCII 文本文件,编译后生成二进制文件 (.dtb),由 Bootloader 传递给内核。

它就像一个家族族谱,是一个树状结构:

  • Root Node (/)
    • CPU Node
    • Memory Node
    • System Bus (SOC)
      • I2C Controller
        • Sensor Device
        • EEPROM
      • GPIO Controller

2. 核心语法解析

2.1 节点 (Node)

1
2
3
4
5
label: node-name@unit-address {
property-name = "string";
property-int = <123>;
property-list = <0x1000 0x2000>;
};
  • label:方便在其他地方引用(phandle)。
  • unit-address:通常是寄存器基地址。

2.2 关键属性

compatible

这是最重要的属性,决定了 Linux 内核加载哪个驱动程序。

1
2
compatible = "manufacturer,model";
// 例如:compatible = "invensense,mpu6050";

内核中的驱动程序会声明它支持哪些 compatible 字符串。如果有匹配的,probe 函数就会被调用。

reg (Register)

描述设备的地址资源。

1
reg = <0x40005000 0x400>; // 基地址 0x40005000,长度 0x400

interrupts

描述中断资源。

1
2
interrupt-parent = <&gpio1>;
interrupts = <10 IRQ_TYPE_EDGE_FALLING>; // 连接到 GPIO1_10,下降沿触发

3. 常见操作

3.1 覆盖 (Overlay)

在板级文件 (.dts) 中引用 SOC 文件 (.dtsi) 中的节点并修改。

1
2
3
4
5
6
7
8
9
10
11
// 在 soc.dtsi 中定义了 &i2c1
&i2c1 {
status = "okay"; // 启用 I2C1
clock-frequency = <400000>; // 修改频率为 400kHz

// 添加子节点
mpu6050: mpu6050@68 {
compatible = "invensense,mpu6050";
reg = <0x68>;
};
};

3.2 调试技巧

Linux 启动后,可以在 /proc/device-tree/sys/firmware/devicetree/base 下看到解析后的设备树结构。

  • 查看是否有节点ls /proc/device-tree/soc/i2c@.../
  • 反编译当前 DTBdtc -I fs -O dts /proc/device-tree > current.dts,这能让你看到实际上生效的完整设备树。

总结

设备树的初衷是解耦。掌握 DTS,你就能像搭积木一样配置硬件,而不需要去修改内核源码。

  • Title: 嵌入式 Linux 设备树 (DTS) 全面解析
  • Author: Evek Golden
  • Created at : 2025-12-03 22:30:00
  • Updated at : 2026-06-12 08:57:02
  • Link: https://blog.cocodemo.uno/posts/dts6y2z/
  • License: This work is licensed under CC BY-NC-SA 4.0.
Comments