07 linux内核device-tree基础

设备树是用一个类似文本的dts文件来描述所有硬件相关的内容. dtb是dts文件编译后得到的文件.
dtc命令可以把dts文件编译成dtb, 也可以把dtb文件反编译成dts.

H5所用的dts文件在内核源码目录arch/arm64/boot/dts/allwinner/里.

dtsi文件是多个方案的设备树共用部分,像c的头文件可在设备树文件里include引用.
现H5方案用的dts是: sun50i-h5-nanopi-neo2.dts


dtc命令主要用法:

dtc -I 输入格式(dts/dtb)  -O 输出格式(dts/dtb)  -o 输出文件名   输入文件...

把dtb文件反编译成dts文件:

dtc -I dtb -O dts -o my.dts sun50i-h5-nanopi-neo2.dtb

把dts文件编译成dtb文件:

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


参考文档: https://elinux.org/Device_Tree_Usage

设备树是由节点和属性组成, 一个节点可以有多个子节点, 子节点里还可以有它的子节点和属性…
节点名和属性名可以自定义, 也有些专门用途的属性.
设备树是由根节点”/”开始的, 用”{}”表示其作用范围. 如:

/ {   /* 根节点 */
    node1 {  /* 子节点 */
        property = "string";  /* 子节点属性 */
        child-node1 {   /* 子节点的子节点 */
            child-property = <1>;  /* 子节点的子节点属性 */
        };
        child-node2 {  /* 子节点属性 */
        };
    };
    node2 {

    };
};


----------
node1和node2分别描述一个设备的信息.
每个节点或每个属性语句都需要以分号结尾.
节点属性的值只分成3种:
 1)  字符串, 以双引号括起来. 如:   what = "hello";  表示what属性的值是一个字符串"hello"
 2)  32位无符号整形数, 以<>符号括起来. 如: cout = <11>;  表示count属性的值是一个整型数11
 3)  字节数组, 以[]符号括起来. 如:  mymac = [11 22 33 44 55 66]; 表示mymac属性值是一个char数组.
     //注意字节数组里内容默认是16进制的,0x即使不写也是按16进制数来处理.

属性值可以有连续多个值,需要使用逗号隔开就可以了. 如:
mixed-property = "a string", [0x01 0x23 0x45 0x67], <0x12345678>;
string-list = "red fish", "blue fish";

与地址相关的节点以"name@基地址"方式来命名, name只能是英文,31个字符长度.
无需写基地址的节点则可以以"name"方式直接来命名.
如果设备的基地址由片选和内部片选号(一般为0)组成,则"name@片选号,内部片选号"的方式来命名
        ethernet@0,0 {
            compatible = "smc,smc91c111";
            reg = <0 0 0x1000>;
        };

name通常是一种设备的类型,不是具体的型号.
节点的compatible属性用于与设备驱动匹配使用(非常重要). 它是一个字符串数组.
compatible属性值可以有多个字符串,表示此设备是有兼容多种角色的功能.
注意属性值里的通配符是不会起作用的.

地址相关的属性.

reg属性表示相关的配置寄存器基地址及地址长度,可以表示多个基地址及其长度.
   写法: "reg = <address1 length1 address2 length2 address3 length3 ...>"

reg属性值里的顺序可以是: "基地址  地址长度  基地址  地址长度"
         也可以是: "基地址 基地址 ... 地址长度 地址长度 ... "
#address-cells属性表示子节点reg属性值里多少个基地址后才可能会有地址长度,如果#size-cells0则表示reg属性值里全是基地址
#size-cells属性表示子节点reg属性值里多少个地址长度才可能会有另外的基地址

如:

/ {
    #address-cells = <1>; //表示子节点里的reg属性值里一个基地址后就可能有地址长度或另一个基地址
    #size-cells = <1>;    //表示reg属性值里一个基地址后就有一个地址长度

    serial@101f0000 {
        compatible = "arm,pl011";
        reg = <0x101f0000 0x1000 >;
    };

    gpio@101f3000 {
        compatible = "arm,pl061";
        reg = <0x101f3000 0x1000
               0x101f4000 0x0010>;
    };
};
    external-bus {
        #address-cells = <2>;
        #size-cells = <1>; 
        //表示它的子节点里的reg属性值里可以是: "基地址 基地址 地址长度"
                     也可以是: "基地址 基地址 地址长度 基地址 基地址 地址长度 ..."
        ...
    };

ranges属性可以在根节点制定好具体控制器的基地址表格,而控制器只需写上ranges里的序号作基地址即可.
如smc91c111的基地址为0x10100000, a1234-i2c-bus的基地址为0x10160000, k8f1315ebm的基地址为0x30000000

/ {
    ...
    external-bus {
        #address-cells = <2>
        #size-cells = <1>;
        ranges = <0 0  0x10100000   0x10000     // Chipselect 1, Ethernet
                //当访问地址0x10100000时,Ethernet则占用地址总线和数据总线
                  1 0  0x10160000   0x10000     // Chipselect 2, i2c controller
                  2 0  0x30000000   0x1000000>; // Chipselect 3, NOR Flash
           // 第一列表示片选线的序号(用于确定哪个控制器工作), 第二列表示内部片选线序号(控制器的内部片选)

        ethernet@0,0 {  /* 这里的"0,0"是指ranges表格里的<0  0 ...项 */
            compatible = "smc,smc91c111";
            reg = <0 0 0x1000>;
        };

        i2c@1,0 {
            compatible = "acme,a1234-i2c-bus";
            #address-cells = <1>;
            #size-cells = <0>;
            reg = <1 0 0x1000>;
            rtc@58 {
                compatible = "maxim,ds1338";
                reg = <58>;
            };
        };

        flash@2,0 {
            compatible = "samsung,k8f1315ebm", "cfi-flash";
            reg = <2 0 0x4000000>;
        };
    };
};

中断相关的属性:

interrupt-controller;属性用于标明此节点设备会接收处理中断信号.
#interrupt-cells; 属性用于标明当前节点里的interrupts属性值里的数值个数.
interrupt-parent; 使用指定的节点作父节点, 相当于在当前位置展开父节点内容
interrupts;属性指定使用的中断号
/ {
    ...
    interrupt-parent = <&intc>; //引用intc节点
    ...

    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>;
    };
};

aliases节点用于设置别名.

    aliases {
        ethernet0 = &eth0;  
        serial0 = &serial0;
    };

chose节点用于设置内核里使用的默认参数, 如bootargs

    chosen {
        bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1:/nfs console=ttyS0,115200";
    };
  • 1
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值