设备树 DTS

发布于:2023-01-22 ⋅ 阅读:(12) ⋅ 点赞:(0) ⋅ 评论:(0)

设备树简介

设备树的组成

设备树:由1个dts文件+n个dtsi文件组成,它们编译而成dtb(二进制的可执行文件)

dts: 在ARM Linux在,一个.dts文件对应一个ARM的machine,一般放置在内核的arch/arm/boot/dts/目录
dtsi: soc厂商会把soc公共的特性和多块开发板公用的特性提炼为dtsi,而dts则负责描述某个具体的产品(开发板)的特性。dts直接或间接的包含多个dtsi(类似于c语言的头文件,使用include包含),就体现了一个完整的产品(开发板)所有的特性
dtb: dtb(Device Tree Blob),dts经过dtc编译之后会得到dtb文件,dtb通过Bootloader引导程序加载到内核。所以Bootloader需要支持设备树才行;Kernel也需要加入设备树的支持

常用节点

/{ //   "/{" 表示 根节点 ,dts最开始的地方,可以理解为程序的main入口

    //子节点
    cpu{   // cpu节点
        name = val; // 属性名name,val是属性值。
        //val形式:
        //1  值
        //2)"string"(双引号括起来);
        //3)<u32 u32 u32> (尖括号,有多少个32位就放多少个,空格间隔);
        //4) [12 34 56](16进制单字节)。
        // val可以是这3种形式组合,如<0x123>,"abcd",[34]

        #address-cells = <1>;  
        #size-cells = <0>;  
        cpu@0 {  
            compatible = "arm,cortex-a9";  
            reg = <0>;  
        };  
        cpu@1 {  
            compatible = "arm,cortex-a9";  
            reg = <1>;  
        };
    };

    //子节点
    memory{ // 内存节点
        
    };

    //子节点
    I2C{ // I2C控制器节点
        
    };
};

注意cpus和cpus的2个cpu子结点的命名,它们遵循的组织形式为:

name(必选项)@unit-address(可选项)

name(必选项):是一个ASCII字符串,用于描述结点对应的设备类型
如3com Ethernet适配器对应的结点name宜为ethernet,而不是3com509。

unit-address(可选项)
如果一个结点描述的设备有地址,则应该给出**@unit-address**。
多个相同类型设备结点的name可以一样,只要unit-address不同即可,
如本例中含有cpu@0、cpu@1以及serial@101f0000与serial@101f2000这样的同名结点。

常用属性

例子

/ {  
    compatible = "acme,coyotes-revenge";  
    #address-cells = <1>;  
    #size-cells = <1>;  
    interrupt-parent = <&intc>;  
  
    cpus {  
        #address-cells = <1>;  
        #size-cells = <0>;  
        cpu@0 {  
            compatible = "arm,cortex-a9";  
            reg = <0>;  
        };  
        cpu@1 {  
            compatible = "arm,cortex-a9";  
            reg = <1>;  
        };  
    };  
  
    serial@101f0000 {  
        compatible = "arm,pl011";  
        reg = <0x101f0000 0x1000 >;  
        interrupts = < 1 0 >;  
    };  
  
    serial@101f2000 {  
        compatible = "arm,pl011";  
        reg = <0x101f2000 0x1000 >;  
        interrupts = < 2 0 >;  
    };  
  
    gpio@101f3000 {  
        compatible = "arm,pl061";  
        reg = <0x101f3000 0x1000  
               0x101f4000 0x0010>;  
        interrupts = < 3 0 >;  
    };  
  
    intc: interrupt-controller@10140000 {  
        compatible = "arm,pl190";  
        reg = <0x10140000 0x1000 >;  
        interrupt-controller;  
        #interrupt-cells = <2>;  
    };  
  
    spi@10115000 {  
        compatible = "arm,pl022";  
        reg = <0x10115000 0x1000 >;  
        interrupts = < 4 0 >;  
    };  
  
    external-bus {  
        #address-cells = <2>  
        #size-cells = <1>;  
        ranges = <0 0  0x10100000   0x10000     // Chipselect 1, Ethernet  
                  1 0  0x10160000   0x10000     // Chipselect 2, i2c controller  
                  2 0  0x30000000   0x1000000>; // Chipselect 3, NOR Flash  
  
        ethernet@0,0 {  
            compatible = "smc,smc91c111";  
            reg = <0 0 0x1000>;  
            interrupts = < 5 2 >;  
        };  
  
        i2c@1,0 {  
            compatible = "acme,a1234-i2c-bus";  
            #address-cells = <1>;  
            #size-cells = <0>;  
            reg = <1 0 0x1000>;  
            interrupts = < 6 2 >;  
            rtc@58 {  
                compatible = "maxim,ds1338";  
                reg = <58>;  
                interrupts = < 7 3 >;  
            };  
        };  
  
        flash@2,0 {  
            compatible = "samsung,k8f1315ebm", "cfi-flash";  
            reg = <2 0 0x4000000>;  
        };  
    };  
};

