LV250-设备树插件的应用
怎么在 linux 系统中使用设备树插件?若笔记中有错误或者不合适的地方,欢迎批评指正 😃。
一、移植设备树插件
1. 挂载 configfs 虚拟文件系统
1.1 内核配置
configfs 虚拟文件系统是什么?这个我们后面会学习,现在主要是学习设备树插件的使用。首先我们打开 Linux 内核源码, 输入以下命令打开 menuconfig 配置界面。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig
界面打开之后,按以下菜单找到对应的配置
File systems --->
Pseudo filesystems --->
{M} Userspace-driven configuration filesystem
将这一项从 M 改为 *。修改完进行保存。
1.2 编译验证
将编译之后的内核镜像烧写到开发板上, 接着可以使用 mount 命令检查 configfs 虚拟文件系统是否挂载成功:
mount
没有 configfs 相关的内容就说明没有自动挂载上,我们可以用 mount 命令手动挂载:
mount -t configfs none /sys/kernel/config挂载成功如下图:

2. 配置内核支持设备树插件
我们打开 Linux 内核源码, 还是输入以下命令打开 menuconfig 配置界面。
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- distclean
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- imx_v6_v7_defconfig
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- menuconfig2.1 Device Tree overlay
界面打开之后,按以下菜单找到对应的配置项
Device Drivers --->
-*- Device Tree and Open Firmware support --->
[*] Device Tree overlays
2.2 Overlay filesystem support
按以下菜单找到对应的配置项
File systems --->
<*> Overlay filesystem support
-*- Overlayfs: turn on redirect directory feature by default
[*] Overlayfs: follow redirects even if redirects are turned off (NEW)
[*] Overlayfs: turn on inodes index feature by default
[*] Overlayfs: auto enable inode number mapping
[*] Overlayfs: turn on metadata only copy up feature by default
3. 移植驱动
如果已经学完了 configfs 虚拟文件系统的数据结构。其实完全可以自己编写驱动实现一个设备树插件。 但是我们没有必要重复造轮子, github 上有大神编写好的设备树插件驱动,例如 GitHub - ikwzm/dtbocfg: Device Tree Blob Overlay Configuration File System:

这就是一个驱动模块的源码,我们修改 Makefile 配置好源码的路径和编译工具,直接编译就可以了,编译完毕会得到一个 ko 文件,这个后面会用到。
4. 总结
移植设备树插件主要包括以下几个步骤 :
(1)配置内核支持挂载 configfs 虚拟文件系统。
(2)配置内核支持设备树插件。
(3)移植设备树插件驱动。
其中(1)和(2)完成后要注意重新编译内核,再把开发板中的内核更新一下。
二、设备树插件实例
1. 设备树插件中添加节点
1.1 设备树插件
1.1.1 设备树源码
我们用 imx6ull-alpha-emmc.dts 中 led 灯的这个设备节点:
/dts-v1/;
#include "imx6ull.dtsi"
#include "imx6ull-alpha-emmc.dtsi"
/ {
model = "Freescale i.MX6 UlltraLite ALPHA EMMC Board";
compatible = "fsl,imx6ull-alpha-emmc", "fsl,imx6ull";
//把这个节点删掉,移到设备树插件中
sdev_led {
#address-cells = <1>;
#size-cells = <1>;
compatible = "sdev_led";
status = "okay";
reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */
0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */
0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */
0X0209C000 0X04 /* GPIO1_DR_BASE */
0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
};
};
&clks {
assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>;
assigned-clock-rates = <320000000>;
};我们写一个设备树插件 imx6ull-alpha-emmc-overlay.dts 如下:
/dts-v1/;
/plugin/;
&{/} {
overlay_node{
sdev_led {
#address-cells = <1>;
#size-cells = <1>;
compatible = "sdev_led";
status = "okay";
reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */
0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */
0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */
0X0209C000 0X04 /* GPIO1_DR_BASE */
0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
};
};
};我们把主设备树中的 sdev_led 节点移动到设备树插件中去。需要注意的是,这样在设备树插件中添加节点的操作似乎并不会自动取生成 platform_device,所以如果用的平台设备驱动的话可能会有问题。
1.1.2 编译设备树插件
我们使用以下命令进行编译设备树插件:
./dtc -I dts -O dtb imx6ull-alpha-emmc-overlay.dts -o imx6ull-alpha-emmc-overlay.dtbo设备树的编译可以看 demo 中的 makefile,它包含了一些其他的设备树和头文件,所以编译会复杂一点。
1.2 更新内核和设备树
我们按照前面的更新内核和设备树,然后重启设备。然后将 imx6ull-alpha-emmc-overlay.dtbo 和 dtbocfg.ko 放到开发板中。
1.3 环境准备
1.3.1 configfs 文件系统挂载
在内核根文件系统中,有一个文件 /proc/filesystems , 它表示当前内核支持的文件系统,通常是编入内核的文件系统类型,但也可以通过模块加入新的类型。可以通过命令 cat /proc/filesystems 检查 configfs 是否支持。 支持的话就会有如下信息 :
不支持的话可以看前面的笔记对内核进行配置。支持之后,我们可以用 mount 命令看一下有没有挂载上,若是没挂载的话,后面加载驱动是不会生成对应的目录的。可以使用以下命令挂载:
mount -t configfs none /sys/kernel/config1.3.2 加载 dtbocfg.ko
我们通过以下命令加载:
insmod dtbocfg.ko会有如下打印信息:

