tag 标签: 设备树插件

相关博文
  • 热度 3
    2024-3-31 09:22
    881 次阅读|
    1 个评论
    前言 像我这样很多学习驱动的同学都会想一个问题:学了这个能干嘛?学了那个能干嘛? 姑且找找网络上开源的项目,找找,看看,还是一脸懵。因为开源只提供源码和大致介绍下做什么和有什么。而面对于基础开发者的博客还是很少的。甚至有的博主只是放一些定义,丢几个结构体的注释就完结。我曾经就是通过查缺补漏才形成了一个完整的项目框架。 借此,我打算撰写一套驱动的开发流程,从硬件调试到驱动框架搭建,到系统调用验证。 因为AI的盛行,自动驾驶,人脸识别等应用都成了市场的领航者。而他们用到的最多的基础配件都是SOC和摄像头模块等,所以我后面将针对摄像头的开发流程撰写一整套系列教程。希望可以供小白参考学习,也期待大佬进行点评。 不说废话了,接下来请看我的展示。 在开始之前有必要说明下硬件环境: 主芯片:瑞芯微的rv1126 摄像头:ov5640 内核版本:Linux 4.19 市面大多数摄像头都是使用I2C进行配置和初始化的,这里的I2C有时也叫SCCB,不过基本时序差不多的,一般不做区分。 一、确定I2C硬件连接正确 硬件接线:先将摄像头的i2c接到主板上的对应I2C上,然后接上电源,我的OV5640模块是接5V和3.3V 使用i2c-tool工具查看摄像头的i2c地址,下面介绍有两种方式 第一种 命令行输入 i2cdetect -y 1 //“1”代表I2C编号,一般一个SOC有很多I2C,如果接的是I2C0,这里就写0 得到如下结果,3c则是当前摄像头的i2c设备地址,这里先说明一下,如果3C这个地址被驱动使用,则显示UU 试试得到设备的各个寄存器的值,使用如下命令 i2cdump -f -y 1 0x3c 将得到如下结果 有这两个基本够用了,如果想了解更多,则可以看看如下文章 Linux系统下i2c工具 i2c-tool 的使用 第二种 查看数据手册 看到这里就有人有疑问了,为啥这里的设备地址是78,而第一种方法得到的是3C。这个疑问我有个文章写过 ( I2C简单实验之LT6911UXC读取 ChipID ),大家可以看下,我也贴在这 然后咱们就可以使用i2c-tool进行调试了。 二、I2C驱动基本框架的搭建 我曾在 I2C简单实验之LT6911UXC读取ChipID 搭建过一个基本框架,这里再给大家分享一个比较简单的框架 static int ov5640_probe(struct i2c_client *client, const struct i2c_device_id *id) { dev_info(dev,"\r\n this function is %s",__FUNCTION__);//封装好的打印api,其实就是经过一番操作最后调用printk函数 return 0; } static int ov5640_probe(struct i2c_client *client, const struct i2c_device_id *id) { dev_info(dev,"\r\n this function is %s",__FUNCTION__); return 0; } const struct i2c_device_id ov5640_id = { { .compatible = "ovti,ov5640" }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, ov5640_of_match); static struct i2c_driver ov5640_i2c_driver = { .driver = { .of_match_table = of_match_ptr(ov5640_of_match), .name = "ov5640", }, .probe = ov5640_probe, .remove = ov5640_remove, .id_table = ov5640_id, }; //这里是linux封装好的api,其中已经包含了init ,exit以及I2C设备的注册过程。 module_i2c_driver(ov5640_i2c_driver); MODULE_DESCRIPTION("Omnivision OV5640 Camera Driver"); MODULE_AUTHOR("LY"); MODULE_LICENSE("GPL v2"); 代码阅读顺序 按照以上的阅读顺序,有一点基础的同学肯定一目了然。这里就不做过多说明。 三、设备树插件的使用 设备树插件的原理和基本运用我在早期的文章已经写过: 设备树插件_configfs学习笔记 这里贴一下使用方式,毕竟原理大致了解了就行了。使用之前先下载好驱动 链接: https://pan.baidu.com/s/1uuwqCwlZNkSLorEWTmkFrQ 提取码: 5dbv 加载方式跟普通驱动加载方式一样,俩个命令加载insmod和卸载rmmod 1.编写dts文件 /dts-v1/; /plugin/; /{ fragment@0{ target= ; __overlay__{ ov5640:ov5640@3c{ status="okay"; compatible = "ovti,ov5640"; reg= ; }; }; }; 2. 编译 编译的方式和编译设备树是一样的 sdk/kernel/scripts/dtc/dtc -I dts -O dtb overlay.dts -o overlay.dtbo 反编译为 sdk/kernel/scripts/dtc/dtc -I dtb -O dts overlay.dtbo -o overlay.dts 3. 使用 通过第三节加载相关驱动后,进入设备树插件相关configfs中 cd /sys/kernel/config/device-tree/overlays 创建一个内核对象 mkdir test 使用命令将dtbo写入到内核对象 /test/dtbo 使能dtbo /test/status 通过以下方式将能看到加载的节点 ls /proc/device-tree/i2c@ff510000/ 如图所示 四、加载之前编写好的i2c驱动 加载驱动之前需要先编译成KO文件,可以使用如下模板 obj-m += .o KDIR:= PWD?=$(shell pwd) all: make -C $(KDIR) M=$(PWD) modules clean: rm -f *.ko *.o *.mod.o *.mod.c *.symvers *.order 编译命令 make 加载 insmod .KO 正确执行了probe函数,证明我们的驱动和设备树插件都使用的完全正确。 原文链接
  • 热度 5
    2023-11-7 14:44
    690 次阅读|
    0 个评论
    设备树插件定义和作用 设备树插件(Device Tree Overlay) 是一种用于设备树(Device Tree)的扩展机制。 设备树插件允许在运行时动态修改设备树结构的内容,以便添加、修改或删除设备节点和属性。嵌入式驱动开发者将不用再重新启动系统的情况下对硬件进行配置修改。 在早期的时候,每个嵌入式驱动开发者都因为引入了设备树而感到兴奋和激动。因为这使得开发者不用再写两套代码,且代码移植性也变得非常灵活。 然而设备树还有个不太方便的地方,就是每次配置完设备树,还得重新编译后烧录到板卡,重启系统才能完成配置。这使得驱动开发者非常头疼,有可能因为更改个GPIO属性都得重新过一遍烧录过程。所以在linux4.4以后引入了动态设备树。设备树插件是实现的方式。 一、预备知识 如果不想关注原理,只是简单使用。可以跳过本节。 设备树插件是基于configfs实现的。所以本节介绍configfs的相关知识。 1. 什么是configfs 在kernel目录下的Documentation/filesystems/configfs有官方说明文档configfs.txt 。其中是这样说明的: configfs是与sysfs功能相反的基于ram的文件系统。sysfs是基于文件系统查看内核对象,configfs是基于文件系统管理内核对象或配置项 对于sysfs,一个对象是在内核中创建和删除的。内核控制着sysfs表示的生命周期,和sysfs只是一个窗口而已。而configfs配置项表示的生命周期完全由用户空间驱动,内核模块支持这样项目的必须作出响应。 它可以被编译成模块或者编入内核 2. 如何编写 认识相关结构体 结构体相关性 编写-创建一个子系统并创建group 通过编译为KO文件并加载到开发板上,可以在/sys/kernel/config下查看到一个名为myconfig的group 编写-在子系统group中创建group 通过编译为KO文件并加载到开发板上,可以在/sys/kernel/config/myconfig下查看到一个名为mygroup的group 编写-在group中创建item 通过编译为KO文件并加载到开发板上,可以在/sys/kernel/config/myconfig/mygroup下使用mkdir创建group,使用rmdir可以删除相关group 编写-实现读写属性 通过编译为KO文件并加载到开发板上,可以在/sys/kernel/config/myconfig/mygroup下使用mkdir创建group,在此group下将会有write和read两个属性。可以通过echo对write写相关参数,通过cat read查看参数值 二、内核配置 若实现设备树插件,还需要对内核进行相关配置 以上操作后,编译烧录到开发板。将在/sys/kernel下看到config目录,说明自动挂载上了。 如果不能自动挂载,则使用 mount -t configfs none /sys/kernel/config 接着配置内核支持设备树插件 三、移植驱动 关于设备树插件的相关驱动,我是通过网上下载得到的,就直接编译移植了(可以通过insmod加载KO方式也可以直接编译进内核) 相关文件放入如下网盘: 链接: https://pan.baidu.com/s/1uuwqCwlZNkSLorEWTmkFrQ 提取码: 5dbv 移植过程为一般驱动编译加载一样,这里不赘述。移植完成后将在sys/kernel/config下查看到一个名为device-tree的文件夹 四、设备树插件语法 1. 插件头部声明 /dts-v1/; /plugin/; 2. 插件节点名称用于定义要添加、修改或删除的设备节点以及属性 有如下三种表示形式(以rk3568的485节点为例): 五、编译与使用 1. 编译 编译的方式和编译设备树是一样的 sdk/kernel/scripts/dtc/dtc -I dts -O dtb overlay.dts -o overlay.dtbo 反编译为 sdk/kernel/scripts/dtc/dtc -I dtb -O dts overlay.dtbo -o overlay.dts 2. 使用 通过第三节加载相关驱动后,进入设备树插件相关configfs中 cd /sys/kernel/config/device-tree/overlays 创建一个内核对象 mkdir test 使用命令将dtbo写入到内核对象 /test/dtbo 使能dtbo /test/status 通过以下方式将能看到加载的节点 ls /proc/device-tree/rk-485-ctl/overlay_node/