Linux驱动开发实战(六):设备树升级!插件设备树点灯!

Linux驱动开发实战(六):设备树升级!插件设备树点灯!



1. 为什么需要插件设备树

在嵌入式Linux开发中,设备树(Device Tree)已经成为描述硬件平台的标准方式。然而,传统的设备树存在一些局限性,尤其是在需要动态修改系统硬件配置的场景下。这就是插件设备树(Device Tree Overlay)出现的原因。

传统设备树的局限性

传统设备树在系统启动时一次性加载,描述了整个系统的硬件配置。这种方式存在以下问题:

  1. 静态性:一旦系统启动,设备树就被锁定,无法动态修改
  2. 重启需求:任何硬件配置的变更都需要修改设备树文件并重启系统
  3. 不适合热插拔:对于可热插拔设备,传统设备树难以支持实时响应
  4. 冗余配置:为了支持多种可能的硬件配置,往往需要在设备树中包含所有可能的配置

插件设备树的优势

插件设备树解决了上述问题,它具有以下优势:

  1. 动态加载:可以在系统运行时动态加载和卸载硬件描述
  2. 无需重启:修改硬件配置无需重启整个系统
  3. 热插拔支持:可以实时响应硬件变化
  4. 模块化配置:可以根据实际需求选择性地加载硬件描述
  5. 灵活性:支持定制化的硬件配置而无需修改核心设备树

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";
                };
            };
        };
    };
};

关键语法元素

  1. /dts-v1/: 设备树版本声明
  2. /plugin/: 标记这是一个插件设备树,允许引用未定义的节点
  3. fragment@n: 定义一个覆盖片段,n是一个索引数字
  4. target: 指定覆盖的目标节点,有两种形式:
    • target = <&节点标签>: 通过标签引用目标节点
    • target-path = "节点路径": 通过路径引用目标节点
  5. __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系统开发能力更上一层楼。

### VxWorks 设备树Linux 设备树的区别比较 #### 1. 架构设计哲学 Linux设备树 (Device Tree, DT) 是一种描述硬件的数据结构,旨在分离硬件配置和操作系统内核代码。这使得同一份内核可以在不同硬件平台上运行而无需修改源码[^1]。 相比之下,VxWorks 中的设备树概念并不像 Linux 那样成熟和完善。VxWorks 使用的是基于 C 结构体的方式定义硬件资源,在某些版本中引入了类似于 Device Tree 的机制来简化硬件抽象层(HAL),但这主要服务于特定功能模块而非整体架构的一部分[^3]。 #### 2. 表达方式 Linux 设备树采用 `.dts` 文件格式编写,这是一种人类可读的文字形式,易于维护和扩展。它支持复杂的嵌套关系表达,并且可以通过编译工具链转换成二进制格式供启动加载程序解析[^2]。 而在 VxWorks 中,则更多依赖于预处理器宏定义或静态初始化列表的形式完成类似的任务。虽然也存在一些尝试模仿 Device Tree 功能特性的实现方案,但这些通常局限于个别组件内部而不具备通用性[^4]。 #### 3. 工具链支持程度 对于 Linux 来说,围绕着设备树已经形成了完整的生态系统,包括但不限于 dtc 编译器、各种调试辅助工具等。开发者能够方便地创建、编辑甚至动态更新 DTS/DTSI 文件。 相反,由于缺乏统一标准的支持,针对 VxWorks 平台上的类 Device Tree 解决方案往往缺少相应的配套软件设施,给实际应用带来不便之处[^5]。 #### 4. 社区活跃度与发展潜力 得益于开源社区的强大推动力量,有关 Linux 设备树的技术文档非常详尽全面;同时也有大量现成案例可供学习借鉴。随着 ARM 架构服务器市场的崛起,未来这一领域还将持续获得更多的关注和发展机遇。 然而,尽管 Wind River Systems 不断努力改进其产品特性集,但由于市场份额相对较小等原因,关于 VxWorks 类似技术的研究进展较为缓慢,相关资料也比较稀缺。 ```python # Python 示例用于说明两种环境下的区别(仅示意) linux_device_tree = """ /dts-v1/; /plugin/; / { compatible = "example-board"; }; """ vxworks_like_structure = [ {"name": "emif", "type": "memory_controller"}, {"name": "uart0", "baseAddr": 0x80000000} ] ```
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值