一、设备树文件的组成
- 主要由节点(Node)和属性(Property)组成
- 括号
{}表示节点的内容区块/子树 - 每个节点可以有子节点和多个属性
二、基本语法
1、节点
格式:
c
节点名: 节点标签@单位地址 {
...属性/子节点...
};1
2
3
2
3
- 节点名(可选标签)@物理地址
{...}- “@地址” 部分有时可省略,常用于总线挂载设备区分唯一性
- 标签(如
xxx:)常用于引用 phandle
例子:
c
i2c1: i2c@1c2b400 { // 标签 i2c1,节点名 i2c,挂载地址 0x1c2b400
/* 子节点和属性 */
};1
2
3
2
3
2、属性
设备参数、寄存器、compatible标识等都写作属性
语法:
c
属性名 = 属性值; // 最常见
属性名; // 空值属性(标志位,代表“此属性存在”)1
2
2
属性的类型
- 字符串:用英文双引号包裹
compatible = "vendor,device-name"; - 数值/数组:用尖括号包裹,十六进制
0x,十进制直接数字,多数字之间用空格reg = <0x01c2b400 0x400>;gpios = <&gpio1 4 GPIO_ACTIVE_HIGH>; - 标志属性:只写名字,无值
status;
3、注释
- 单行注释:
// 内容 - 多行注释:
/* ... */
三、常见的结构和书写风格
1、根节点
设备树入口/最顶端,通常直接写 / { ... };
例子:
c
/ {
model = "LCKFB TaishanPi 3M RK3576 Board";
compatible = "lckfb,tspi-3m-rk3576", "rockchip,rk3576";
// ...
};1
2
3
4
5
2
3
4
5
2、子节点嵌套
每个节点内部可以有属性和子节点(用大括号包裹)
例子:
c
/ {
soc {
i2c@1c2b400 {
sensor@20 {
/* 这是子节点 */
};
};
};
};1
2
3
4
5
6
7
8
9
2
3
4
5
6
7
8
9
3、节点名字和标签用法
c
myled: led@0 {
compatible = "gpio-leds;
};1
2
3
2
3
- myled: 标签:用于被其它地方引用(如 phandle,见进阶用法)
- led@0:节点名称和在父节点下唯一的地址
4、属性类型详细说明
| 类型 | 示例 | 说明 |
|---|---|---|
| 字符串 | compatible = "myvendor,mydevice"; | 驱动匹配用 |
| 单数字 | interrupt-parent = <&gpio2>; | 引用标签 |
| 数组 | reg = <0x100000 0x1000>; | 物理地址+长度 |
| 标志属性 | status; | 仅用于“存在”无具体值 |
| 多字符串 | compatible = "v1", "v2", "v3"; | 多个可兼容 |
5、引号和尖括号
- 属性为字符串时要用英文双引号,每个字符串都要包裹
- 单个或数组数字用尖括号
**< ... >** - 逗号用于分隔字符串/数字,空格分隔数字
6、引用其他节点
常见用法,例如 gpio、interrupt-parent:
c
interrupt-parent = <&gpio2>;1
&gpio2 是上面定义过的标签形式,引用 phandle。
四、include 和拆分
- 支持
#include语法,引用.dtsi公共部分(类似 C 语言 include)
例子:
c
#include "soc_common.dtsi"1
五、常用标准属性简表
| 属性名 | 作用说明 | 举例 |
|---|---|---|
| compatible | 驱动匹配关键 | "vendor,chip123" |
| reg | 外设物理地址/长度 | <0x40000000 0x1000> |
| interrupts | 中断号 | <45 IRQ_TYPE_LEVEL_HIGH> |
| status | 当前硬件是否可用 | "okay" / "disabled" |
| gpios | GPIO 管脚信息 | <&gpio1 5 GPIO_ACTIVE_LOW> |
| interrupt-parent | 中断控制器引用 | <&gic> |
| phandle | 节点唯一引用指针 | <...> |
六、实际样例解析
1、源代码
c
/ {
model = "LCKFB TaishanPi 3M RK3576 Board";
compatible = "lckfb,tspi-3m-rk3576", "rockchip,rk3576";
/*
* 用户LED
* 用于提示系统状态
*/
leds: leds {
status = "okay";
compatible = "gpio-leds";
work_led: work {
linux,default-trigger = "heartbeat";
gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
};
};
};1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2、顶层属性
model = "LCKFB TaishanPi 3M RK3576 Board";:
- model 属性:单板的名片,主要用于可读性,显示在启动日志里。
"LCKFB TaishanPi 3M RK3576 Board"对应你的板卡实际型号。
compatible = "lckfb,tspi-3m-rk3576", "rockchip,rk3576";:
- compatible 属性:最关键的匹配标识!
- 第1位
lckfb,tspi-3m-rk3576(你的自定义标识,优先推荐用于驱动官方适配)。 - 第2位
rockchip,rk3576(SoC型号标识,兼容于主流的 Rockchip 芯片)。
- 第1位
- 内核/驱动会根据 compatible 字符串自动匹配对应驱动程序。
3、leds 节点
leds: leds {
- 这里同时出现标签和节点名
leds:是标签,便于在其他地方引用(如 phandle 高级应用)leds是节点名,表明本区块是“LED相关硬件资源”- 写法格式:
标签名: 节点名 { ... }
- 这块描述板子上所有 LED 灯
status = "okay";
- 属性,表明该节点“已启用”。
- 另外,
disabled表示禁用该节点、让内核忽略它。
- 另外,
compatible = "gpio-leds";
- 说明这个节点里的设备属于“gpio-leds”驱动框架,内核会用 gpio-led 驱动管理这里列出的所有 LED。
4、work_led子节点
work_led: work {
work_led:是标签,便于作为引用、给其他节点或属性(phandle)使用。work是本节点名,代表这是一颗名字为work的LED。
linux,default-trigger = "heartbeat";
- 这行定义了 LED 的默认触发器,表示这颗灯将显示 Linux 心跳(CPU负载或内核活动的节奏闪烁)。
gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_LOW>;
- 指定驱动控制这颗LED的物理GPIO口:
<&gpio0 ...>:&gpio0是前面可能定义过的 GPIO 控制器的 phandle 标签引用RK_PA0:具体的GPIO管脚编号(RK为Rockchip平台惯用写法,PA0为第0组第0脚)GPIO_ACTIVE_LOW:表示接低电时此LED亮(硬件为低电平点亮)
- 这组写法告诉内核该如何实际操控这颗LED。
5、结构说明
- 根节点统一描述板卡基本信息
- leds节点定义为一个gpio-leds框架设备,包括所有LED灯
- 每颗LED再作为子节点描述单独属性,与物理硬件一一对应
这样写,内核和驱动能自动发现、识别、管理一切LED设备,不用手写GPIO资源表,也不用烧写底层地址,便于移植和维护。
七、简单字段速查表
| 语法 | 意义 |
|---|---|
xxx { ... }; | 新节点 |
xxx = yyy; | 新属性 |
xxx: yyy@zz {} | 标签+节点名@地址 |
#include "" | 引用其他dts/dtsi文件 |
// 注释 | 单行注释 |
/* 注释 */ | 多行注释 |