Linux驱动开发实战(六):设备树升级!插件设备树点灯!
Linux驱动开发实战(六):设备树升级!插件设备树点灯!
文章目录
- Linux驱动开发实战(六):设备树升级!插件设备树点灯!
- 1. 为什么需要插件设备树
- 传统设备树的局限性
- 插件设备树的优势
- 2. 传统设备树与插件设备树的区别
- 3. 插件设备树的语法
- 基本结构
- 关键语法元素
- 4. 实验步骤
- 修改原本的设备树(原来没有rgb节点的可以不改)
- 编译插件设备树
- 方法一:内核运行状态加载
- 方法二:uboot加载(强推)
- 总结
1. 为什么需要插件设备树
在嵌入式Linux开发中,设备树(Device Tree)已经成为描述硬件平台的标准方式。然而,传统的设备树存在一些局限性,尤其是在需要动态修改系统硬件配置的场景下。这就是插件设备树(Device Tree Overlay)出现的原因。
传统设备树的局限性
传统设备树在系统启动时一次性加载,描述了整个系统的硬件配置。这种方式存在以下问题:
- 静态性:一旦系统启动,设备树就被锁定,无法动态修改
- 重启需求:任何硬件配置的变更都需要修改设备树文件并重启系统
- 不适合热插拔:对于可热插拔设备,传统设备树难以支持实时响应
- 冗余配置:为了支持多种可能的硬件配置,往往需要在设备树中包含所有可能的配置
插件设备树的优势
插件设备树解决了上述问题,它具有以下优势:
- 动态加载:可以在系统运行时动态加载和卸载硬件描述
- 无需重启:修改硬件配置无需重启整个系统
- 热插拔支持:可以实时响应硬件变化
- 模块化配置:可以根据实际需求选择性地加载硬件描述
- 灵活性:支持定制化的硬件配置而无需修改核心设备树
2. 传统设备树与插件设备树的区别
特性 | 传统设备树 | 插件设备树 |
---|---|---|
加载时机 | 系统启动时 | 系统运行时 |
修改方式 | 静态(需重启) | 动态(无需重启) |
文件格式 | .dtb (编译后) | .dtbo (编译后) |
灵活性 | 低 | 高 |
适用场景 | 固定硬件配置 | 可变硬件配置,热插拔设备 |
实现复杂度 | 相对简单 | 相对复杂 |
3. 插件设备树的语法
插件设备树有其特定的语法结构,主要包括以下几个关键部分:
基本结构
/dts-v1/;
/plugin/;
/ {
fragment@n {
target = <&目标节点>;
overlay {
/* 要添加的节点和属性 */
};
};
};
下面以rgb插件设备树为例
/dts-v1/; // 设备树版本声明
/plugin/; // 标记这是一个设备树插件(overlay)文件
/ { // 根节点
fragment@0 { // 设备树片段,索引为0
target-path = "/"; // 目标路径,指定覆盖将应用到根节点
__overlay__ { // 覆盖内容开始
/* bar peripheral */
rgb_led{ // 创建一个rgb_led节点
#address-cells = <1>; // 地址单元格数量
#size-cells = <1>; // 大小单元格数量
compatible = "fire,rgb_led"; // 兼容性字符串,用于匹配驱动
ranges; // 子地址空间与父地址空间直接映射
// 红灯子节点
rgb_led_red@0x020C406C{
// 寄存器映射,包含5组地址和大小
reg = <0x020C406C 0x00000004
0x020E006C 0x00000004
0x020E02F8 0x00000004
0x0209C000 0x00000004
0x0209C004 0x00000004>;
status = "okay"; // 启用状态
};
// 绿灯子节点
rgb_led_green@0x020C4074{
reg = <0x020C4074 0x00000004
0x020E01E0 0x00000004
0x020E046C 0x00000004
0x020A8000 0x00000004
0x020A8004 0x00000004>;
status = "okay";
};
// 蓝灯子节点
rgb_led_blue@0x020C4074{
reg = <0x020C4074 0x00000004
0x020E01DC 0x00000004
0x020E0468 0x00000004
0x020A8000 0x00000004
0x020A8004 0x00000004>;
status = "okay";
};
};
};
};
};
关键语法元素
/dts-v1/
: 设备树版本声明/plugin/
: 标记这是一个插件设备树,允许引用未定义的节点fragment@n
: 定义一个覆盖片段,n
是一个索引数字target
: 指定覆盖的目标节点,有两种形式:target = <&节点标签>
: 通过标签引用目标节点target-path = "节点路径"
: 通过路径引用目标节点
__overlay__
: 定义要覆盖/添加的内容
4. 实验步骤
在本实验中,我们通过修改之前写过的设备树基础上加插件设备树,我们将展示如何使用插件设备树来动态添加LED设备。
修改原本的设备树(原来没有rgb节点的可以不改)
编译原本的设备树
配置内核
make ARCH=arm CROSS_COMPILE=arm-linux-gnueabihf- npi_v7_defconfig
编译dts
sudo make ARCH=arm -j4 CROSS_COMPILE=arm-linux-gnueabihf- dtbs
传到共享文件夹
sudo cp arch/arm/boot/dts/imx6ull-mmc-npi.dtb /../home/embedfire/workdir/imx6ull-mmc-npi.dtb
cd /usr/lib/linux-image-4.19.35-imx6/ 这里是开发板设备树的路径
将共享文件夹的设备树dtb文件替换掉开发板里面的dtb文件
sudo cp /mnt/imx6ull-mmc-npi.dtb /usr/lib/linux-image-4.19.35-imx6/imx6ull-mmc-npi.dtb
重启开发板
ls /proc/device-tree
命令查看是否增加了节点
发现原本的rgb_led是已经没有了,现在开始插件设备树的工作
编译插件设备树
这里的插件设备树就是上面rgb代码示例
编译 dts 为 dtbo
./../../../../home/pi/build/scripts/dtc/dtc -I dts -O dtb -o rgb.dtbo led.dts
把rgb.dtbo复制到共享文件夹
方法一:内核运行状态加载
先在/usr/lib/linux-image-4.19.35-imx6/overlays/目录下创建xxx文件夹
发现这个方法好像设备树没有加载出来
可是overlays的文件夹只有在这个目录下
看了官方的文档发现,应该是内核版本问题但是没关系,我们可以采用另一种方法
方法二:uboot加载(强推)
先把rgb.dtbo文件复制到/usr/lib/linux-image-4.19.35-imx6/overlays下
然后在/boot/uEnv.txt修改添加
我们重启开发板
发现是有的这个驱动的
我们加载驱动然后使用qt应用程序(qt程序点灯)去点灯是没有问题的
总结
插件设备树极大地提高了Linux嵌入式系统的灵活性和可扩展性。通过允许动态修改硬件描述,它使得系统能够适应更广泛的使用场景,特别是在需要热插拔和动态配置的应用中。掌握插件设备树的开发,将使您的嵌入式Linux系统开发能力更上一层楼。