LV06-11-设备树插件-01-设备树插件基础

设备树插件是什么?若笔记中有错误或者不合适的地方,欢迎批评指正😃。

点击查看使用工具及版本
PC端开发环境 Windows Windows11
Ubuntu Ubuntu20.04.2的64位版本
VMware® Workstation 17 Pro 17.6.0 build-24238078
终端软件 MobaXterm(Professional Edition v23.0 Build 5042 (license))
Win32DiskImager Win32DiskImager v1.0
Linux开发板环境 Linux开发板 正点原子 i.MX6ULL Linux 阿尔法开发板
uboot NXP官方提供的uboot,使用的uboot版本为U-Boot 2019.04
linux内核 linux-4.19.71(NXP官方提供)
点击查看本文参考资料
分类 网址 说明
官方网站 https://www.arm.com/ ARM官方网站,在这里我们可以找到Cotex-Mx以及ARMVx的一些文档
https://www.nxp.com.cn/ NXP官方网站
https://www.nxpic.org.cn/NXP 官方社区
https://u-boot.readthedocs.io/en/latest/u-boot官网
https://www.kernel.org/linux内核官网
点击查看相关文件下载
分类 网址 说明
NXP https://github.com/nxp-imx NXP imx开发资源GitHub组织,里边会有u-boot和linux内核的仓库
nxp-imx/linux-imx/releases/tag/v4.19.71 NXP linux内核仓库tags中的v4.19.71
nxp-imx/uboot-imx/releases/tag/rel_imx_4.19.35_1.1.0 NXP u-boot仓库tags中的rel_imx_4.19.35_1.1.0
I.MX6ULL i.MX 6ULL Applications Processors for Industrial Products I.MX6ULL 芯片手册(datasheet,可以在线查看)
i.MX 6ULL Applications ProcessorReference Manual I.MX6ULL 参考手册(下载后才能查看,需要登录NXP官网)
Source Code https://elixir.bootlin.com/linux/latest/source linux kernel源码
kernel/git/stable/linux.git - Linux kernel stable tree linux kernel源码(官网,tag 4.19.71)
https://elixir.bootlin.com/u-boot/latest/source uboot源码

一、设备树插件?

1. 什么是设备树插件

Linux4.4 以后引入了动态设备树(Dynamic DeviceTree) 。 设备树插件(Device Tree Overlay)是一种用于设备树(Device Tree) 的扩展机制。 设备树是一种用于描述硬件设备的数据结构,广泛应用于嵌入式系统中, 特别是基于 Linux 内核的系统中。

设备树插件允许在运行时动态修改设备树的内容, 以便添加, 修改或删除设备节点和属性。它提供了一种灵活的方式来配置和管理硬件设备, 而无需重新编译整个设备树。 通过使用设备树插件, 开发人员可以在不重新启动系统的情况下对硬件进行配置更改。

设备树插件(Dynamic DeviceTree) 通常以一种文本格式定义, 称为设备树源文件(Device Tree Source,DTS) 。 DTS 文件描述了设备树的结构和属性, 包括设备节点, 寄存器地址, 中断信息等。 设备树插件可以通过加载和解析设备树文件, 并将其合并到现有的设备树中, 从而实现对设备树的动态修改。

设备树插件可以理解为主设备树的“补丁”它动态的加载到系统中,并被内核识别。 例如我们要在系统中增加RGB驱动,那么我们可以针对RGB这个硬件设备写一个设备树插件, 然后编译、加载到系统即可,无需从新编译整个设备树。

2. 应用场景

使用设备树插件, 可以实现一些常见的配置变化, 比如添加外部设备, 禁用不需要的设备,修改设备属性等。 这对于嵌入式系统的开发和调试非常有用, 特别是面对多种硬件配置或需要频繁更改硬件配置的情况下。

二、基本语法

设备树插件是在设备树基础上增加的内容,我们之前讲解的设备树语法完全适用, 甚至我们可以直接将之前编写的设备树节点复制到设备树插件里。但是也会有自己的一些语法,下面就来看一下。

1. 头部声明

设备树插件有插件头部声明, 它指定了插件的名称和版本等信息, 并指定了要修改的设备树的路径, 如下所示:

