Linux驱动-单总线-DS18b20-驱动设备树配置-GPIO复用
提示DS18B20驱动配置设备树文章目录前言一、参考资料二、 原理图分析-配置设备树1、字符设备驱动框架-再分析-需求描述2、地板原理图简要分析DS18b20 引脚底板原理图简要分析实物图20pin的原理图pinctrl 引脚复用-可复用的引脚配置图3、配置设备树配置gpio1. ds18b20_gpio: gpio0_b02. compatible ds18b20;3. ds18b20-gpios gpio0 RK_PB0 GPIO_ACTIVE_HIGH;4. pinctrl-names default;5. pinctrl-0 ds18b20_gpio_ctrl;配置pinctrl1. pinctrl2. ds18b20_gpio3. ds18b20_gpio_ctrl: ds18b20-gpio-ctrl4. rockchip,pins 0 RK_PB0 RK_FUNC_GPIO pcfg_pull_none;两段配置的关系核心逻辑三、源码-原理分析-验证1、源码说明-加载驱动2、验证设备树配置的gpio节点是否生成 cd /proc/device-tree/3、检查设备树是否加载进入内核-ls -l /proc/device-tree/gpio0_b04、验证申请的设备号-cat /proc/devices5、验证申请的字符设备类-ls /sys/class/-ls /sys/class/sensors6、验证申请的字符设备 -ls -l /dev/-ls -l /dev/ds18b20总结前言这里还是结合前面的知识点前面文章已经讲解、总结、归纳了驱动框架、字符驱动框架里面还及到平台总线知识点。接下来就是设备树知识点。很早以前我们学习每个知识点都是 加载驱动、按照我们的demo 流程来进行知识点验证前面的温度传感器-DS18B20驱动框架编写 、温度传感器-DS18B20字符设备驱动框架 就是写了框架其实驱动还没有加载成功的比如平台总线驱动还没有识别到没有调用probe函数。一、参考资料这里我们把以前的相关知识点拿到这里规整一下总线设备知识点platform总线注册流程分析在总线下注册设备及设备注册流程分析Linux驱动之platform 总线设备注册流程分析总线驱动相关知识点驱动-在自定义总线上创建驱动-分析驱动注册流程总线、字符设备、相关知识点讯为:第十四期 | 单总线RK3568驱动指南第十四篇 单总线-第158章DS18B20编写字符设备驱动框架涉及到核心知识点alloc_chrdev_region // 动态申请字符设备号驱动-申请字符设备号涉及到核心知识点cdev_init //字符设备初始化 cdev_initcdev_add //字符设备的注册 - cdev_add驱动-注册字符设备涉及到核心知识点class_create() - 创建设备类device_create() - 创建设备节点驱动-创建设备节点gpio-pinctrl知识点GPIO 控制和操作-使用命令通过sysfs文件系统控制GPIO使用C程序通过sysfs文件系统控制gpio操作寄存器来控制GPIO-点亮LED灯将原理图中的一个引脚复用为gpio功能驱动GPIO-获取单个gpio描述符Linux驱动-GPIO基本函数apiLinux驱动-GPIO子系统与pinctrl子系统相结合温度传感器-DS18B20驱动框架编写温度传感器-DS18B20字符设备驱动框架其实我们这里用到的DS18B20外设然后整个链路把知识点串联起来而已之前相关知识点都学过的。 如果忘记 强烈建议自己再去补一补基础的东西忘记了不行的。二、 原理图分析-配置设备树1、字符设备驱动框架-再分析-需求描述在字符驱动设备框架温度传感器-DS18B20字符设备驱动框架中 我们对驱动源码进行了详细的分析的。但是我们没做什么我们只是写了框架平台总线设备并没有加载成功也就是说probe函数这个驱动的灵魂当设备树中compatible ds18b20的设备与驱动匹配成功时内核才会自动调用probe完成字符设备的完整注册流程。所以 我们要做的是什么配置gpio: 驱动层配置一个gpio给DS18b20外设来用配置pinCtrl: 但是系统里面默认的pin点可能是配置了其它的功能、或者 默认情况下不是gpio功能。 那么就需要用pin-ctrl进行引脚复用到GPIO功能这样外设才能正常使用匹配到gpio,实现2、地板原理图简要分析DS18b20 引脚DS18B20引脚如下这里DC 就是信号引脚需要一个GPIO来连接的那么就在主板上面找一个GPIO不就行了嘛。底板原理图简要分析参考资料topeet_rk3568_main_v1_7.pdf底板原理图实物图先看实物图 打算用这个20pin脚里面的GPIO0_B0的拐角作为GPIO控制来做DS18B20的信号连接。20pin的原理图在topeet_rk3568_main_v1_7.pdf底板原理图 里面去找那么就去找J39 的原理图如下我们看到了拐角17 对应的就是GPIO0_B0的拐角全称DVP_PWREN0_H_GPIO0_B0pinctrl 引脚复用-可复用的引脚配置图那么这个引脚DVP_PWREN0_H_GPIO0_B0我想用来做GPIO来用那么就要去配置pinctrl引脚复用继续看 引脚复用继续在topeet_rk3568_main_v1_7.pdf底板原理图 里面去找如下说明引脚DVP_PWREN0_H_GPIO0_B0可以复用的功能有CLK32K_IN 、CLK32K_OUTO、PCIE30X2_BUTTONRSTn、GPIO0_B03、配置设备树文件路径kernel/arch/arm64/boot/dts/rockchip/rk3568/rk3568-evb1-ddr4-v10.dtsi参考文档将原理图中的一个引脚复用为gpio功能-Linux驱动-GPIO子系统与pinctrl子系统相结合要求就是当有GPIO复用功能需求不应该无从下手应该很熟练的去配置。配置gpio在根节点中配置/{.......................ds18b20_gpio:gpio0_b0{compatibleds18b20;ds18b20-gpiosgpio0 RK_PB0 GPIO_ACTIVE_HIGH;pinctrl-namesdefault;pinctrl-0ds18b20_gpio_ctrl;statusokay;};}1. ds18b20_gpio: gpio0_b0ds18b20_gpio节点标签方便其他地方引用gpio0_b0节点名字随便写建议和引脚对应2. compatible “ds18b20”;驱动匹配字符串告诉内核这个设备要去找名字叫 ds18b20 的驱动来匹配、接管内核就是靠这个字段找到对应驱动3. ds18b20-gpios gpio0 RK_PB0 GPIO_ACTIVE_HIGH;这是最重要的一行指定 DS18B20 接在哪个 GPIO但是就是一个gpio描述符gpio0使用 GPIO0 控制器RK_PB0GPIO0_B0 引脚GPIO_ACTIVE_HIGH高电平有效单总线必须这样4. pinctrl-names “default”;定义引脚状态名称default 表示默认工作状态5. pinctrl-0 ds18b20_gpio_ctrl;关联引脚配置意思是去引用 pinctrl 里定义的 ds18b20_gpio_ctrl 引脚配置这是两段配置之间的 “桥梁”配置pinctrl在pinctrl 节点中配置pinctrl 相关信息pinctrl{.............ds18b20_gpio{ds18b20_gpio_ctrl:ds18b20-gpio-ctrl{rockchip,pins0 RK_PB0 RK_FUNC_GPIOpcfg_pull_none;};};}1. pinctrl引用 RK3568 的引脚控制器所有引脚复用、上下拉、驱动能力都在这里配置2. ds18b20_gpio给这组引脚配置起个名字随便写3. ds18b20_gpio_ctrl: ds18b20-gpio-ctrl这是真正被引用的配置节点第一段 pinctrl-0 就是引用它4. rockchip,pins 0 RK_PB0 RK_FUNC_GPIO pcfg_pull_none;参数功能参数 10GPIO 组号GPIO0参数 2RK_PB0引脚编号GPIO0_B0参数 3RK_FUNC_GPIO功能模式普通 GPIO 输入输出模式不是 I2C、UART、PWM 等复用功能参数 4pcfg_pull_none上下拉配置pull_none 无上下拉;DS18B20 必须外部接 4.7k 上拉电阻内部不能开上下拉两段配置的关系核心逻辑第一段设备节点 pinctrl-0ds18b20_gpio_ctrl↓ 引用 第二段pinctrl 引脚配置 ds18b20_gpio_ctrl{...}第一段告诉内核 “这是什么设备、用哪个引脚”第二段告诉内核 “这个引脚要怎么配置GPIO 模式、无上下拉”。核心点小结属性名称作用compatible匹配驱动ds18b20-gpios指定引脚pinctrl-0关联引脚配置rockchip,pins设置引脚为 GPIO 模式 无上下拉三、源码-原理分析-验证1、源码说明-加载驱动这里不演示源码用的是上一节中一摸一样的源码 温度传感器-DS18B20字符设备驱动框架 源码如下#includelinux/init.h#includelinux/module.h#includelinux/platform_device.h#includelinux/of.h#includelinux/fs.h#includelinux/cdev.h#includelinux/kdev_t.h#includelinux/slab.h#includelinux/gpio.h#includelinux/gpio/consumer.h#includelinux/delay.hstruct ds18b20_data{dev_t dev_num;// 什么一个字符设备号就是设备号struct cdev ds18b20_cdev;//声明一个字符设备structclass*ds18b20_class;//声明一个设备类struct device*ds18b20_device;//声明一个设备//device};intds18b20_open(struct inode*inode,struct file*file){return0;}ssize_tds18b20_read(struct file*file,char__user*buf,size_t size,loff_t*offs){return0;}intds18b20_release(struct inode*inode,struct file*file){return0;}struct file_operations ds18b20_fops{.opends18b20_open,.readds18b20_read,.releaseds18b20_release,.ownerTHIS_MODULE,};struct ds18b20_data*ds18b20;intds18b20_probe(struct platform_device*dev){intret;printk(This is probe \n);ds18b20kzalloc(sizeof(*ds18b20),GFP_KERNEL);if(ds18b20NULL){printk(kzalloc error \n);gotoerror_0;}// 第一步骤:申请设备号retalloc_chrdev_region(ds18b20-dev_num,0,1,myds18b20);//通过动态方式进行设备号注册if(ret0){printk(alloc_chrdev_region error \n);ret-EAGAIN;gotoerror_1;}// 第二步字符设备初始化 cdev_initcdev_init(ds18b20-ds18b20_cdev,ds18b20_fops);// 使用 cdev_init()函数初始化 cdev_test 结构体 并链接到cdev_test_ops 结构体ds18b20-ds18b20_cdev.ownerTHIS_MODULE;// 将 owner 字段指向本模块 可以避免在模块的操作正在被使用时卸载该模块// 第三步字符设备的注册 - cdev_addretcdev_add(ds18b20-ds18b20_cdev,ds18b20-dev_num,1);// 使用 cdev_add()函数进行字符设备的添加// 第四步class_create() - 创建设备类ds18b20-ds18b20_classclass_create(THIS_MODULE,sensors);//使用class_create进行类的创建类名称为sensorsif(IS_ERR(ds18b20-ds18b20_class)){printk(class_create error\n);retPTR_ERR(ds18b20-ds18b20_class);gotoerror_2;}// 第五步创建device device_create() - 创建设备节点ds18b20-ds18b20_devicedevice_create(ds18b20-ds18b20_class,NULL,ds18b20-dev_num,NULL,ds18b20);//使用device_create进行设备的创建设备名称为device_testif(IS_ERR(ds18b20-ds18b20_device)){printk(device_create error\n);retPTR_ERR(ds18b20-ds18b20_device);gotoerror_3;}return0;//error_4:// device_destroy(ds18b20-ds18b20_class, ds18b20-dev_num);error_3:class_destroy(ds18b20-ds18b20_class);error_2:cdev_del(ds18b20-ds18b20_cdev);unregister_chrdev_region(ds18b20-dev_num,1);error_1:kfree(ds18b20);error_0:returnret;}conststruct of_device_id ds18b20_match_table[]{{.compatibleds18b20},{},};struct platform_driver ds18b20_driver{.driver{.ownerTHIS_MODULE,.nameds18b20,.of_match_tableds18b20_match_table,},.probeds18b20_probe,};staticint__initds18b20_init(void){intret;retplatform_driver_register(ds18b20_driver);if(ret0){printk(platform_driver_register error\n);return-1;}return0;}staticvoid__exitds18b20_exit(void){device_destroy(ds18b20-ds18b20_class,ds18b20-dev_num);class_destroy(ds18b20-ds18b20_class);cdev_del(ds18b20-ds18b20_cdev);unregister_chrdev_region(ds18b20-dev_num,1);kfree(ds18b20);platform_driver_unregister(ds18b20_driver);}module_init(ds18b20_init);module_exit(ds18b20_exit);MODULE_LICENSE(GPL);编译程序make生成驱动程序ds18b20.ko然后执行驱动[rootRK356X:/mnt/sdcard]# chmod777ds18b20.ko[rootRK356X:/mnt/sdcard]# insmod ds18b20.ko[rootRK356X:/mnt/sdcard]#查看内核日志dmesg看到打印了This is probe这就说明设备树中gpio 配置成功了设备树中的compatible ds18b20;和驱动程序中的.name ds18b20定义驱动名称 name 对应上了。struct platform_driver ds18b20_driver{.driver{.ownerTHIS_MODULE,.nameds18b20,.of_match_tableds18b20_match_table,},.probeds18b20_probe,};[rootRK356X:/]# dmesg2、验证设备树配置的gpio节点是否生成cd /proc/device-tree/gpio配置如下 节点名称是gpio0_b0ds18b20_gpio:gpio0_b0{compatibleds18b20;ds18b20-gpiosgpio0 RK_PB0 GPIO_ACTIVE_HIGH;pinctrl-namesdefault;pinctrl-0ds18b20_gpio_ctrl;statusokay;};执行命令cd /proc/device-tree/如下存在名称为gpio0_b0的设备树节点说明设备树配置成功了的3、检查设备树是否加载进入内核-ls -l /proc/device-tree/gpio0_b0如上只是说明设备树已经配置好了那么相关属性是否配置到内核呢ds18b20_gpio:gpio0_b0{compatibleds18b20;ds18b20-gpiosgpio0 RK_PB0 GPIO_ACTIVE_HIGH;pinctrl-namesdefault;pinctrl-0ds18b20_gpio_ctrl;statusokay;};执行ls -l /proc/device-tree/gpio0_b0命令验证如下实际和自己在设备树中的配置对上了。[rootRK356X:/sys/firmware/devicetree/base]# ls-l/proc/device-tree/gpio0_b0 total0-r--r--r--1root root8Apr2608:06compatible-r--r--r--1root root12Apr2608:06ds18b20-gpios-r--r--r--1root root9Apr2608:06name-r--r--r--1root root4Apr2608:06phandle-r--r--r--1root root4Apr2608:06pinctrl-0-r--r--r--1root root8Apr2608:06pinctrl-names-r--r--r--1root root5Apr2608:06status[rootRK356X:/sys/firmware/devicetree/base]#4、验证申请的设备号-cat /proc/devices在驱动源码中申请设备号参考资料驱动-申请字符设备号// 第一步骤:申请设备号retalloc_chrdev_region(ds18b20-dev_num,0,1,myds18b20);//通过动态方式进行设备号注册查看设备号命令cat /proc/devices我们看到申请的字符设备号了。5、验证申请的字符设备类-ls /sys/class/-ls /sys/class/sensors如上源码创建设备类ds18b20-ds18b20_class class_create(THIS_MODULE,sensors);那就看一下设备类是否生成ls /sys/class/参考资料驱动-创建设备节点继续看一下字符设备类下面对应的软链接到哪一个设备命令ls -l /sys/class/sensors/6、验证申请的字符设备 -ls -l /dev/-ls -l /dev/ds18b20如上源码创建设备类// 第五步创建device device_create() - 创建设备节点ds18b20-ds18b20_devicedevice_create(ds18b20-ds18b20_class,NULL,ds18b20-dev_num,NULL,ds18b20);//使用device_create进行设备的创建设备名称为device_test参考资料驱动-创建设备节点命令ls -l /dev/查看当前设备: 如下结果说明字符设备是创建成功了。总结配置设备树、gpio定义声明、pinctrl配置复用、字符设备、平台总线 这些基本知识点之前都学过这里通过实际案例再次实操务必掌握务必在实际开发中搞清楚开发流程如果遇到问题知道怎么定位问题然后分析问题
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2592407.html
如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!