reg

设备的unit-address地址也经常在其对应结点的reg属性中给出。ePAPR标准给出了结点命名的规范:
reg:

//reg的组织形式 
reg =   <地址1 长度1>,  // 起始地址,范围长度
        <地址2 长度2>,
        <地址3 长度3>,
        ...

其中的每一组address length表明了设备使用的一个地址范围。

#address-cells: 为1个或多个32位的整型(即cell),基地址、片选号等绝对起始地址所占字长
#size-cells:寄存器地址所占字长

#address-cells = 1
#size-cells = 0
reg = <address1>

#address-cells = 1
#size-cells = 1
reg = <address1 size1>

#address-cells = 2
#size-cells = 1
reg = <address1 address2 size1>

interrupt属性

Device Tree中还可以中断连接信息,对于中断控制器而言,它提供如下四个属性:

  1. interrupt-controller : 这个属性为空,中断控制器应该加上此属性表明自己的身份;
  2. #interrupt-cells : 与#address-cells 和 #size-cells相似,它表明连接此中断控制器的设备的interrupts属性的cell大小。
    在整个Device Tree中,与中断相关的属性还包括:
  3. interrupt-parent : 设备结点透过它来指定它所依附的中断控制器的phandle,当结点没有指定interrupt-parent 时,则从父级结点继承。对于本例而言,root结点指定了interrupt-parent = <&intc>;其对应于intc: interrupt-controller@10140000,而root结点的子结点并未指定interrupt-parent,因此它们都继承了intc,即位于0x10140000的中断控制器。
  4. interrupts :用到了中断的设备结点透过它指定中断号、触发方法等,具体这个属性含有多少个cell,由它依附的中断控制器结点的#interrupt-cells属性决定。而具体每个cell又是什么含义,一般由驱动的实现决定,而且也会在Device Tree的binding文档中说明。如果有两个,第一个是中断号,第二个是中断类型,如高电平、低电平、边缘触发等触发特性。对于给定的中断控制器,应该仔细阅读相关文档来确定其中断标识该如何解析。

2个cell

第一个值: 中断号
第二个值: 触发方式
固定的取值如下:
1 = 上升沿触发
2 = 下降沿触发
4 = 高电平触发
8 = 低电平触发

3个cell

第一个值:中断号
第二个值:触发的类型
第三个值:优先级,0级是最高的,7级是最低的;其中0级的中断系统当做 FIQ处理。

在dts中引用其他节点

//label:node-name@unit-address的别名,在其他dts中被引用使为&label
[label:] node-name[@unit-address] {   //冒号前的label是为了方便引用给节点起的别名,此label一般使用为&label
    [properties definitions]          //就是属性定义,对当前节点描述,将硬件信息提供给内核处理
    [child nodes]                     //子节点 
 }

PIC2: pic@11000000 {
    interrupt-controller;
};

another-device-node {
    interrupt-parent = <&PIC>;   // 使用label来引用上述节点, 
    interrupt-parent = <&PIC2>;   // 使用label来引用上述节点, 
                                 // 使用lable时实际上也是使用phandle来引用, 
                                 // 在编译dts文件为dtb文件时, 编译器dtc会在dtb中插入phandle属性
};

&PIC: pic@10000000 {
    interrupt-controller;
};

覆盖规则:
同一层次的节点,后面的会覆盖前面的节点。

    memory@30000000 {
        device_type = "memory";
        reg = <0x30000000 0x20000000>;
    };  
    memory@30000000 {
        reg = <0x30000000 0x10000000>;
    }; 

直接引用方式覆盖(增加)节点属性:
假设下面节点定义在dtsi文件中

   xusbxti: oscillator@1 {
                compatible = "fixed-clock";
                reg = <1>;
                clock-frequency = <0>;
                clock-output-names = "xusbxti";
                #clock-cells = <0>;
            };

某个dts文件包含了该dtsi文件,并定义了如下内容


&xusbxti {
     clock-frequency = <24000000>;
};

编译设备树

将设备树文件拷贝到内核源码的arch/(处理器平台)/boot/dts/(厂家)/目录下

第一种方式:make dtbs
第二种方式:dtc -I dts -O dtb my.dts > my.dtb

设备树反编译

dtc -I dtb -O dts my.dtb -o my.dts

如果觉得对你有帮助,请意思意思
点击赞助


网站公告

欢迎关注微信公众号

今日签到

点亮在社区的每一天
签到