欢迎您访问365答案网,请分享给你的朋友!
生活常识 学习资料

设备树介绍

时间:2023-07-25
一、背景介绍 二、工作流程

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

在系统启动的时候,bootloader将dtb传递给内核,内核解析改文件得到一个个的device_node,linux driver初始化的时候回去获取device_node定义好的资源。

三、基本语法

设备树是一个由节点和属性组成的简单树状结构。属性是键值对,节点可包含属性和子节点。如下是一个简单的设备树的例子:

/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>; child-node1 { }; };};

很明显,上面的设备树并没有实际意义,因为它没有描述任何设备,但是它展示了节点和属性的结构,如下:

一个简单的根节点:”/”一对子节点:”node1” and “node2”“node1”的一对子节点:”child-node1” and “child-node2”一堆分散在树的属性

属性是简单的键值对,它可以为空,也可以是任意的字节流。

基本类型字符串文本字符串(以空字符结尾)用双引号表示:
string-property = “a string”;字符串列表逗号分隔
string-list = “red fish”, “blue fish”;cell

用尖括号括起来 ,例如<1 0x3 0x123>,每个成员都是32bit无符号整形数据,每个成员都是一个cell,称为arrays of cells;

二进制数据

二进制数据用中括号‘[]’限定
binary-property = [0x01 0x23 0x45 0x67];

用中括号括起来的字节序列(byte string)[xx xx xx ...],使用16进制表示1个/多个byte,需要注意的是,byte string中,一个byte必须用2位16进制数来表示,例如[00 11 22],其中00不能简写为0,但是byte之间的空格可以省略,也就是[00 11 22]和[001122]是一样的;

自由组合多种不同类型的数据之间用逗号分隔
mixed-property = “a string”, [0x01 0x23 0x45 0x67], <0x12345678>;四、常用属性

设备书规范预定义了一些标准的属性

1、compatible

每个节点都要有一个compatible属性。

compatible 属性的值是一个字符串列表,compatible 属性用于将设备和驱动绑定起来。字符串列表用于选择设备所要使用的驱动程序,compatible 属性的值格式如下所示:

compatible = "manufacturer,model"

manufacturer 表示厂商,model 一般是模块对应的驱动名字。

例如:

sound {undefined compatible = "fsl,imx6ul-evk-wm8960","fsl,imx-audio-wm8960"; 、、、、、. }

上述实例中compatible属性有两个值,分别是“fsl,imx6ul-evk-wm8960”和“fsl,imx-audio-wm8960”,其中“fsl” 表示厂商是飞思卡尔,“imx6ul-evk-wm8960”和“imx-audio-wm8960”表示驱动模块名字,这个设备首先使用第一个兼容值在 Linux 内核里面查找,看看能不能找到与之匹配的驱动文件,如果没有找到的话就使用第二个兼容值查。

那么怎么找?去哪里找?

一般驱动程序文件都会有一个OF匹配表,此OF匹配表保存着一些compatible值,如果设备节点的compatible属性值和OF匹配表中的任何一个值相等,那么就表示设备可以使用这个驱动。

比如在文件imx-wm8960.c中有如下内容

static const struct of_device_id imx_wm8960_dt_ids[] = {    { .compatible = "fsl,imx-audio-wm8960", },    { }};MODULE_DEVICE_TABLE(of, imx_wm8960_dt_ids); static struct platform_driver imx_wm8960_driver = {    .driver = {        .name = "imx-wm8960",        .pm = &snd_soc_pm_ops,        .of_match_table = imx_wm8960_dt_ids,    },    .probe = imx_wm8960_probe,    .remove = imx_wm8960_remove,};


imx_wm8960_dt_ids 就是 imx-wm8960.c 这个驱动文件的匹配表,此匹配表只有一个匹配值“fsl,imx-audio-wm8960”。如果在设备树中有哪个节点的 compatible 属性值与此相等,那么这个节点就会使用此驱动文件
 

status 属性

status 属性是和设备状态有关的,status 属性值也是字符串,字符串是设备的状态信息,默认情况下不设置该属性是使能状态(okay)。

