设备树DTS简介及DTS基本语法

参考资料:
 
在linux3.1版本引入设备树
设备树用来描述板级信息
0

编译设备树:

make all    // 全编译,包括内核镜像和dtb
make dtbs    // 编译所有的设备树文件
make imx6ull-14x14-emmc-4.3-800x480-c.dtb        // 编译单个dtb
 

dtc反编译出dts方法:

sudo apt install device-tree-compiler
通过安装device-tree-compiler工具,可以通过下面的命令进行将dtb反编译出dts:
fdtdump imx6ull-14x14-emmc-4.3-800x480-c.dtb > test.txt            或
dtc -I dtb -O dts -o test.dts imx6ull-14x14-emmc-4.3-800x480-c.dtb
 

DTS语法基本语法:

1、.dtsi头文件

和c语言一样,也有头文件的概念,举个例子:
为了适应不同的屏幕,其他的设备树内容都是一样的,那么就可以不同屏幕的设备创建不同分辨率的设备树dts文件
设备树不仅可以引用.dtsi头文件,也可以直接引用c语言的.h头文件,用来说明一些dts规范
 

2、设备节点

如下截取设备树部分:
 {                    // 根节点,多个文件的根节点在dtc时会汇总为一个
         aliases {
                 can0 = &flexcan1;
        };
         cpus {
                 #address-cells = <1>;
                 #size-cells = <0>;

                 cpu0: cpu@0 {
                         compatible = "arm,cortex-a7";
                         device_type = "cpu";
                         reg = <0>;
                };
        };
         intc: interrupt-controller@00a01000 {
                 compatible = "arm,cortex-a7-gic";
                 #interrupt-cells = <3>;
                 interrupt-controller;
                 reg = <0x00a01000 0x1000>,
                       <0x00a02000 0x100>;
         };
}
节点命令格式:
label:    node-name@unit-address
label是个标签,label 的目的就是为了方便访问节点,可以直接通过&label 来访问这个节点,比如通过&cpu0 就可以访问“cpu@0”这个节点,而不需要输入完整的节点名字
node-name是节点名字,为 ASCII 字符串
unit-address是节点基地址
 

基本节点属性:

compatible = "arm,cortex-a7";                                            // 字符串属性,compatible 属性的值为字符串“arm,cortex-a7
reg = <0>;                                                                // 32位无符号整数,reg属性的值为0
compatible = "fsl,imx6ull-gpmi-nand", "fsl, imx6ul-gpmi-nand";            // 属性值也可以为字符串列表,字符串和字符串之间采用“,”隔开,代码设置属性 compatible 的值为“fsl,imx6ull-gpmi-nand”
                                              和“fsl, imx6ul-gpmi-nand”。

 

 

3、标准属性

3.1 compatible属性

这个是跟驱动进行匹配的
一般驱动程序文件都会有一个 OF 匹配表,此 OF 匹配表保存着一些 compatible 值,如果设备节点的 compatible 属性值和 OF 匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动
 

3.2 status属性

status 属性看名字就知道是和设备状态有关的,status 属性值也是字符串
可选状态有:
okay        // 表示设备可以操作
disabled    // 表示设备当前不可操作
fail        // 表示设备不可操作,没用过
fail-sss    // 表示设备不可操作,也没用过
 

3.3 #address-cells 、#size-cells 属性和reg属性

这两个属性的值都是无符号 32 位整形,#address-cells 和#size-cells 这两个属性可以用在任何拥有子节点的设备中,用于描述子节点的地址信息。#address-cells 属性值决定了子节点 reg 属性中地址信息所占用的字长(32 位),#size-cells 属性值决定了子节点 reg 属性中长度信息所占的字长(32 位)。#address-cells 和#size-cells 表明了子节点应该如何编写 reg 属性值,一般 reg 属性都是和地址有关的内容,和地址相关的信息有两种:起始地址和地址长度,reg 属性的格式一为:
reg = <address1 length1 address2 length2 address3 length3……>
例如下面节点:
aips3: aips-bus@02200000 {
    compatible = "fsl,aips-bus", "simple-bus";
    #address-cells = <1>;
    #size-cells = <1>;

    dcp: dcp@02280000 {
        compatible = "fsl,imx6sl-dcp";
        reg = <0x02280000 0x4000>;
    };
};
子节点 dcp: dcp@02280000 的 reg 属性值为<0x02280000 0x4000>,因为父节点设置了#address-cells = <1>,#size-cells = <1>,address= 0x02280000,length= 0x4000,相当于设置了起始地址为 0x02280000,地址长度为 0x40000。
 

3.4 追加设备节点

例如向i2c1追加mag3110设备,则可如下设置:
&i2c1 {
    clock-frequency = <100000>;
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_i2c1>;
    status = "okay";
    
    mag3110@0e {
        compatible = "fsl,mag3110";
        reg = <0x0e>;
        position = <2>;
    };
};
这个就是向i2c1节点追加mag3110设备,重点就是通过&i2c1来访问节点,然后直接在里面编写要追加或者修改的内容。
 

3.5 alias子节点

aliases {
        can0 = &flexcan1;
        can1 = &flexcan2;
        ethernet0 = &fec1;
        ethernet1 = &fec2;
        gpio0 = &gpio1;
        gpio1 = &gpio2;
        gpio2 = &gpio3;
        gpio3 = &gpio4;
        gpio4 = &gpio5;
...
        spi0 = &ecspi1;
        spi1 = &ecspi2;
        spi2 = &ecspi3;
        spi3 = &ecspi4;

};
aliases 节点的主要功能就是定义别名,定义别名的目的就是为了方便访问节点。不过我们一般会在节点命名的时候会加上 label,然后通过&label来访问节点,这样也很方便,而且设备树里面大量的使用&label 的形式来访问节点。
 

3.6 chosen 子节点

chosen 并不是一个真实的设备,chosen 节点主要是为了 uboot 向 Linux 内核传递数据,重点是 bootargs 参数。
例如当前我的开发板的chosen节点下bootargs如下:
0
如何来的可见:
0
 
以上就是最基本的设备树基础语法
posted @ 2024-03-23 19:59  lethe1203  阅读(365)  评论(0编辑  收藏  举报