2. 设备树基础语法(一):节点与属性的概念,根节点、子节点、标签的写法
好,咱们正式开始啃设备树的语法了。
说实话,我第一次接触设备树的时候,看着那一堆花括号和分号,心里直犯嘀咕——这不就是个配置文件吗?后来被硬件折腾了几回,才明白这东西远不止配置文件那么简单。它其实是操作系统和硬件之间的「翻译官」。
2.1 节点(Node)是什么?
节点,说白了就是设备树里的「文件夹」。每个节点代表一个硬件设备、一个总线、或者一个功能模块。
我习惯把节点想象成硬件电路板上的一个芯片。芯片有引脚,节点有属性。芯片有名字,节点也有名字。嗯,这个类比很直观。
节点的基本语法长这样:
node-name {
property1 = <value>;
property2 = "string";
child-node {
...
};
};
注意看:节点名后面跟花括号,花括号里放属性和子节点。最后用分号结尾。这个分号特别容易漏,我当年就因为这个,调试了整整一个下午。
2.2 属性(Property)是什么?
属性就是节点的「参数」。它告诉内核:这个设备用哪个中断号、内存地址是多少、时钟频率多快。
属性有三种常见写法:
| 属性类型 | 示例 | 说明 |
|---|---|---|
| 整型(32位) | reg = <0x10000000 0x1000>; |
尖括号包起来,多个值用空格隔开 |
| 字符串 | compatible = "ti,am335x-gpio"; |
双引号包起来,逗号分隔厂商和设备名 |
| 布尔值 | status = "disabled"; |
用字符串表示,常见的有 "okay" 和 "disabled" |
我在项目中遇到过最常用的属性就是 compatible。内核就是靠这个字符串找到对应的驱动。你想想看,如果这个字符串写错了,驱动就加载不上,设备就罢工了。
2.3 根节点(Root Node)
每个设备树文件有且只有一个根节点。它用斜杠 / 表示,是整个设备树的起点。
/ {
model = "TI AM335x BeagleBone Black";
compatible = "ti,am335x-bone-black", "ti,am335x-bone", "ti,am335x";
memory@80000000 {
device_type = "memory";
reg = <0x80000000 0x10000000>; // 256MB RAM
};
cpus {
cpu@0 {
compatible = "arm,cortex-a8";
};
};
};
根节点里一般放什么呢?板子型号、内存信息、CPU信息、还有各种总线。说白了,整个板子的「骨架」都在根节点里。
2.4 子节点(Child Node)
子节点就是节点里面再套节点。这跟文件系统的目录结构一模一样。
/ {
soc {
uart0: serial@44e09000 {
compatible = "ti,am3352-uart", "ti,omap3-uart";
reg = <0x44e09000 0x2000>;
interrupts = <72>;
};
i2c0: i2c@44e0b000 {
compatible = "ti,omap4-i2c";
reg = <0x44e0b000 0x1000>;
#address-cells = <1>;
#size-cells = <0>;
eeprom@50 {
compatible = "atmel,24c32";
reg = <0x50>;
};
};
};
};
你看,soc 是根节点的子节点,uart0 和 i2c0 是 soc 的子节点,eeprom 又是 i2c0 的子节点。这种层级关系,直接反映了硬件上的连接关系。
2.5 标签(Label)的写法
标签是个好东西。它相当于给节点起了一个「别名」,方便在其他地方引用。
标签的写法很简单:在节点名前加一个名字,后面跟冒号。
uart0: serial@44e09000 {
// 节点内容
};
这里的 uart0 就是标签。有了标签,我可以在其他地方这样引用:
&uart0 {
status = "okay";
pinctrl-0 = <&uart0_pins>;
};
注意那个 & 符号,它表示「引用标签为 uart0 的节点」。这种写法在设备树中特别常见,尤其是当你需要修改某个节点的时候,不用把整个节点重新写一遍。
2.6 知识体系结构图
下面这张图,是我自己画的知识结构。你看一眼,就能把今天讲的内容串起来。
2.7 避坑指南
最后,分享几个我实际项目中遇到的坑:
- 节点名不要用特殊字符:只能用字母、数字、连字符和下划线。我见过有人用点号,编译直接报错。
- 标签不能重复:整个设备树里,标签必须是唯一的。重复了,编译会报「duplicate label」错误。
- 根节点没有标签:根节点不能用标签引用。想修改根节点?直接在根节点花括号里改。
- 属性值类型要匹配:整型用尖括号,字符串用双引号。混用了,内核解析会出问题。
嗯,今天就讲这么多。节点和属性是设备树的基石,搞懂了这两个概念,后面的内容就水到渠成了。