1
2
/dts-v1/;
/plugin/;
  • 第1行: 用于指定dts的版本。
  • 第2行: 表示允许使用未定义的引用并记录它们,设备树插件中可以引用主设备树中的节点,而这些“引用的节点”对于设备树插件来说就是未定义的,所以设备树插件应该加上“/plugin/”。

2. 节点

插件节点名称用于定义要添加, 修改或删除的设备节点及其属性。 它使用与设备树源文件相同的语法, 但在节点名称前面使用特定的修饰符来指示插件的操作。

比如设备树中 rs485 节点为如下所示, rs485 节点位于根节点下:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
/dts-v1/;
/ {
model = "This is my devicetree!";
#address-cells = <1>;
#size-cells = <1>;
chosen {
bootargs = "root=/dev/nfs rw nfsroot=192.168.1.1 console=ttyS0,115200";
};
//......
rk_485_ctl: rk-485-ctl {
compatible = "topeet, rs485_ctl";
gpios = <&gpio0 22 GPIO_ACTIVE_HIGH>;
pinctrl-names = "default";
pinctrl-0 = <&rk_485_gpio>;
};
};

那么我们如果在设备树插件中要为这个节点添加 overlay_node 节点, 可以有四种表达方式:

2.1 方式一:从根节点开始的绝对路径

1
2
3
4
5
6
7
8
/dts-v1/;
/plugin/;

&{/rk-485-ctl} {
overlay_node{
status = "okay";
};
};

2.2 方式二:使用节点的别名

1
2
3
4
5
6
7
8
/dts-v1/;
/plugin/;

&rk_485_ctl {
overlay_node{
status = "okay";
};
};

2.3 方式三

固定写法,如果有多个节点,通过子节点 fragment@x 的序号区分,路径也是绝对路径:

1
2
3
4
5
6
7
8
9
10
11
12
13
/dts-v1/;
/plugin/;

/{
fragment@0 {
target-path = "/rk-485-ctl";
__overlay__ {
overlay_node{
status = "okay";
};
};
};
};
  • 第6行: 指定设备树插件的加载位置,默认我们加载到根节点下,既“target-path =“/”。
  • 第7-8行: 我们要插入的设备及节点或者要引用(追加)的设备树节点放在__overlay__ {…};内。

方式一编译为dtbo后,再反编译就会得到这种格式的。

2.4 方式四

固定写法,如果有多个节点,通过子节点 fragment@x 的序号区分,路径也可以用别名:

1
2
3
4
5
6
7
8
9
10
11
12
13
/dts-v1/;
/plugin/;

/{
fragment@0 {
target = <&rk_485_ctl>;
__overlay__ {
overlay_node{
status = "okay";
};
};
};
};

方式二编译为dtbo后,再反编译就会得到这种格式的。

3. 总结

设备树插件拥有相对固定的格式,甚至可以认为它只是把设备节点加了一个“壳”编译后内核能够动态加载它。

3.1 基本格式1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/dts-v1/;
/plugin/;

/ {
fragment@0 {
target-path = "/";
__overlay__ {
/*在此添加要插入的节点*/
.......
};
};

fragment@1 {
target = <&XXXXX>;
__overlay__ {
/*在此添加要插入的节点*/
.......
};
};
.......
};
  • 第1行: 用于指定dts的版本。
  • 第2行: 表示允许使用未定义的引用并记录它们,设备树插件中可以引用主设备树中的节点,而这些“引用的节点”对于设备树插件来说就是未定义的,所以设备树插件应该加上“/plugin/”。
  • 第6行: 指定设备树插件的加载位置,默认我们加载到根节点下,既“target-path =“/”,或者使用target = <&XXXXX>,增加节点或者属性到某个节点下。
  • 第7-8行: 我们要插入的设备及节点或者要引用(追加)的设备树节点放在__overlay__ {…}内,你可以增加、修改或者覆盖主设备树的节点。

3.2 基本格式2

1
2
3
4
5
6
7
8
9
10
/dts-v1/;
/plugin/;

&{/} {
/*此处在根节点"/"下,添加要插入的节点或者属性*/
};

&XXXXX {
/*此处在节点"XXXXX"下,添加要插入的节点或者属性*/
};

三、设备树插件编译

1. DTC编译

使用dtc工具:

1
./dtc -I dts -O dtb overlay.dts -o overlay.dtbo

2. DTC反编译

使用dtc工具:

1
./dtc -I dtb -O dts overlay.dtbo -o overlay_dtb.dts