2. 设备树语法
好,咱们今天来啃设备树语法这块硬骨头。说实话,很多工程师一看到设备树就头大,觉得它像个黑盒子。其实没那么玄乎,它就是个描述硬件信息的文本文件。我刚开始接触时也犯过迷糊,后来发现只要把几个核心概念搞明白,剩下的就是熟练工了。
2.1 节点——设备树的基本单元
节点是设备树里最基本的组成单位。你可以把它想象成一个硬件设备的“身份证”。每个节点都描述了一个具体的硬件设备或总线。
节点长什么样?看个例子:
/ {
cpu {
compatible = "arm,cortex-a7";
reg = <0x00>;
};
memory {
device_type = "memory";
reg = <0x80000000 0x40000000>;
};
};
看到没?每个节点都用花括号 {} 包起来,里面可以嵌套子节点。根节点是 /,所有设备都挂在它下面。
我的经验:节点命名最好用全小写,单词之间用短横线连接。比如 i2c-controller 而不是 I2C_Controller。这是内核社区的约定,咱们跟着走准没错。
2.2 属性——描述节点的“形容词”
属性就是节点的特征描述。常用的属性就那么几种:
| 属性名 | 作用 | 示例 |
|---|---|---|
compatible |
指定驱动匹配名称 | "ti,am335x-uart" |
reg |
描述地址和大小 | <0x44e09000 0x2000> |
interrupts |
指定中断号 | <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH> |
status |
设备状态 | "okay" 或 "disabled" |
属性值可以是字符串、32位整数、64位整数、字节数组等。我最常用的是 compatible 属性,它决定了内核能不能找到对应的驱动。
避坑指南:我曾经在一个项目里把 compatible 写成了 "my-uart",结果驱动死活加载不上。后来才发现,规范写法应该是 "厂商,设备名" 格式,比如 "ti,am335x-uart"。少了厂商前缀,内核匹配机制就认不出来了。
2.3 标签——给节点起个“外号”
标签就是节点的别名。为什么要用标签?因为节点路径太长了,比如 /soc/serial@44e09000,每次引用都得写全路径,多麻烦。
标签的用法很简单:
uart0: serial@44e09000 {
compatible = "ti,am335x-uart";
reg = <0x44e09000 0x2000>;
};
// 在其他地方引用
&uart0 {
status = "okay";
};
看到 uart0: 了吗?这就是标签。后面用 &uart0 就能直接引用这个节点。我个人习惯给每个重要外设都加个标签,方便后续修改。
2.4 包含文件——代码复用的利器
设备树支持 #include 指令,跟C语言的头文件类似。这样可以把通用的定义抽出来,避免重复劳动。
#include "soc-common.dtsi"
#include "board-specific.dtsi"
/ {
model = "My Custom Board";
compatible = "my,board-v1";
};
.dtsi 文件是设备树包含文件,通常放一些芯片级或板级通用的定义。比如某个SoC的UART、I2C控制器定义,都可以放在 .dtsi 里。
我的建议:把芯片相关的定义放在 .dtsi 里,板级特有的配置放在 .dts 里。这样换板子时只需要改 .dts 文件,省事多了。
2.5 宏定义——让设备树更灵活
设备树里也能用宏定义!不过它用的是C预处理器,所以你得在 .dts 文件开头加上 #define。
#define UART_BASE 0x44e09000
#define UART_SIZE 0x2000
uart0: serial@44e09000 {
reg = <UART_BASE UART_SIZE>;
};
宏定义的好处是:如果地址变了,只需要改一个地方。我在做多板兼容时特别喜欢用这招。
内核还提供了一些预定义的宏,比如中断类型:
#include <dt-bindings/interrupt-controller/irq.h>
interrupts = <GIC_SPI 32 IRQ_TYPE_LEVEL_HIGH>;
这样写比直接写数字可读性强多了。你想想看,IRQ_TYPE_LEVEL_HIGH 一眼就知道是高电平触发,要是写个 4,鬼知道什么意思。
2.6 知识体系总览
说了这么多,咱们用一张图把设备树语法的核心逻辑串起来:
这张图把设备树语法的核心要素都串起来了。从根节点出发,下面挂子节点,子节点里填属性。标签、包含文件、宏定义这些辅助工具,让整个结构更灵活、更易维护。
核心要点:设备树语法其实就三件事——节点描述硬件、属性描述特征、辅助工具提升复用性。把这三点吃透了,写设备树就跟写配置文件一样简单。
嗯,语法部分就讲这么多。记住,多写多练,遇到问题别怕。我刚开始写设备树时也经常编译不过,后来慢慢就摸出门道了。你要是卡住了,回头看看这张图,思路就清晰了。