设备树语法基础:节点、属性、标签的规则与写法

说实话,刚接触设备树那会儿,我也觉得这东西有点玄乎。不就是描述硬件嘛,怎么搞出这么多弯弯绕绕?后来做项目踩了几次坑,才明白——设备树的语法设计,其实非常精妙。今天我就把节点、属性、标签这三个核心概念,掰开了讲给你听。

一、节点(Node)——设备树的骨架

节点是什么?说白了就是硬件设备在软件世界里的“化身”。一个节点对应一个硬件设备,或者一个总线,甚至一个功能模块。

节点的写法很简单:

/dts-v1/;

/ {
    cpu {
        compatible = "arm,cortex-a7";
        reg = <0x00>;
    };

    memory {
        device_type = "memory";
        reg = <0x80000000 0x10000000>;
    };
};

看到没?每个节点都用花括号 {} 包起来,最后用分号结束。根节点是 /,所有设备都挂在它下面。我刚开始写的时候,经常忘记加分号,编译报错半天找不到原因——嗯,这种低级错误,谁还没犯过呢?

我的习惯:每个节点写完,先检查花括号和分号是否配对。养成这个习惯,能省下不少调试时间。

二、属性(Property)——描述节点的“身份证”

属性就是节点的特征描述。比如这个设备是什么型号、用哪个中断、内存地址在哪。属性分两种:一种是标准属性,内核已经定义好了;另一种是自定义属性,你自己随便起名。

常见的标准属性有:

属性名 含义 示例
compatible 设备兼容性标识 "vendor,device"
reg 寄存器地址/长度 <0x40000000 0x1000>
interrupts 中断号 <0 31 4>
status 设备状态 "okay" 或 "disabled"

属性的值可以是字符串、32位整数、64位整数、字节数组,甚至二进制数据。举个例子:

uart1: serial@40004000 {
    compatible = "st,stm32-uart";
    reg = <0x40004000 0x400>;
    interrupts = <0 37 0>;
    status = "okay";
    clock-frequency = <64000000>;
    dmas = <&dma1 5>;
};

这里 compatible 是字符串,reg 是32位整数对,interrupts 是三个整数,status 是字符串,clock-frequency 是单个整数,dmas 是引用加整数。你看,属性值的类型很灵活。

我曾经踩过的坑:有一次我写 reg = <0x40004000 0x400>,结果地址写成了 0x4000400(少了一个0)。内核启动时直接挂掉,查了两天才发现是地址写错了。所以,地址值一定要反复核对数据手册。

三、标签(Label)——给节点起个“外号”

标签就是节点的别名。为什么要用标签?你想想看,如果节点路径很长,比如 /soc/spi@40013000,每次引用都要写全路径,多麻烦。标签就是用来解决这个问题的。

标签的写法:在节点名前加一个标识符,后面跟冒号。

spi2: spi@40003800 {
    compatible = "st,stm32-spi";
    reg = <0x40003800 0x400>;
    status = "disabled";
};

这样,在其他地方就可以用 &spi2 来引用这个节点了。比如在pinctrl里:

&spi2 {
    status = "okay";
    pinctrl-0 = <&spi2_pins>;
};

我个人习惯,每个重要节点都加上标签。哪怕暂时用不到,也先加上。为什么?因为后期调试时,你很可能需要引用它。到时候再翻设备树找路径,那才叫痛苦。

四、节点、属性、标签的关系

这三者的关系,我用一张图来说明:

根节点 / 标签: uart1 → serial@40004000 属性 (Properties) compatible = "st,stm32-uart" reg = <0x40004000 0x400> interrupts = <0 37 0> status = "okay" clock-frequency = <64000000> 标签 节点是骨架,属性是血肉,标签是快捷方式

这张图很直观:根节点下面挂子节点,子节点里面塞属性。标签就像给节点贴了个“名牌”,方便别人找到它。

五、实战中的注意事项

写设备树的时候,有几个细节我特别想提醒你:

  1. 节点名要规范:一般用 设备名@地址 的格式,比如 serial@40004000。不要随便起名,否则内核匹配驱动时会失败。
  2. 属性值类型要匹配:字符串用双引号,整数用尖括号,字节数组用方括号。混用会导致编译错误。
  3. 标签不能重复:整个设备树里,标签必须是唯一的。重复了,编译会报错。
  4. 别忘了分号:每个属性后面都要加分号,每个节点结束也要加分号。这是初学者最容易犯的错误。

核心要点:

  • 节点 = 硬件设备的软件抽象
  • 属性 = 描述设备特征的键值对
  • 标签 = 节点的别名,方便引用
  • 三者配合,构成了设备树的基本单元

好了,设备树的语法基础就讲到这里。说白了,节点、属性、标签就是设备树的“三要素”。你只要把这三样搞明白,后面学中断映射、时钟配置、GPIO控制,都会轻松很多。我在实际项目中,经常看到有人把属性写错类型,或者标签引用错了节点——这些坑,你提前知道,就能绕过去了。

可可精品资料库