dtsi 文件中定义了很多设备,但是在你的板子上某些设备是没有的。这时你可以给这个设备节点添加一个 status 属性,设置为“disabled”.

ValueDescription"okay"设备正常运行"disabled"设备不可操作,但是后面可能恢复工作"fail"发生了严重错误,需修复"fail-sss"发生了严重错误,需要修复;sss表示错误信息 #address-cells、#size-cells和reg属性

可寻址的设备可以使用两种方式来声明设备地址,第一种是结点名@地址,第二种是在结点内部使用reg属性指定。

每一个可寻址的设备都有一个”reg”属性,其是以reg = 格式组成的一系列元组,每一个元组代表了设备使用的地址空间,包含起始地址和大小。还有另外一个问题,地址和大小用几个u32表示呢?这个就由父节点的"#address-cells","#size-cells"属性确定。

cpus { #address-cells = <1>; //地址个数为1 #size-cells = <0>; //length个数为0,即只有地址,没有长度 cpu@0 { device_type = "cpu"; compatible = "arm,cortex-a8"; reg = <0>; }; }; amba { #address-cells = <1>; // 地址个数为1 #size-cells = <1>; // 长度个数为1 compatible = "arm,amba-bus"; ranges; pdma0: dma@e0900000 { compatible = "arm,pl330", "arm,primecell"; reg = <0xe0900000 0x1000>;//起始地址0xe0900000,长度0x1000 interrupt-parent = <&vic0>; interrupts = <19>; clocks = <&clocks CLK_PDMA0>; clock-names = "apb_pclk"; #dma-cells = <1>; #dma-channels = <8>; #dma-requests = <32>; }; };

ranges和dma-ranges属性

我们之前讨论了如何给设备分配地址,但是这个地址仅仅是相对于当前的设备节点而言的。我们还没有介绍如何将这个地址转换成CPU能够使用的地址。

根节点描述了从CPU侧看的地址分配情况,根节点的子节点已经使用了CPU的地址域,因此无需做任何显性的映射。例如我们为串口设备”serial@101f0000”直接分配CPU地址0x101f0000。

注意那些不是根节点的子节点没有使用CPU的地址域。为了得到映射地址,设备树必须指明如何实现一个地址域到另一个地址域的转换。ranges属性就是为这个目的设置的。

总结:

1、ranges属性值的格式 , 表示将local地址向parent地址的转换。

比如对于#address-cells和#size-cells都为1的话,以<0x0  0x10 0x20>为例,表示将local的从0x0~(0x0 + 0x20)的地址空间映射到parent的0x10~(0x10 + 0x20)

其中,local地址的个数取决于当前含有ranges属性的节点的#address-cells属性的值,size取决于当前含有ranges属性的节点的#size-cells属性的值。

而parent地址的个数取决于当前含有ranges属性的节点的parent节点的#address-cells的值。

2、对于含有ranges属性的节点的子节点来说,其reg都是基于local地址的

3、ranges属性值为空的话,表示1:1映射,说明子地址空间和父地址空间完全相同,不需要进行地址转换。

4、对于没有ranges属性的节点,代表不是memory map区域


'dma-ranges'属性的结构和定义与'ranges'属性完全相同,唯一不同的是地址是dma使用的地址,'ranges'中的地址是cpu使用的地址。

ref:

Device Tree(一):背景介绍

Device Tree(二):基本概念

设备树中ranges属性分析(1) - 摩斯电码 - 博客园

5、设备树的规范 - DTS格式 - 简书

linux设备树笔记--dts基本概念及语法

一文带你搞懂设备树 - 云+社区 - 腾讯云

Linux device tree(设备树)_往事随风的博客-CSDN博客

2.1设备树的规范(dts和dtb)——DTS格式_一个嵌入式软件工程师的博客-CSDN博客_设备树规范

【linux】设备树dts文件中节点的属性compatible #address-cells 和#size-cells reg属性_那可真是太开心了的博客-CSDN博客_dts reg属性

Copyright © 2016-2020 www.365daan.com All Rights Reserved. 365答案网 版权所有 备案号:

部分内容来自互联网,版权归原作者所有,如有冒犯请联系我们,我们将在三个工作时内妥善处理。