Linux 设备树DTS语法精讲:从节点到属性的实战解析

张开发
2026/4/19 0:16:06 15 分钟阅读

分享文章

Linux 设备树DTS语法精讲:从节点到属性的实战解析
1. 设备树DTS基础入门第一次接触设备树DTS文件时我完全被那些奇怪的符号和嵌套结构搞懵了。后来才发现设备树其实就是用文本文件描述硬件配置的一种方式就像给硬件画一张地图。这张地图告诉Linux内核你的CPU在哪里、内存有多大、外设怎么连接。DTS文件最终会被编译成DTB二进制文件由bootloader传递给内核。我常用的工作流程是这样的编写或修改.dts文件用dtc编译器生成.dtb文件通过bootloader加载到内核最基础的DTS文件结构是这样的/dts-v1/; / { compatible my-company,my-board; #address-cells 1; #size-cells 1; memory0 { device_type memory; reg 0x00000000 0x40000000; }; };这个简单例子包含了几个关键要素/表示根节点所有设备都是它的子节点compatible属性标识板卡类型memory节点描述物理内存布局#address-cells和#size-cells定义地址和长度的表示方法2. 节点与属性详解2.1 节点命名规则节点命名看似简单但实际项目中我见过不少因为命名不规范导致的问题。标准格式是node-nameunit-address比如一个串口设备可能被命名为uartfe001000。这里有几个要点node-name只能包含字母数字和特定符号,._-必须以字母开头数字开头会编译失败后面的地址通常对应硬件的物理地址我常用的命名习惯是使用英文全称而非缩写如用ethernet而非eth相同类型设备用数字区分i2c0,i2c1地址使用小写十六进制表示2.2 属性类型与用法属性是节点的特征描述常见格式有两种property-name value; // 有值的属性 property-name; // 布尔属性存在即表示true属性值支持多种数据类型字符串compatible fsl,mpc8641;32位整数clock-frequency 825000000;64位整数reg 0x11223344 0x55667788;字节序列local-mac-address [00 11 22 33 44 55];实际项目中我建议优先使用标准属性如reg、interrupts等自定义属性容易导致兼容性问题。如果必须自定义建议加上厂商前缀比如my-company,reset-gpio。3. 特殊节点实战解析3.1 必须存在的核心节点有些节点是设备树必须包含的缺少它们会导致系统无法正常启动/memory节点描述物理内存布局memory0 { device_type memory; reg 0x00000000 0x80000000; // 起始地址0大小2GB };/chosen节点传递启动参数chosen { bootargs consolettyS0,115200 root/dev/mmcblk0p2 rw; };/cpus节点描述CPU信息cpus { #address-cells 1; #size-cells 0; cpu0 { device_type cpu; reg 0; }; };3.2 实用工具节点/aliases节点可以给设备创建短名称方便引用aliases { serial0 uart0; ethernet0 fec; };这样在命令行中就可以用serial0代替完整的设备路径了。4. 关键属性深度剖析4.1 地址与空间描述描述硬件地址空间是设备树的核心功能之一主要涉及三个属性#address-cells定义地址用几个cell表示#size-cells定义大小用几个cell表示reg具体地址范围一个典型的内存映射示例soc { #address-cells 1; #size-cells 1; serialfe001000 { compatible ns16550; reg 0xfe001000 0x100; // 地址0xfe001000大小0x100 }; };4.2 中断处理机制中断配置是设备树中最复杂的部分之一涉及多个属性// 中断控制器定义 intc: interrupt-controllerfee00000 { #interrupt-cells 2; interrupt-controller; }; // 设备节点中的中断配置 ethernetf0000000 { interrupts 23 IRQ_TYPE_LEVEL_HIGH; interrupt-parent intc; };这里有几个关键点interrupt-controller声明这是一个中断控制器#interrupt-cells定义中断描述格式interrupt-parent指定中断控制器interrupts定义具体中断号和触发方式5. 实际案例解析5.1 完整DTS示例下面是一个简化但功能完整的DTS示例综合了前面讲到的各种元素/dts-v1/; / { compatible my-company,my-board; #address-cells 1; #size-cells 1; memory0 { device_type memory; reg 0x00000000 0x40000000; }; cpus { #address-cells 1; #size-cells 0; cpu0 { device_type cpu; reg 0; }; }; soc { #address-cells 1; #size-cells 1; ranges; serialfe001000 { compatible ns16550; reg 0xfe001000 0x100; interrupts 10 IRQ_TYPE_LEVEL_HIGH; }; ethernetf0000000 { compatible snps,dwmac; reg 0xf0000000 0x2000; interrupts 23 IRQ_TYPE_LEVEL_HIGH; phy-mode rgmii; }; }; chosen { bootargs consolettyS0,115200 root/dev/nfs rw; }; };5.2 常见错误排查根据我的调试经验90%的DTS问题都集中在以下几个方面地址单元不匹配// 错误示例 soc { #address-cells 2; #size-cells 1; serialfe001000 { // 这里地址只用了1个cell与定义不符 reg 0xfe001000 0x100; }; };中断配置错误// 错误示例 interrupt-controllerfee00000 { #interrupt-cells 3; // 定义为3个cell }; devicef0000000 { interrupts 23 IRQ_TYPE_LEVEL_HIGH; // 但这里只用了2个cell interrupt-parent intc; };兼容性字符串拼写错误// 错误示例 serialfe001000 { compatible ns16550a; // 正确的应该是ns16550 };调试DTS问题时我通常会先用dtc -I dtb -O dts反编译DTB文件检查编译后的实际内容是否符合预期。

更多文章