大家好,欢迎来到IT知识分享网。
什么是设备树
-
设备树(Device Tree)是用来描述板卡上的硬件资源信息的,包括外设控制器和各种外设所使用的硬件资源信息
-
设备树的源文件名后缀是.dts/.dtsi, dtsi文件一般用来描述一些通用的硬件信息资源,然后会被dts文件引入,这样dts文件中就会包含dtsi文件中的内容
-
设备树源文件在内核中的位置:/arch/arm(64)/boot/dts
-
dts源文件不能直接被内核驱动所使用,必须被编译成二进制文件才能被内核驱动使用,设备树二进制文件后缀名是dtb,使用dtc工具把dts文件编译成dtb文件
graph LR dts —-dtc—> dtb
设备树语法
dts文件布局
/dts-v1/; // 表示版本
[memory reservations] // 格式为: /memreserve/ <address> <length>;
/ {
[property definitions]
[child nodes]
};
以上各项的含义:
名称 | 含义 |
---|---|
/dts-v1/ | 设备树文件的版本 |
memory reservations | 指定保留内存,内核不会使用保留内存 |
/ | 根节点(使用花括号表示属于根节点的内容) |
property definitions | 根节点的属性,用来描述硬件 |
child nodes | 子节点(使用花括号表示属于孩子节点的内容) |
设备节点
设备树中的基本单元被称为节点(node),格式为:
[label:] node-name[@unit-address] {
[properties definitions]
[child nodes]
};
label是标号,可以省略,label的作用是为了方便地引用node,比如:
/dts-v1/;
/ {
uart0: uart@fe001000 {
compatible="ns16550";
reg=<0xfe001000 0x100>;
};
};
可以使用下面2种方法来修改uart@fe001000这个node:
// 在根节点之外使用label引用node:
&uart0 {
status = “disabled”;
};
或在根节点之外使用全路径:
&{/uart@fe001000} {
status = “disabled”;
};
属性(properties)
每个节点都有不同的属性,不同的属性又有不同的内容,属性都是键值对,值可以为空或任意的字节流
属性格式
- 属性有值
[label:] property-name = value;
- 属性没有值
[label:] property-name;
属性取值可以有四种
- arrays of cells(1个或多个32位数据, 64位数据使用2个32位数据表示)
cell 就是一个32位的数据,一个或多个cell用尖括号括起来,并以空格隔开就可以作为一种合法的属性值
interrupts = <17 0xc>
64bit数据使用2个cell来表示,一个或多个cell用尖括号包围起来:
clock-frequency = <0x00000001 0x00000000>
- string(字符串),用双引号包围起来
compatible = "simple-bus";
- bytestring(1个或多个字节),用中括号包围起来
local-mac-address = [00 00 12 34 56 78]; // 每个byte使用2个16进制数来表示
local-mac-address = [000012345678]; // 每个byte使用2个16进制数来表示
- 以上三种值的混合,以逗号隔开
compatible = "ns16550", "ns8250";
example = <0xf00f0000 19>, "a strange property format";
一些常用的属性
compatible
compatible 属性也叫做“兼容性”属性,这是非常重要的一个属性!compatible 属性的值是一个字符串列表,compatible 属性用于将设备和驱动绑定起来。
“compatible”表示“兼容”,对于某个LED,内核中可能有A、B、C三个驱动都支持它,那可以这样写:
led {
compatible = “A”, “B”, “C”;
};
内核启动时,就会为这个LED按这样的优先顺序为它找到驱动程序:A、B、C。
当该属性位于根节点时,用于指定内核中哪个machine_desc可以支持本设备,即当前设备与哪些平台兼容。其值的格式一般是”manufacturer,model”,其中manufacturer表示厂家,model表示型号(厂家的哪型产品)。
当该属性的值有多个字符串时,从左往右,从最特殊到最一般。举例来说,compatible = “samsung,smdk2416”, “samsung,s3c2416”;作为根节点的属性时,第一个字符串指示了一个具体的开发板型号,而第二个字符串要更一般,只指示了SoC的型号。在linux初始化时,会优先找支持”samsung,smdk2416″的machine_desc用以初始化硬件,找不到时才退而求其次”samsung,s3c2416″。
model
model属性与compatible属性有些类似,但是有差别。
compatible属性是一个字符串列表,表示你的硬件可以兼容A、B、C等驱动;
model用来准确地定义这个硬件是什么。
比如根节点中可以这样写:
/ {
compatible = "samsung,smdk2440", "samsung,mini2440";
model = "jz2440_v3";
};
它表示这个单板,可以兼容内核中的“smdk2440”,也兼容“mini2440”。
从compatible属性中可以知道它兼容哪些板,但是它到底是什么板?用model属性来明确。
#address-cells、#size-cells
cell指一个32位的数值
address-cells:address要用多少个32位数来表示
size-cells:size要用多少个32位数来表示
比如一段内存,怎么描述它的起始地址和大小?
下例中,address-cells为1,所以reg中用1个数来表示地址,即用0x80000000来表示地址;size-cells为1,所以reg中用1个数来表示大小,即用0x20000000表示大小:
/ {
#address-cells = <1>;
#size-cells = <1>;
memory {
reg = <0x80000000 0x20000000>;
};
};
status
status 属性是和设备状态有关的,status 属性值是字符串
&uart1 {
status = "disabled";
};
status 可选的状态如下:
值 | 含义 |
---|---|
“okay” | 表明设备是可操作的。 |
“disabled” | 表明设备当前是不可操作的,但是在未来可以变为可操作的 |
“fail” | 发生了严重错误,需修复 |
“fail-sss” | 发生了严重错误,需修复;sss表示错误信息 |
phandle
该属性可以为节点指定一个全局唯一的数字标识符。这个标识符可以被需要引用该节点的另一个节点使用。举例来说,现有一个中断控制器:
pic@10000000 {
phandle = <1>;
interrupt-controller;
};
还有一个可以产生中断的设备,且这个设备的中断信号线连接到了上述中断控制器,为了描述清楚这种关系,该设备的设备节点就需要引用中断控制器的节点:
another-device-node {
interrupt-parent = <1>; /* 数字1就唯一标识了节点pic@10000000 */
};
interrupt-controller
这是一个没有值的属性,用在中断控制器的设备节点中,以表明这个节点描述的是一个中断控制器。
interrupt-parent
该属性用于可以产生中断,且中断信号连接到某中断控制器的设备的设备节点,用于表示该设备的中断信号连接到了哪个中断控制器。该属性的值通常是中断控制器设备节点的数字标识(phandle),具体示例在上文已经出现过了。
reg
reg属性描述了设备资源在其父总线定义的地址空间内的地址。reg 属性的值一般是(address,length)对,该属性使用一对或多对(地址,长度)来描述设备所占的地址空间。至于地址和长度使用多少个cell来表示呢?这取决于父节点的#address-cells、#size-cells属性的值。
举个例子,当:
#address-cells = <1>;
#size-cells = <1>;
那么reg = <0x3000 0x20 0xFE00 0x100>,表示该属性所属的设备占据了两块内存空间,第一块是以0x3000为起始的32字节内存块;第二块是以0xFE00为起始的256字节内存块。
/aliases
/aliases节点应当作为根节点的孩子节点,用于定义一个或多个别名属性,每条别名属性会为一个设备节点的路径名设置一个别名,别名即为别名属性的属性名,属性值则是设备节点的路径名。如下面这个例子所示:
aliases { serial0 = "/simple-bus@fe000000/serial@llc500"; ethernet0 = "/simple-bus@fe000000/ethernet@31c000"; };
/chosen
/chosen节点应当用作根节点的孩子节点,有以下可选属性:
- bootargs
- stdout-path
- stdin-path
顾名思义,该节点可以指定启动参数、标准输出和标准输入,一个例子如下:
/ {
......
chosen {
bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};
......
};
向节点追加或修改内容
要向节点中追加或修改节点中的属性,可以对节点使用引用的方式来处理。
比如原始的i2c1节点是:
i2c1: i2c@021a0000 {
#address-cells = <1>;
#size-cells = <0>;
compatible = "fsl,imx6ul-i2c", "fsl,imx21-i2c";
reg = <0x021a0000 0x4000>;
interrupts = <GIC_SPI 36 IRQ_TYPE_LEVEL_HIGH>;
clocks = <&clks IMX6UL_CLK_I2C1>;
status = "disabled";
};
要对i2c1节点做属性的追加和修改,使用如下方式:
&i2c1 {
/* 要追加或修改的内容 */
};
&i2c1 表示使用引用的方式访问 i2c1 这个 label 所对应的节点
修改后的设备树代码如下:
&i2c1 {
clock-frequency = <100000>;
pinctrl-names = "default";
pinctrl-0 = <&pinctrl_i2c1>;
status = "okay";
mag3110@0e {
compatible = "fsl,mag3110";
reg = <0x0e>;
position = <2>;
};
fxls8471@1e {
compatible = "fsl,fxls8471";
reg = <0x1e>;
position = <0>;
interrupt-parent = <&gpio5>;
interrupts = <0 8>;
};
};
其中:
clock-frequency 就是新添加的属性。
status 属性的值由原来的 disabled 改为 okay
mag3110 和 fxls8471 是新增加的2个子节点
编写设备树
在DTS文件中包含其他文件
编写设备树文件时,我们通常会把多种设备的共性抽出来,写在DTSI文件(后缀为.dtsi)中,其语法与DTS文件一样。比如,多款使用了am335x的板子,因为使用了同一款SoC,描述设备时肯定会有一些相同的部分,可以把这部分抽出来,写到am335x.dtsi中,然后在具体的某型板子的设备树中包含相应的DTSI文件,包含的方式有:
/include/ “xxx.dtsi”
#include “xxx.dtsi”
设备树编译器还支持c语言的头文件,因此,如果有需要可以定义一些宏并在设备树文件中使用。
如何在设备树文件中描述设备
设备树写出来是给驱动程序看的,也就是说驱动程序怎么写的,相应的设备树就该怎么写;或者反过来,先约定好设备树怎么写,在相应的设计驱动。驱动和设备树有着对应的关系,这种对应关系也被称为bindings。具体的:
对于上游芯片厂商,应当按照devicetree-specification推荐的设备树写法,遵守各种约定,确定好如何规范的描述设备,并提供相应的驱动程序。devicetree-specification-v0.3的第四章给出了一些推荐的做法。
对于下游产品厂商,当使用芯片厂商的芯片做产品时,芯片厂商通常会提供驱动程序和设备树文件编写的参考文档,这些文档位于linux内核源码树的Documentation/devicetree/bindings目录下。如果芯片厂商没提供相应文档的话,就要读驱动的源码,知道驱动怎么写的,自然也就知道如何写设备树了。
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://yundeesoft.com/30373.html