3. 设备树语法基础:节点、属性、标签、路径的语法规则

设备树(Device Tree)是一种描述硬件资源的树形数据结构,其语法简洁、层次分明。掌握节点(node)、属性(property)、标签(label)和路径(path)的语法规则,是编写和解析设备树源文件(.dts)的基础。本章将逐一拆解这四个核心要素,并通过对比表格和可视化 SVG 图帮助理解。

核心要点:设备树的本质是一个“硬件描述语言”,它通过树状结构将板级硬件信息(CPU、内存、外设、中断、GPIO 等)传递给 Linux 内核,实现驱动与硬件的解耦。

3.1 节点(Node)—— 树形结构的骨架

节点是设备树的基本组成单元,代表一个硬件设备或总线。每个节点可以包含子节点,形成从根到叶的层次关系。

3.1.1 节点定义语法

node-name {
    property1 = <value>;
    property2 = "string";
    child-node {
        ...
    };
};
  • 节点名称:由字母、数字、连字符(-)、下划线(_)组成,必须以字母开头。
  • 节点体:用花括号 { } 包裹,内部包含属性和子节点。
  • 结束符:每个节点定义后必须加分号 ;。

3.1.2 根节点与特殊节点

节点类型 名称 说明
根节点 / 设备树的顶层节点,所有其他节点都是它的子节点。
CPU 节点 cpus 描述处理器核心,通常包含多个子节点(每个 CPU 核心一个)。
内存节点 memory 描述系统物理内存的起始地址和大小。
别名节点 aliases 为其他节点定义简短的别名,方便引用。
选择节点 chosen 传递内核启动参数(如 bootargs),不描述具体硬件。
实战提示:根节点 / 是设备树的入口,所有硬件描述都从根节点开始展开。在 .dts 文件中,根节点通常位于文件开头,且只能有一个。

3.2 属性(Property)—— 节点的数据载体

属性是节点内部用于描述硬件特性的键值对。属性值可以是整数、字符串、字节数组或它们的组合。

3.2.1 属性值类型与语法

值类型 语法示例 说明
32 位整数 reg = <0x10000000 0x1000>; 尖括号 <> 包裹,多个值用空格分隔。
64 位整数 reg = <0x00000000 0x80000000>; 用两个 32 位整数拼接表示高 32 位和低 32 位。
字符串 compatible = "arm,cortex-a9"; 双引号包裹,用于匹配驱动。
字符串列表 compatible = "ti,am335x", "ti,omap3"; 多个字符串用逗号分隔。
字节数组 local-mac-address = [00 11 22 33 44 55]; 方括号 [] 包裹,十六进制字节。
布尔值 status = "disabled"; 通过字符串表示,常用 "okay" 或 "disabled"。
混合类型 reg = <0x1000 0x100>, [00 11]; 用逗号分隔不同类型值。

3.2.2 标准属性速查

  • compatible:驱动匹配的关键,格式为 "厂商,设备型号"。
  • reg:描述设备地址空间,格式为 <地址 长度>。
  • interrupts:描述中断号、触发类型。
  • clocks:引用时钟源。
  • status:设备状态,可选 "okay"、"disabled"、"reserved"。
常见错误:属性值末尾忘记加分号 ; 是初学者最常犯的语法错误。设备树编译器(DTC)会报错并停止编译,务必检查每个属性行结尾。

3.3 标签(Label)—— 节点的引用别名

标签是附加在节点名称前面的标识符,用于在其他位置引用或覆盖该节点。标签可以显著提高设备树的可维护性。

3.3.1 标签定义语法

uart0: serial@44e09000 {
    compatible = "ti,am3352-uart";
    reg = <0x44e09000 0x2000>;
    interrupts = <72>;
};

在上例中,uart0 就是标签。通过标签,可以在其他 .dtsi 或 .dts 文件中直接引用该节点:

&uart0 {
    status = "okay";
    pinctrl-0 = <&uart0_pins>;
};

3.3.2 标签的三大用途

用途 语法 示例
节点引用 &label &uart0 { ... }; 引用并扩展 uart0 节点。
属性引用 &label 作为属性值 clocks = <&clk_uart0>; 引用时钟节点。
路径别名 aliases { ... }; aliases { serial0 = &uart0; }; 定义别名。
最佳实践:在编写 .dtsi(设备树包含文件)时,为所有关键外设节点添加标签(如 i2c0、spi1、mmc0),这样板级 .dts 文件可以通过 &label 轻松覆盖或启用这些设备,无需重复编写完整路径。

