Linux驱动系列--4.设备树

设备树的理解

个人理解

设备树是一种设备信息结构体,在一个嵌入式系统中,存在各种设备,CPU,RAM,ROM,IIC,定时器,SPI等等都是一种设备,在系统构建时,为了方便设备驱动开发,将各种设备的信息以树状结构整合到一起,在编写驱动时,从设备树上获取设备基础信息,进行设备的配置和操作。
在设备树中根节点为设备树的根,设备以树干-树枝-树叶的结构链接,设备信息包含:兼容性,寄存器地址,设备类型等信息。

设备树的生成

设备树文件格式为.dtb格式,有dtsi文件通过dtb编译器编译而来。我们通常通过修改dtsi文件,编译生成设备树文件。
根据具体电路原理图及数据手册修改设备树文件后,编译加载设备树,即可在系统中发现修改后的设备文件,然后在编写底层驱动时,根据提取设备文件的描述信息,对设备进行初始化和读写操作。

设备树语法

设备树组成

  • demo
/*--------------------第一部分----------------*/
#include <dt-bindings/input/input.h>
#include "imx6ull.dtsi"            ---------------①


/*--------------------第二部分----------------*/
/ {  --------------------②
    model = "Seeed i.MX6 ULL NPi Board";
    compatible = "fsl,imx6ull-14x14-evk", "fsl,imx6ull";

    aliases {
            pwm0 = &pwm1;
            pwm1 = &pwm2;
            pwm2 = &pwm3;
            pwm3 = &pwm4;
    };
    chosen {
            stdout-path = &uart1;
    };

    memory {
            reg = <0x80000000 0x20000000>;
    };

    reserved-memory {
            #address-cells = <1>;
            #size-cells = <1>;
            ranges;

            linux,cma {
                    compatible = "shared-dma-pool";
                    reusable;
                    size = <0x14000000>;
                    linux,cma-default;
            };
    };
    /*-------------以下内容省略=-------------*/
};

/*--------------------第三部分----------------*/
&cpu0 {  --------------------③
    dc-supply = <&reg_gpio_dvfs>;
    clock-frequency = <800000000>;
};

&clks {  --------------------④
    assigned-clocks = <&clks IMX6UL_CLK_PLL4_AUDIO_DIV>;
    assigned-clock-rates = <786432000>;
};


&fec1 {  --------------------⑤
    pinctrl-names = "default";
    pinctrl-0 = <&pinctrl_enet1>;
    phy-mode = "rmii";
    phy-handle = <&ethphy0>;
    status = "okay";
};
/*-------------以下内容省略=-------------*/
  • 头文件
    设备树可以包含头文件。经常讲一款MPU的设备树信息写成一个dts文件,其它板子使用时,只需要包含这个头文件就把MPU信息加进来了。

  • 根节点
    /{…}中’/'代表根节点,所有信息都是在根节点之下,一个dts文件只能有一个根节点,不同的头文件中的根节点会合并在一起。

  • 追加节点信息
    &cpu0中为节点cpu0追加信息。节点可以为本文件中的子节点,也可以是不同的头文件包含的子节点。

  • 节点定义

node-name@unit-address{
属性1 = …
属性2 = …
属性13= …
子节点…
}

node-name为节点名,@为分隔符,unit-address为节点reg属性首地址,若无reg属性可直接省略@unit-address。同级子节点节点名唯一,节点名相同,unit-address不同也可以。

  • 节点别名
cpu0: cpu@0 {
    compatible = "arm,cortex-a7";
    device_type = "cpu";
    reg = <0>;
}

其中cpu0为节点别名,方便直接通过&cpu0对其追加信息。为此产生一个特殊节点:别名子节点,作用是为其他节点定义别名。

aliases {
    can0 = &flexcan1;
    can1 = &flexcan2;
    ethernet0 = &fec1;
    ethernet1 = &fec2;
    gpio0 = &gpio1;
    gpio1 = &gpio2;
    gpio2 = &gpio3;
    gpio3 = &gpio4;
    gpio4 = &gpio5;
    i2c0 = &i2c1;
    i2c1 = &i2c2;
    /*----------- 以下省略------------*/
}
  • choosen 子节点
    不代表实际硬件,用于向内核传递参数。

节点属性

  • compatible
    通常由一个或多个字符串组成,定义了设备编程模型,用于设备和驱动匹配。
intc: interrupt-controller@a01000 {
    compatible = "arm,cortex-a7-gic";
    #interrupt-cells = <3>;
    interrupt-controller;
    reg = <0xa01000 0x1000>,
          <0xa02000 0x100>;
};
  • model
    用于指定设备的制造商和型号,推荐使用“执照商, 型号”的格式。

  • status
    用于指示设备操作状态,状态值如下

状态值 描述
“okay” 设备正常运行
“disabled” 设备目前尚未运行,但是未开可能运行(比如热插拔)
“fail” 表示设备不可操作
“fail-sss” 设备不可操作,因为检测到严重错误。
  • #address-cells和#size-cells
    二者同时存在,用于设置子节点的“reg”属性的“书写格式”。size指定子节点reg属性地址字段所占长度。

  • reg
    格式reg = <0x900000 0x4000>,表示起始地址为0x900000长度为0x4000的一段空间。

  • ranges
    属性值类型:任意数量的 <子地址、父地址、地址长度>编码

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章