浅析Linux设备树dts相关知识

一、设备树dts的基本知识

Linux内核从3.x开始引入设备树的概念,用于实现驱动代码与设备信息相分离。在设备树出现以前,所有关于设备的具体信息都要写在驱动里,一旦外围设备变化,驱动代码就要重写。

引入了设备树之后,驱动代码只负责处理驱动的逻辑,而关于设备的具体信息存放到设备树文件中,这样,如果只是硬件接口信息的变化而没有驱动逻辑的变化,驱动开发者只需要修改设备树文件信息,不需要改写驱动代码。比如在ARM Linux内,一个.dts(device tree source)文件对应一个ARM的machine,一般放置在内核的"arch/arm/boot/dts/"目录内,引入Device Tree,许多硬件的细节可以直接透过它传递给Linux,而不再需要在kernel中进行大量的冗余编码。

本质上,Device Tree改变了原来用code方式将HW配置信息嵌入到内核代码的方法,改用bootloader传递一个DB的形式。对于嵌入式系统,在系统启动阶段,bootloader会加载内核并将控制权转交给内核。
在devie tree中,可描述的信息包括:

1、CPU的数量和类别
2、内存基地址和大小
3、总线和桥
4、外设连接
5、中断控制器和中断的使用情况
6、GPIO控制器和GPIO使用情况
7、clock控制器和clock使用情况

它基本就是一棵电路板上的CPU、总线、设备组成的树,Bootloader会将这棵树传递给内核,然后内核来识别这棵树,并根据它展开出Linux内核中的platform_device、i2c_client、spi_device等设备,而这些设备用到的内存、IRQ等资源,也被传递给内核,内核会将这些资源绑定给展开的相应设备。

二、设备树dts的相关文件

通常由.dts文件以文本方式对系统设备树资源进行描述,经过Device Tree Compiler(dtc)将dts文件转换成二进制文件binary device tree blob(dtb),.dtb文件可由Linux内核解析,
有了device tree就可以在不改动Linux内核的情况下,对不同的平台实现无差异的支持,只需更换相应的dts文件即可。

除了设备树(DTS)外,还有dtsi文件,就像c代码里的头文件一样,是不同设备树共有的设备文件,我一般把它们分别叫做主设备树(dts)和子设备树(dtsi)。这不难理解,
但是值得注意的是如果dts和dtsi里都对某个属性进行定义的话,dts的定义会覆盖dtsi的定义。假如你要调试一个内核工程,工程里有很多模块是已经存在的,这样就可以直接像包含头文件
一样把共性的dtsi文件包含(#include)进来,大大减少工作量,后期也可以对类似模块再次利用。

内核中与设备树相关的文件包括以下几个:

1.1 dts
硬件的相应信息都会写在.dts为后缀的文件中,每一款硬件可以单独写一份xxxx.dts,一般在Linux源码中存在大量的dts文件,对于arm架构可以在arch/arm/boot/dts找到相应的dts,一个dts文件对应一个ARM的machie。

1.2 dtsi
值得一提的是,对于一些相同的dts配置可以抽象到dtsi文件中,然后类似于C语言的方式可以include到dts文件中,类似于C语言头文件,对于同一个节点的设置情况,dts中的配置会覆盖dtsi中的配置;

1.3 dtc
dtc是编译dts的工具,可以在Ubuntu系统上通过指令apt-get install device-tree-compiler安装dtc工具,不过在内核源码scripts/dtc路径下已经包含了dtc工具;

1.4 dtb
dtb(Device Tree Blob),dts经过dtc编译之后会得到dtb文件,dtb文件是二进制格式的, dtb通过Bootloader引导程序加载到内核。所以Bootloader需要支持设备树才行;Kernel也需要加入设备树的支持;

三、设备树dts的结构框架

/dts-v1/;
/ {
    node1 {
        a-string-property = "A string";
        a-string-list-property = "first string", "second string";
        // hex is implied in byte arrays. no '0x' prefix is required
        a-byte-data-property = [01 23 34 56];
        child-node1 {
            first-child-property;
            second-child-property = <1>;
            a-string-property = "Hello, world";
        };
        child-node2 {
        };
    };
    node2 {
        an-empty-property;
        a-cell-property = <1 2 3 4>; /* each number (cell) is a uint32 */
        child-node1 {
        };
    };
};

device tree的基本单元是node。这些node被组织成树状结构,除了root node,每个node都只有一个parent。一个device tree文件中只能有一个root node。
每个node中包含了若干的property/value来描述该node的一些特性。每个node用节点名字(node name)标识,节点名字的格式是node-name@unit-address。
如果该node没有reg属性(后面会描述这个property),那么该节点名字中必须不能包括@和unit-address。unit-address的具体格式是和设备挂在那个bus上相关。
例如对于cpu,其unit-address就是从0开始编址,以此加一。而具体的设备,例如以太网控制器,其unit-address就是寄存器地址。root node的node name是确定的,必须是“/”。
也就是说设备树源文件的结构为:

1个root节点”/”;
root节点下面含一系列子节点,“node1” and “node2”
节点node1和下又含有一系列子节点,“child-node1” and “child-node2”
各个节点都有一系列属性
这些属性可能为空,如an-empty-property
可能为字符串,如a-string-property
可能为字符串树组,如a-string-list-property
可能为Cells(由u32整数组成),如second-child-property

可以直接打开一个(rk3288)dts文件来看一下。

四、设备树dts的基本语法

在dts文件中,一个node被定义成:

[label:] node-name[@unit-address] {
   [properties definitions]
   [child nodes]
} 

“[]”表示option,因此可以定义一个只有node name的空节点,label方便在dts文件中引用
基本数据类型:

text string(以null结束),以双引号括起来,如:
string-property = “a string”
cells 是32位无符号整形数,以尖括号括起来,如
cell-property = <0xbeef 123 0xabcd1234>
binary data 以方括号括起来,如:
binary-property = [0x01 0x23 0x45 0x67];
不同类型数据可以在同一个属性中存在,以逗号分格,如:
mixed-property = “a string”, [0x01 0x23 0x45 0x67], <0x12345678>;
多个字符串组成的列表也使用逗号分格,如:
string-list = “red fish”,“blue fish”;

想了解更多设备树dts详情请到我的课程去看看《蔡工linux设备树dts入门详解》

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

零意@

您的打赏将是我继续创作的动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值