概念
设备树是一种描述硬件资源的数据结构,在bootloader传递给内核。可以去除内核中不必要的板级代码。
设备树是Linux内核3.x之后才出现的,在内核源码的arch/架构/boot/dts目录下。
常用的名词:
DT: Device Tree 设备树
FDT: Flattened Device Tree //开放固件,设备树起源于OF,所以在设备树里会经常见到带of的函数
device tree source(dts) 设备树代码
device tree source include(dtsi) 更通用的设备树代码
device tree blob(dtb) DTS编译后得到的DTB文件
device tree compiler(dtc) 设备树编译器
dts和dtsi格式是设备树源码文件,一般dtsi里的内容更加通用。
所以一般dts文件会include需要的dtsi文件;.h格式的文件也可以被设备树文件inculde。
编译出的设备树文件是dtb格式的。
基础语法
整体结构
/{ //根节点
node1 //子节点node1
{
key = value; //node1的属性
child-node1 //子子节点child-node1
{
key = value;
};
};
node2
{
};
};
设备树文件由根节点开始,向下分为各个子节点,子节点中可以包含属性或者子子节点。
每个节点都用大括号标识范围,最后以分号结束。
根节点的大括号前用'/'号表示,子节点的大括号前要有节点名。
节点中的属性都使用key-value对来描述。
路径
在内核或驱动中获取节点时一般会通过节点在设备树中的路径查找。
路径用 从根节点向下层层子节点的名称 表示
"/node1/child-node1"
这就表示节点child-node1的路径
节点名称和别名
名称要体现设备的类型
同一级的节点只要地址不一样,名称可以不唯一
serial@20080000 { //名称@设备地址
};
uart8: serial@20080000 { //别名: 名称@设备地址
};
//uart8就是这个节点的别名
节点的引用
向节点添加属性内容的时候,一般使用节点的引用来添加
uart8: serial@20080000 { //别名: 名称@设备地址
status = "disabled";
};
&uart8{
pinctl-name = "default";
status = "okay";
};
uart8的引用和节点本身,不同的属性会被合并,相同的属性会被引用重写。
本例中status属性最终状态是"okay"的。
常见的属性
compatible
compatible是一个字符串列表,用来在驱动/内核代码中进行匹配
compatible = "led_sw";
status
一般用来表示此设备是否使能
status = "okay";
或者
status = "disabled";
reg相关
reg用来描述设备的地址范围
#address-cells表示子节点中reg地址的数量
#size-cells表示子节点中reg地址长度的数量
格式: reg = <addr1 length1 [addr2 length2]>
serial@20080000{
#address-cells = <1>;
#size-cells = <1>;
reg = <101F2000 0x1000>;
};
//101F2000是起始地址,0x1000是长度
特殊节点或属性
/chosen
chosen节点是为了boot loader向内核传递参数。对内核来说重点是bootargs属性,该属性是字符串类型,用来向内核传递cmdline。还有stdout-path和stdin-path两个可选属性,标识标准的输出输入设备。
chosen节点可在设备/sys/firmware/devicetree/base/chosen目录找到
/memory
memory是完整的设备树必须包含的节点(cpus和memory),描述硬件内存布局。
aliases
专门用来定义节点别名
aliases {
serial0 = &uart1;
serial1 = &uart2;
};
属性的数据类型
< >尖括号内的是一个或多个32位数据,多个数据用空格隔开
" "双引号内数据类型是字符串
[ ]方括号内是一个或多个字节类数据