【Linux驱动】Linux设备树(一)—— 设备树基本语法

  • Post author:
  • Post category:linux


设备树是一种树形结构,用于描述某一个板级设备的硬件信息,比如 CPU数量、I2C接口上接了哪些设备、SPI接口上接了哪些设备等。设备树让驱动程序和硬件信息发生了解耦,对于不同的板级设备,即便是外设不同,也无需变动驱动,只需要修改设备树即可。

一、设备树文件类型

C语言的文件类型包含 .c、.h、.i、.s、.o,设备树也存在类似的文件,



  • .dts:



    设备树源文件,一般描述板级信息(开发板上包含哪些外设)—— 类似于 .c 文件


  • .dtsi:



    描述 SOC 信息(即CPU数量、主频等)                                 —— 类似于 .h 文件


  • .dtb:



    二进制设备树文件,经过 .dts 编译得到的文件                         —— 类似于 .o 文件

通常会将不同板级设备的共同信息提取出来作为一个通用的文件,其他板级设备独有的 .dts 文件直接引入这个通用文件即可,这个通用文件就是 .dtsi 文件。



注意:

每次修改完 .dts 或 .dtsi 后,都需要重新编译成 .dtb

二、.dts 文件语法结构

.dts 文件内部也是以树形结构描述设备信息的,根节点下包含了其他子节点 cpus、backlight、spi@fe001000 等,其中 cpus 下又包含了 cpu@0 和 cpu@1 两个节点。

1、节点命名规范

每一个节点的命名规范为


【label:】node-name@unit-address


label

:节点别名(可省略)。有时节点名比较长,为了方便其他地方获取节点,会给节点起一个别名


node-name

:节点名(字母开头),同一级下的节点名不能重复。


unit-address

:该节点的起始地址。如果该节点无 reg 属性,那么unit-address 必须省略

以下图为例,节点ov5640@3c的名字是 ov5640,地址是 3c,别名为 ov5640

2、获取节点

一般通过别名获取节点,获取节点使用的是


&


符号。

// &节点或节点别名
// 通过别名获取节点ov5640@3c
&ov5640

3、追加节点内容

.dtsi 文件中保存了不同板机设备的共同信息,但是当前开发板还包含了一些额外的 cpu0 的信息,我们需要追加这些信息。比如imx6ull.dtsi 中已经包含了 cpu0 的相关信息

我们希望追加一些额外信息,所以我们可以先获取到这个节点,然后追加内容

4、标准属性

(1) compatible

兼容性列表,表示当前设备是否与当前内核兼容,compatible 属性的格式如下:

/* 格式 */
compatible: "manufacturer,model", ... ;
  • manufacturer:表示厂商
  • model:表示驱动模块的名字

sound 设备会使用兼容性列表里的内容逐个在 Linux 内核查找,是否存在对应的驱动模块。

(2) model

描述的是设备模块信息,比如当前设备类型、型号等。

(3) status

描述了当前设备状态信息。







描述

“okay” 表明设备是可操作的
“disable” 表明设备当前不可被操作,但未来可以变为可操作
“fail” 表明设备不可操作,因为检测到了一系列错误,未来不大可能变得可操作
“fail-xxx” 意义和 “fail” 相同,后面的 xxx 表示检测到的错误内容

(4) #address-cells、#size-cells、reg属性

决定了子节点中的 reg 属性应该如何设置。


  • #address-cells:




    reg属性中


    每个地址要使用多少个 u32 类型的值来表示

  • #size-cells:


    reg属性中


    每个地址长度要使用多少个 u32 类型的值来表示

  • reg:


    描述了某个外设寄存器地址的范围信息
/* 1、示例1 */
{
    #address-cells = <1>;    // 每个地址使用1个u32类型的值来表示
    #size-cells = <0>;       // 无地址长度
    gpio_spi: gpio_spi@0 {
        reg = <0>;           // 这里的 0 代表起始地址
    }
}

/* 2、示例2 */
{
    #address-cells = <1>;    // 每个地址使用1个u32类型的值来表示
    #size-cells = <1>;       // 每个地址长度使用1个u32类型的值来表示

    dcp: dcp@02280000 {
        reg = <0x02280000 0x4000>;    // 0x02280000代表起始地址,用 1 个u32类型的值来表示
                                      // 0x4000 代表地址长度,用 1 个u32类型的值来表示
    }
}

三、设备树在系统中的体现

Linux内核在启动时会解析设备树中各个节点的信息,并且在根文件系统的 /proc/device-tree 目录下根据节点名字创建对应的文件夹,属性则是创建对应的文件。

板级设备的 dts 文件:

/proc/device-tree 目录



版权声明:本文为challenglistic原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接和本声明。