树莓派的设备树资料

这里有所有配置

https://www.raspberrypi.org/documentation/configuration/

设备树配置在

https://www.raspberrypi.org/documentation/configuration/device-tree.md


DT=DeviceTree 

DTB= Device Tree Block

DTS=Device Tree Source


include的文件一般用dtsi结尾


树莓派最新的内核和固件开始使用设备树管理资源和内存以及模块的加载了。主要是缓和多驱动争取系统资源的问题。

并且允许HAT模块自动配置 (https://www.raspberrypi.org/blog/introducing-raspberry-pi-hats/)


当然当前的实现并不是一个纯的设备树系统,仍然有一些板子里面的代码创建了一些平台设备。。但是其他的外部接口。比如I2C I2S SPI以及音频设备现在必须用DTB来实例化。通过start.elf来传递给kernel

.最大的影响是将所有设备从开启状态,变成关闭状态,除非DTB需要这个设备。为了继续使用外部接口和相关设备。可能需要在config,txt里面添加一些新的设置,详细的介绍放在PART3里面。


PART1 

设备树是用来描述系统硬件的。它应当包含了cpu的类型名字。内存配置和其他的外接设备。尽管通过列出硬件模块的确可以使得这些驱动模块被加载,但是设备树不应该用来描述软件。千万记得dt是系统无关的。因此任何linux特定的东西都不应该出现在这里。


DT通过分层次的节点来表示这些硬件。每个节点包含属性和子节点。属性是通过字节数组(大端字节序,字符串,数字或者一些随意的字节序列或者这些的组合)来命名的。

跟文件系统的节点和数据差不多。节点的位置和属性可以用斜线(/)分割的路径来表示。一个单独的/表示根节点。


1.1 基础的DTS语法

DTS是常常以.dts结尾的文本文件。和C语法有点像。用括号来分组。每行用分号结束,在一个闭合的括号后面必须要一个分号,和C的结构体差不多。

编译后的文件是FDT或者DTB,保存在dtb文件里面。

下面是一个简单的 .dts格式

/dts-v1/;
/include/ "common.dtsi";

/ {
    node1 {
        a-string-property = "A string";
        a-string-list-property = "first string", "second string";
        a-byte-data-property = [0x01 0x23 0x34 0x56];
        cousin: 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 {
            my-cousin = <&cousin>;
        };
    };
};

/node2 {
    another-property-for-node2;
};

1 一个需要的头部 /dts-v1/  应该是dts版本v1的意思

2 包含另外一个标准的common.dtsi。和C里面的include一样

3单一的一个节点 /

4一组子节点 node1和node2

5node1的子节点 child-node1 child-node2

6一个标签 cousin和一个标签的引用&cousin

7一些零散的属性

8一个重复的node2


属性是简单的键值对。值可以为空或者包含字节流。结构中的数据是没有编码的。


NULL结尾的字符串双引号

string-property = "a string";

32bit无符号整数用尖括号表示

cell-property = <0xbeef 123 0xabcd1234>;

随意的字节序用中括号 中间写16进制数据


binary-property = [01 23 45 67 89 ab cd ef];

混合型的数据用逗号分割

mixed-property = "a string", [01 23 45 67], <0x12345678>;

逗号也可以用来创建数据列表

string-list = "red fish", "blue fish";

1.2 关于/include/指令的一点东西

这个/include/指令一般是直接包含。类似于C语言的include. 但是dtb编译器的一个特性可能导致不同的处理方式。

假设两个节点是用绝对路径命名的,而且名字一样。那么可能会在一个dts文件里面出现两次。如果是这样的话。那么

这两个节点的属性是组合起来的,其中交叉和覆盖的属性根据需要后面的一个会覆盖前面的一个。


前面的里面,第二个出现的node2将一个新的属性添加到了原来的那个上


因此可以在dtsi里面写一个默认的值。反正后面会可以覆盖掉



1.3 标签和引用

常常需要在一个tree的地方用到另一个节点的一些属性。那么这里有四种方式。

一 使用路径字符串。

    路径应该是很明显的。跟文件系统类比一下 /soc/i2s@7e203000是BCM2835和BCM2836的I2S设备的全路径。尽管很容易为属性构建一个路径。比如 /soc/i2s@7e203000/status但是标准API不会这么做。所以你先找到这个node。然后再选择他的属性

二 使用phandle

 phandle是一个节点里面用phandle属性标记的一个独一无二的32bit整数。由于历史的原因,可能会出现多余的这些phandle。phandlees是连续的标号从1开始。0是无效的。

通常是DT编译器遇到的按照整数表达形式存储的节点的引用的时候分配的(也就是用尖括号括起来的。比如遇到<&node>这个时候就分配了一个整数)。通常是用label的形式。使用phandle节点的引用通常将对应整数值简单进行了编码。也没有一定要暗示他们就是phandles.。

三 使用 标签labels

和C语言里面的标签一样。一个标签给一个节点赋了一个名字。当变一起遇到以string格式或者整数格式存放的引用标签的时候会将他们转换成全路径。原来的标签在编译以后不会出现在编译后的文件里面。标签是没有属性的。只是一个命名 空间而已。

四 别名

别名和标签差不多。但是他们会以索引的形式出现在编译后的文件里面。他们保存在/aliases节点的属性下面。每个属性映射了一对别名和全路径。尽管别名会在源文件中出现。但是路径字符串通常作为标签的引用出现。而不是以全路径写出来。DT API通过检查路径的第一个字符来将路径字符串转换为节点。先查看路径是不是以斜线开头,如果不是斜线开头,必须通过/aliases表转换。


1.4 设备树的意义

构建一个设备树是很复杂的。但是下面还是提一下关键的几个点


compatible属性是硬件描述和软件驱动之间的联系。当系统遇到一个节点拥有compatible属性的时候。就开始寻找他的设备驱动数据库来寻找对应的驱动。linux上通常就是自动加载一些驱动模块。

status属性表明这个设备是启用还是禁用。如果是ok或者okay或者空的。就表示允许。如果是disable就表示禁用。所以可以将disabled放到dtsi里面。如果有需要,在对应的dts里面设置为OK



PART2 设备书的一些overlay                     OVERLAY是树莓派特有的。其他的有没有。后续这里我就不看了

现代的芯片是很复杂的。负载的设备树可能有好几百行。更进一步,把其他的组件和芯片放到一块板子上只会边个更麻烦。要让使得方便管理。尤其是相似的设备共用同一个组件的时候。更有必要把相同的元素放到.dtsi文件里面。然后多个.dts来包含他。


如何一个像PI一样的系统用了一些可选的组件。比如HATS。那么更麻烦。最终终每个可能的配置都需要一个设备树来描述。但是考虑到不同的基板和一些小配件仅仅需要几个GPIO针脚就共存,那么组合的数量就增加得很快了。

因此需要一个方式来描述这些占用一小部分设备树的可选组件。然后通过基本的设备树加上这些可选的组件构成完整的设备树。这些可选的元素就是overlay


2.1 片段

overlay包含大量的片段。每个包含一个节点和他的子节点。尽管听起来简单。但是语法起初很奇怪。

// Enable the i2s interface
/dts-v1/;
/plugin/;

/ {
    compatible = "brcm,bcm2708";

    fragment@0 {
        target = <&i2s>;
        __overlay__ {
            status = "okay";
        };
    };
};

compatible字符串定义了这是属于BCM2708的。也就是BCM2835基芯片的一部分。如果是BCM2836你可以用 “brcm,bcm2709”,但是除非你要使用CPU芯片的某些特性。否则这两值一般是一样的。所以用brcm,bcm2708是比较合理的。然后来到了第一个片段。片段序号是从0开始依次增加的,如果某些片段丢失了,序号变化。就是失败。

每个片段包含两个部分。第一 target属性标记这个overlay该应用到哪个节点,第二 __overlay__他的内容将添加到目标节点里面。


上面的代码片段可以写成下面的形式

/dts-v1/;

/ {
    compatible = "brcm,bcm2708";
};

&i2s {
    status = "okay";
};

将这个overlay和标准的树莓派设备树比如bcm2708-rpi-b-plus.dtb合并的效果(假设后面这个overlay后面被加载了)就是I2S接口开启。但是如果你用下面的代码编译overlay

会出错

dtc -I dts -O dtb -o 2nd.dtbo 2nd-overlay.dts

提示

Label or path i2s not found
找不到i2s


这次用-@选项来解决引用问题

dtc -@ -I dts -O dtb -o 1st.dtbo 1st-overlay.dts

记得使用 sudo apt-get install device-tree-compiler 安装

一般来说 编译器会在scripts/dtc/dtc里面提供。当dtbs 被编译的时候 用到。

make ARCH=arm dtbs

可以使用dftdump来查看编译器生成的一些内容

$ fdtdump 1st.dtbo

/dts-v1/;
// magic:           0xd00dfeed
// totalsize:       0x106 (262)
// off_dt_struct:   0x38
// off_dt_strings:  0xe8
// off_mem_rsvmap:  0x28
// version:         17
// last_comp_version:    16
// boot_cpuid_phys: 0x0
// size_dt_strings: 0x1e
// size_dt_struct:  0xb0

/ {
    compatible = "brcm,bcm2708";
    fragment@0 {
        target = <0xdeadbeef>;
        __overlay__ {
            status = "okay";
        };
    };
    __fixups__ {
        i2s = "/fragment@0:target:0";
    };
};

这里i2s变成了 0xdesdbeef。而且后面多了一个fixup

这个包含了一些映射的属性,映射了phandle和目标节点。这里就是target和-0xdeadbeef。但是片段可能包含一些没有解决的引用。需要进一步处理。

如果写了很复杂的片段。可能有其他两个节点。 __local_fixups__和__symbols__


回到1.3节。说原来的标签在编译后的文件里面不会出现。如果使用了-@的时候还是会出现的。除此之外每个label会产生一个__sybols__节点。银蛇了标签到路径。和别名节点一样。





  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
在嵌入式Linux下,设备(device tree)用来描述硬件平台的各种资源,Linux内核在启动过程中,会解析设备,获取各种硬件资源来初始化硬件。设备的overlay功能是指可以在系统运行期间动态修改设备。一般情况下,如上图所示,设备经过DTC编译器编译为二进制的hello.dtb文件,加载到内存,随Linux内核一起启动后,一般就无法更改了。如果我们想修改设备,需要修改hello.dts文件文件,重新编译成二进制文件:hello.dtb,然后重新启动内核,重新解析。有了设备的overlay功能,省去了设备的重新编译和内核重启,我们可以直接编写一个设备插件:overlay.dts,编译成overlay.dtbo后,直接给设备“打补丁”,在运行期间就可以动态添加节点、修改节点...设备的overlay功能,在很多场合都会用得到,会让我们的开发更加方便:外界插拔设备,无法在设备中预先描述:耳机树莓 + FPGA开发板基于I2C的温度传感器管脚的重新配置:PIN multiplexing修改bootcmd、分区...设备的overlay功能,目前还没有加入到内核mainline(linux-5.10.x),但目前有些开发板和配套的BSP已经支持了,支持在系统运行期间动态修改设备文件。如果你手头的开发板或内核平台还没有支持device tree overlay,可以学习本期课程,学习内核中设备overlay的实现原理,如何给内核打补丁,使内核支持设备的overlay功能。有了本期课程的学习基础,明白了设备overlay的实现原理和运行机制,你就可以尝试在自己的开发板平台上实现这个功能了。本期课程的主要内容如下:在开发板上如何实现设备的overlay功能Configfs文件系统的配置与挂载Configfs编程接口如何编写设备 overlay插件设备 overlay的编译和运行设备overlay运行机制分析本期课程适合哪些人学习:嵌入式驱动工程师嵌入式BSP工程师嵌入式软件工程师想从事嵌入式开发的同学全网首家讲解设备overlay的视频教程。   

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值