加载成功应该会生成 /sys/kernel/config/device-tree/overlays 目录:

要是没有的话,就注意用 mount 看一下是不是成功挂载了 configfs。
1.4 设备树插件测试
- (1)查看未添加设备树插件的时候的设备树情况
ls /proc/device-tree/
- (2)我们进入 /sys/kernel/config/device-tree/overlays 目录
cd /sys/kernel/config/device-tree/overlays- (3)新建一个 dtbo_demo 目录
mkdir dtbo_demo
然后进入这个目录就会发现这个目录下自动生成了两个文件:dtbo 和 status。
- (4)将设备树插件的内容写入到 dtbo 中
cd /sys/kernel/config/device-tree/overlays/dtbo_demo
cat /drivers_demo/imx6ull-alpha-emmc-overlay.dtbo > dtbo- (5)使能 dtbo
cd /sys/kernel/config/device-tree/overlays/dtbo_demo
echo 1 > status- (6)查看设备树插件加载的节点
ls /proc/device-tree/overlay_node/
- (7)删除使用 dtbo 修改的节点
cd /sys/kernel/config/device-tree/overlays
rmdir dtbo_demo
# 或者
cd /sys/kernel/config/device-tree/overlays/dtbo_demo
echo 0 > status然后我们再查看一下 /proc/device-tree,就会发现没有 overlay_node 节点了:

2. 修改后设备树节点属性
2.1 设备树插件
我们用 imx6ull-alpha-emmc.dts 中 led 灯的这个设备节点:
/dts-v1/;
#include "imx6ull.dtsi"
#include "imx6ull-alpha-emmc.dtsi"
/ {
model = "Freescale i.MX6 UlltraLite ALPHA EMMC Board";
compatible = "fsl,imx6ull-alpha-emmc", "fsl,imx6ull";
sdev_led {
#address-cells = <1>;
#size-cells = <1>;
compatible = "sdev_led";
//status = "disable";
reg = < 0X020C406C 0X04 /* CCM_CCGR1_BASE */
0X020E0068 0X04 /* SW_MUX_GPIO1_IO03_BASE */
0X020E02F4 0X04 /* SW_PAD_GPIO1_IO03_BASE */
0X0209C000 0X04 /* GPIO1_DR_BASE */
0X0209C004 0X04 >; /* GPIO1_GDIR_BASE */
};
};
&clks {
assigned-clocks = <&clks IMX6UL_CLK_PLL3_PFD2>;
assigned-clock-rates = <320000000>;
};我们写一个设备树插件 imx6ull-alpha-emmc-overlay.dts 如下:
/dts-v1/;
/plugin/;
//修改设备树节点属性的 demo
/{
fragment@0 {
target-path = "/alpha/sdev_led";
__overlay__ {
overlay_node{
status = "okay";
};
};
};
};我们把主设备树中的 sdev_led 节点移动到设备树插件中去。需要注意的是,这样在设备树插件中添加节点的操作似乎并不会自动取生成 platform_device,所以如果用的平台设备驱动的话可能会有问题。
2.2 开发板测试
- (1)加载设备树插件之前节点的情况

- (2)加载设备树插件之前加载驱动

看到会报一个状态读取失败,然后我们运行测试 demo,发现可以正常操作,这个应该是因为我内部判断了,但是没有返回错误的原因,不过这里不影响测试。测完卸载驱动。
- (3)加载设备树插件
# 挂载 configfs 文件系统
mount -t configfs none /sys/kernel/config
# 加载设备树插件驱动
insmod dtbocfg.ko
# 创建目录
cd /sys/kernel/config/device-tree/overlays
mkdir dtbo_demo
# 将设备树插件的内容写入到 dtbo 中
cd /sys/kernel/config/device-tree/overlays/dtbo_demo
cat /drivers_demo/imx6ull-alpha-emmc-overlay.dtbo > dtbo
# 使能 dtbo
cd /sys/kernel/config/device-tree/overlays/dtbo_demo
echo 1 > status
可以看到这里生成了一个 overlay_node 目录,里面包含了 name 和 status 属性。
- 重新加载设备的驱动
insmod sdriver_demo.ko
发现还是报错的,这是因为 status 属性并不是在 /alpha/sdev_led/status,而是 alpha/sdev_led/overlay_node/status 所以获取的时候出现了问题,这个大概了解就可以了,后续使用设备树插件的话需要注意这个事情。