一、设备树的概念
Linux4.4以后引入了动态设备树(Dynamic DeviceTree),我们这里翻译为“设备树插件”。 设备树插件可以理解为主设备树的“补丁”它动态的加载到系统中,并被内核识别。 例如我们要在系统中增加RGB驱动,那么我们可以针对RGB这个硬件设备写一个设备树插件, 然后编译、加载到系统即可,无需从新编译整个设备树。
设备树插件是在设备树基础上增加的内容,我们之前讲解的设备树语法完全适用, 甚至我们可以直接将之前编写的设备树节点复制到设备树插件里。具体使用方法介绍如下。
二、设备树插件格式
设备树插件拥有相对固定的格式,甚至可以认为它只是把设备节点加了一个“壳”编译后内核能够动态加载它。 格式如下:
/dts-v1/; //用于指定dts的版本
/plugin/; //表示允许使用未定义的引用并记录它们,设备树插件中可以引用主设备树中
的节点,而这些“引用的节点”对于设备树插件来说就是未定义的,所以设备树插件应
该加上“/plugin/”
/ {
fragment@0 {
target-path = "/"; //指定设备树插件的加载位置,默认我们加载到根节点下,既“target-
path =“/”
__overlay__ {
/*在此添加要插入的节点*/ //我们要插入的设备及节点或者要引用(追加)的设备树节
点放在__overlay__ {…};内
};
};
};
三、创建RGB灯的设备树插件
/dts-v1/;
/plugin/;
#include "imx6ul-pinfunc.h" // 包含引脚配置信息的头文件
#include "dt-bindings/gpio/gpio.h" // 包含 GPIO 相关的宏定义
/ {
//第一个 fragment,用于配置引脚
fragment@0 {
target = <&iomuxc>; //目标节点为 iomuxc
__overlay__ {
pinctrl_dht11: dht11grp { // 定义一个名为 dht11grp 的 pinctrl
fsl,pins = <
MX6UL_PAD_GPIO1_IO02__GPIO1_IO02 0x10b0 /*dht11*/
// 配置引脚,将 GPIO1_IO02 配置为 GPIO 模式,使用 0x10b0 功能,即
GPIO 功能
>;
};
};
};
// 第二个 fragment,用于描述设备信息和驱动程序的绑定关系
fragment@1 {
target-path = "/"; // 目标路径为根节点
__overlay__ {
dht11 { // 定义一个名为 dht11 的设备节点
#address-cells = <1>;// 地址单元格数为 1
#size-cells = <1>; // 大小单元格数为 1
pinctrl-names = "default";// 引脚控制器名称为 default
compatible = "fire,temphum_dht11";// 兼容性字符串
linux,open-drain; // 配置为开漏输出
pinctrl-0 = <&pinctrl_dht11>; // 引脚控制器为 dht11grp
dht11_pin = <&gpio1 2 GPIO_ACTIVE_HIGH>;// dht11 的引脚为 GPIO1_IO02,
使用 GPIO_ACTIVE_HIGH 模式
/*dht11 pin*/
status = "okay"; // 设备状态为正常
};
};
};
};
四、实验准备
在板卡上的部分GPIO可能会被系统占用,在使用前请根据需要修改 /boot/uEnv.txt 文件, 可注释掉某些设备树插件的加载,重启系统,释放相应的GPIO引脚。
如本节实验中,可能在鲁班猫系统中默认使能了 LED 的设备功能, 用在了LED子系统。引脚被占用后,设备树可能无法再加载或驱动中无法再申请对应的资源。
方法参考如下:
取消 LED
设备树插件,以释放系统对应LED资源,操作如下:
如若运行代码时出现“Device or resource busy”或者运行代码卡死等等现象, 请按上述情况检查并按上述步骤操作。
如出现 Permission denied
或类似字样,请注意用户权限,大部分操作硬件外设的功能,几乎都需要root用户权限,简单的解决方案是在执行语句前加入sudo或以root用户运行程序。
五、通过内核工具编译设备树插件
设备树插件与设备树一样都是使用DTC工具编译,只不过设备树编译为.dtb。而设备树插件需要编译为.dtbo。 我们可以使用DTC编译命令编译生成.dtbo,但是这样比较繁琐、容易出错。
我们可以修改内核目录/arch/arm/boot/dts/overlays下的Makefile文件, 添加我们编辑好的设备树插件。并把设备树插件文件放在和Makefile文件同级目录下。 以进行设备树插件的编译。
在内核的根目录下执行如下命令即可:
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs
生成的.dtbo位于内核根目录下的“/arch/arm/boot/dts/overlays”目录下。
本章的RGB设备树插件为“imx-fire-rgb-led-overlay.dts”, 编译之后就会在/arch/arm/boot/dts/overlays目录下生成同名的imx-fire-rgb-led.dtbo文件。得到.dtbo后,下一步就是将其加载到系统中。
六、实验结果
上一小节我们编译生成了.dtbo。.dtbo 可以被动态的加载到系统,这一小节介绍将设备树插件加入系统的方法。
6.1 uboot加载(适用野火linux开发板)
linux内核从4.4开始支持设备号树插件,支持并不代表默认开启。所以我们使用之前要配置内核开启这个功能。 如果使用的是我们提供的debian镜像(无论哪个版本)都是开启过了,无需再配置内核并重新编译。 假设使用的是debian镜像,下面介绍具体的加载步骤。
首先我们把编译好的设备树插件文件,上传到我们开发板中。
我们可以使用uboot加载编写好的设备树插件,只需完成简单的两个步骤:
1、将需要加载的.dtbo文件放入“/usr/lib/linux-image-4.19.35-imx6/overlays/”目录下。
2、将对应的设备树插件加载配置,写入uEnv.txt配置文件,系统启动过程中会自动从uEnv.txt读取要加载的设备树插件。
添加好后,我们重启开发板,并输入对应的命令可以查看设备树插件是否加载成功:
ls /sys/firmware/devicetree/base/
# 或者
ls /proc/device-tree
看到这些文件,证明已经加载成功了。
删除设备树”插件”时,我们只需将对用的插件在“/boot”目录下的uEnv.txt文件中添加#号注释即可。
从上图可以看出在uEnv.txt文件夹下有很多被屏蔽的设备树插件,这些设备树插件是烧写系统时自带的插件,为避免它们干扰我们的实验,这里把它们全部屏蔽掉。 如果要将RGB的设备树插件写入uEnv.txt也很简单,参照着写即可。书写格式为“dtoverlay=<设备树插件路径>”。 修改完成后保存、退出。执行reboot命令重启系统。正常情况下我们可以在“/proc/device-tree”找与插入的设备节点同名的文件夹。
6.2 加载RGB灯驱动
驱动程序和应用程序的使用方法与上一章完全相同,可直接使用上一章的驱动和测试应用程序完成实验,实验现象完全相同。