3.4 路径(Path)—— 节点的唯一地址

路径是从根节点到目标节点的完整字符串表示,类似于文件系统中的绝对路径。路径用于在设备树中唯一标识一个节点。

3.4.1 路径语法规则

  • 以根节点 / 开头。
  • 各级节点名称用斜杠 / 分隔。
  • 节点名称可以包含 @ 后的地址部分(如 serial@44e09000)。
  • 路径末尾不加斜杠。

示例路径:

/soc/serial@44e09000
/cpus/cpu@0
/aliases
/chosen

3.4.2 路径与标签的对比

特性 路径(Path) 标签(Label)
表示方式 字符串,如 /soc/i2c@48020000 标识符,如 i2c0
唯一性 全局唯一,由树结构决定 全局唯一,由开发者定义
可读性 较长,但结构清晰 简短,便于记忆和引用
使用场景 在 dts 文件中直接定义节点 跨文件引用、覆盖节点属性
是否必须 每个节点都有唯一路径 可选,但强烈建议为关键节点添加

3.5 四要素关系 SVG 图

下图展示了节点、属性、标签、路径在设备树中的组织关系:

设备树四要素关系图 设备树四要素关系图 根节点 / soc chosen aliases serial@44e09000 标签: uart0 i2c@48020000 标签: i2c0 属性(Property)示例 compatible = "ti,am3352-uart"; reg = <0x44e09000 0x2000>; interrupts = <72>; 路径(Path)示例 完整路径:/soc/serial@44e09000 引用方式:&uart0 或 /soc/serial@44e09000

3.6 综合语法示例

以下是一个完整的设备树片段,综合展示了节点、属性、标签和路径的用法:

/dts-v1/;

/ {
    model = "TI AM335x BeagleBone Black";
    compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am33xx";

    cpus {
        cpu@0 {
            compatible = "arm,cortex-a8";
            device_type = "cpu";
            reg = <0x0>;
        };
    };

    memory@80000000 {
        device_type = "memory";
        reg = <0x80000000 0x10000000>;  /* 256 MB */
    };

    chosen {
        bootargs = "console=ttyO0,115200 root=/dev/mmcblk0p2 rw";
    };

    aliases {
        serial0 = &uart0;
        i2c0 = &i2c0;
    };

    soc {
        uart0: serial@44e09000 {
            compatible = "ti,am3352-uart";
            reg = <0x44e09000 0x2000>;
            interrupts = <72>;
            status = "okay";
        };

        i2c0: i2c@48020000 {
            compatible = "ti,omap4-i2c";
            reg = <0x48020000 0x1000>;
            interrupts = <70>;
            status = "okay";
            clock-frequency = <400000>;
        };
    };
};
关键解读:
  • 根节点 / 包含 model、compatible 等全局属性。
  • 标签 uart0 和 i2c0 定义在节点名称前,便于在 aliases 或其他位置引用。
  • 路径 /soc/serial@44e09000 是 uart0 节点的完整路径。
  • 属性 reg、interrupts、status 描述了设备的硬件资源。

3.7 常见语法错误与避坑指南

错误类型 错误示例 正确写法
缺少分号 reg = <0x1000 0x100> reg = <0x1000 0x100>;
花括号不匹配 node { prop = "val"; }(缺少分号) node { prop = "val"; };
标签重复 两个节点使用相同标签 uart0 确保每个标签全局唯一
路径拼写错误 &uart0 但实际标签为 uart1 使用 &uart1 或修正标签名
属性值类型错误 reg = 0x1000;(缺少尖括号) reg = <0x1000>;
编译检查:始终使用 dtc -I dts -O dtb -o output.dtb input.dts 命令编译设备树源文件,编译器会提示所有语法错误。不要手动“目测”检查,DTC 是最可靠的语法验证工具。

3.8 本章小结

  • 节点是设备树的骨架,通过嵌套结构描述硬件层次。
  • 属性是节点的数据内容,支持整数、字符串、字节数组等多种类型。
  • 标签是节点的引用别名,用于跨文件覆盖和扩展节点。
  • 路径是节点的唯一地址,从根节点开始逐级定位。
  • 四要素协同工作,构成了设备树描述硬件的基础语法体系。