一、设备树基础语法:节点、属性、标签、别名
大家好,我是老李。做嵌入式Linux开发十几年了,设备树这东西,说实话刚出来那会儿我也挺头疼的。但后来发现,只要把几个核心概念搞明白,剩下的就是熟练工。今天咱们就来聊聊设备树最基础的四个要素:节点、属性、标签和别名。
1. 节点(Node)——设备树的骨架
节点是什么?说白了就是设备树里的“文件夹”。每个节点代表一个硬件设备或一个总线控制器。比如你的I2C控制器、SPI控制器、GPIO控制器,在设备树里都是一个节点。
节点用一对花括号 { } 包裹,里面可以嵌套子节点。来看个例子:
/ {
soc {
i2c1: i2c@40012000 {
compatible = "st,stm32-i2c";
reg = <0x40012000 0x400>;
status = "okay";
};
};
};
这里 / 是根节点,soc 是子节点,i2c@40012000 是孙子节点。节点名后面的 @40012000 是地址,用来区分同名的节点。我个人习惯,只要节点有地址,就一定会加上 @ 后缀,这样一眼就能看出它映射到哪个物理地址。
关键点:节点名可以重复,但完整的路径必须唯一。比如 /soc/i2c@40012000 和 /soc/i2c@40013000 是两个不同的节点。
2. 属性(Property)——节点的“身份证”
属性就是描述节点特征的数据。每个节点可以有多个属性,属性值可以是字符串、数字、数组、布尔值等。
常见的属性有:
compatible:驱动匹配的关键,格式是"厂商,型号"reg:寄存器地址和长度status:设备状态,"okay"或"disabled"interrupts:中断号clocks:时钟源
举个例子:
uart7: serial@40018000 {
compatible = "st,stm32-uart";
reg = <0x40018000 0x400>;
interrupts = <29>;
clocks = <&rcc UART7>;
status = "disabled";
};
嗯,这里要注意 status = "disabled"。我在项目中遇到过好几次,明明设备树写对了,驱动就是没加载。查了半天,发现是status默认是"disabled",忘了改成"okay"。这种坑,踩过一次就记住了。
避坑指南:我曾经在调试一个SPI设备时,compatible写成了"spi,device",结果驱动死活匹配不上。后来发现标准格式应该是"厂商,设备名",比如"microchip,mcp2515"。少一个逗号都不行。
3. 标签(Label)——节点的“外号”
标签就是给节点起个简短的名字,方便在其他地方引用。标签写在节点名前面,用冒号隔开。
i2c1: i2c@40012000 {
// 节点内容
};
这里的 i2c1 就是标签。有了标签,你就可以在别的地方用 &i2c1 来引用这个节点。比如:
&i2c1 {
status = "okay";
clock-frequency = <100000>;
};
我个人习惯,所有重要的控制器节点都会加上标签。标签名一般用设备类型加序号,比如 i2c1、spi2、uart7。这样在板级文件里引用起来特别方便。
小技巧:标签名最好用全小写,避免和C语言宏定义冲突。我见过有人用 I2C1 做标签,结果和头文件里的宏重名了,编译报错查了半天。
4. 别名(Aliases)——路径的“快捷方式”
别名和标签有点像,但用途不同。别名定义在根节点的 aliases 子节点里,用来给设备路径起个短名字。
/ {
aliases {
i2c0 = &i2c1;
serial0 = &uart7;
ethernet0 = &mac;
};
};
为什么需要别名?你想想看,U-Boot启动时,它不知道你的设备树里 uart7 是哪个节点。但如果你定义了 serial0 = &uart7,U-Boot就可以通过 serial0 这个别名找到它。
说白了,别名就是给硬件路径起个“通用名”。不管你的UART挂在哪个地址上,只要别名是 serial0,系统就能找到它。
实际应用:我在做STM32MP1项目时,板子上有两个以太网口。通过别名 ethernet0 和 ethernet1,U-Boot和Linux内核都能正确识别哪个是主网口,哪个是从网口。没有别名的话,就得靠地址去猜,容易搞混。
知识体系总览
下面这张图,是我自己总结的设备树基础语法结构。你看一遍就能明白这四个要素之间的关系:
总结一下
这四个概念,说白了就是:
- 节点:设备树的骨架,描述硬件结构
- 属性:节点的具体信息,告诉内核这个设备是什么、怎么用
- 标签:给节点起个短名,方便在其他地方引用
- 别名:给设备路径起个通用名,方便Bootloader和内核识别
我记得刚开始学设备树时,总觉得标签和别名是一回事。后来在项目中调试U-Boot启动时才发现,标签是给dts文件内部用的,别名是给外部程序(比如U-Boot)用的。用途不同,千万别搞混。
个人建议:写设备树时,先把节点结构搭好,再填属性。标签和别名可以后面再加,但节点和属性一定要一次写对。不然改起来很麻烦,尤其是那种几百行的设备树文件。
好了,这一章就到这里。设备树的基础语法其实不难,难的是理解每个字段的含义和用法。下一章咱们聊聊设备树里最常用的属性——compatible和reg,这两个是驱动匹配的关键。
可可精品资料库