1. 设备树基础概念

1.1 什么是设备树(Device Tree)

设备树(Device Tree,DT)是一种描述硬件资源的数据结构,它使用树形节点来记录系统中所有可访问的设备、总线、中断控制器、GPIO 控制器、时钟、复位等硬件信息。设备树的核心目标是将硬件描述从 Linux 内核源码中剥离出来,使得同一份内核镜像可以支持多种硬件平台,而无需为每块板子重新编译内核。

讲师提示: 在引入设备树之前,ARM Linux 内核充斥着大量的 board-*.c 文件,每个板子都要硬编码硬件信息。设备树让板级描述与内核驱动分离,是嵌入式 Linux 走向通用化、可维护性的关键一步。

设备树由一系列节点(node)和属性(property)组成,每个节点代表一个硬件设备或总线,属性则描述设备的配置参数,如寄存器地址、中断号、时钟频率等。设备树的根节点是 /,所有设备节点都挂载在根节点下,形成一棵完整的硬件树。

设备树结构示意图 / (根节点) soc memory chosen uart0 gpio0 i2c0 spi0 key-gpio led-gpio 节点说明 根节点:/ 一级:soc/memory/chosen 二级:uart/gpio/i2c/spi 三级:key/led 子节点 属性:reg/interrupts/compatible

1.2 DTS / DTC / DTB 的关系

设备树的开发和使用涉及三种文件形态,它们构成了从源码到二进制再到内核解析的完整链路:

缩写 全称 文件格式 作用
DTS Device Tree Source 文本文件(.dts / .dtsi) 开发者编写的设备树源码,使用人类可读的文本格式描述硬件
DTC Device Tree Compiler 编译工具 将 DTS 编译为 DTB 的编译器,也支持反编译(DTB → DTS)
DTB Device Tree Blob 二进制文件(.dtb) Bootloader 传递给内核的二进制设备树,内核直接解析使用
关键流程: 开发者在 .dts 中编写硬件描述 → 使用 dtc 工具编译为 .dtb → Bootloader(如 U-Boot)将 DTB 加载到内存 → Linux 内核在启动时解析 DTB 并创建设备模型。

DTS 文件支持 #include 机制,可以引用 .dtsi(Device Tree Source Include)头文件。SoC 厂商通常提供 soc.dtsi 描述芯片内部外设,板级开发者再通过 board.dts 引用并覆盖或添加板级特有设备。

DTS → DTC → DTB 编译流程 .dts / .dtsi 设备树源码(文本) DTC 编译器 dtc -I dts -O dtb .dtb 设备树二进制(Blob) 反编译:dtc -I dtb -O dts Bootloader 加载 DTB → Linux 内核解析 → 设备模型 U-Boot: bootm <kernel> - <dtb>

1.3 设备树在 Linux 内核中的作用

设备树在 Linux 内核中扮演着硬件描述与驱动匹配的桥梁角色,其核心作用体现在以下四个方面:

  • 硬件描述标准化: 内核通过 DTB 获取所有外设的寄存器基址、中断号、DMA 通道、时钟频率等参数,不再依赖硬编码的板级文件。
  • 驱动匹配与实例化: 设备树中的 compatible 属性是驱动匹配的关键字。内核在启动时遍历设备树节点,根据 compatible 字符串查找对应的 platform_driver,并调用 probe() 函数。
  • 中断与 GPIO 绑定: 设备树通过 interrupts、interrupt-parent、gpios 等属性,将外设的中断请求线与中断控制器、GPIO 引脚与 GPIO 控制器进行绑定,这是本课程的核心内容。
  • 运行时配置: 设备树支持 chosen 节点传递启动参数(如 bootargs),也支持通过 status 属性(okay / disabled)动态启用或禁用设备。
常见误区: 设备树不是设备驱动,它只是硬件配置的“数据文件”。驱动代码仍然需要在内核源码中实现,设备树只负责告诉驱动“硬件在哪里、怎么配置”。初学者容易混淆“设备树配置”与“驱动开发”的边界。
设备树在 Linux 内核中的角色 设备树 (DTB) 硬件描述数据 OF (Open Firmware) API 解析 of_match_node / of_property_read_* 驱动匹配 compatible → probe() 中断 / GPIO 绑定 interrupts / gpios 解析 资源分配 reg / clocks / dmas 最终效果:同一内核镜像支持不同板卡,只需更换 DTB 文件

1.4 设备树语法速览

一个典型的设备树节点包含以下要素,我们以 GPIO 按键为例展示其语法结构:

/dts-v1/;

#include "imx6ul.dtsi"

/ {
    model = "Freescale i.MX6 UltraLite Board";
    compatible = "fsl,imx6ul-14x14-evk", "fsl,imx6ul";

    chosen {
        bootargs = "console=ttymxc0,115200 root=/dev/mmcblk1p2 rw";
    };

    gpio-keys {
        compatible = "gpio-keys";
        pinctrl-names = "default";
        pinctrl-0 = &key_pins;

        key-gpio {
            label = "KEY0";
            gpios = &gpio1 18 GPIO_ACTIVE_LOW;
            linux,code = <KEY_ENTER>;
        };
    };
};

&uart1 {
    status = "okay";
    pinctrl-names = "default";
    pinctrl-0 = &uart1_pins;
};
语法要点:
  • /dts-v1/; 是 DTS 版本声明,必须放在文件开头。
  • &uart1 是引用语法,用于在文件末尾追加或覆盖 SoC .dtsi 中已定义的节点。
  • gpios = &gpio1 18 GPIO_ACTIVE_LOW 表示使用 gpio1 控制器的第 18 号引脚,低电平有效。
  • status = "okay" 启用设备,"disabled" 则禁用。

1.5 本章小结

概念 核心要点
设备树 (DT) 树形硬件描述数据结构,节点 + 属性,替代板级硬编码
DTS / DTC / DTB 源码 → 编译器 → 二进制,Bootloader 传递给内核
内核中的作用 硬件描述、驱动匹配、中断/GPIO 绑定、运行时配置
compatible 属性 驱动匹配的关键字,格式为 "厂商,设备型号"