驱动框架5——基于驱动框架写led驱动
以下内容源于朱有鹏《物联网大讲堂》课程的学习整理,如有侵权,请告知删除。
五、基于驱动框架写led驱动1
1、分析
(1)参考哪里? drivers/leds/leds-s3c24xx.c文件,drivers/leds/led-class.c文件(此文件是一些函数的集合体)
(2)关键点?led_classdev_register函数,led_classdev_unregister函数
2、动手写led驱动模块
- led_classdev_unregister函数
- led_classdev_register函数
- 这里写的驱动,没有像leds-s3c24xx.c那样使用驱动模型——平台总线模型,而是参考部分,自己写的驱动
#include <linux/module.h> // module_init module_exit
#include <linux/init.h> // __init __exit
#include <linux/fs.h>
#include <linux/leds.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#include <linux/io.h>
#include <linux/ioport.h>#define GPJ0CON S5PV210_GPJ0CON
#define GPJ0DAT S5PV210_GPJ0DATstatic struct led_classdev mydev; // 定义结构体变量// 这个函数就是要去完成具体的硬件读写任务的
static void s5pv210_led_set(struct led_classdev *led_cdev,enum led_brightness value)
{printk(KERN_INFO "s5pv210_led_set\n");// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value == LED_OFF){// 用户给了个0,希望LED灭writel(0x11111111, GPJ0CON);writel(((1<<3) | (1<<4) | (1<<5)), GPJ0DAT);}else{// 用户给的是非0,希望LED亮writel(0x11111111, GPJ0CON);writel(((0<<3) | (0<<4) | (0<<5)), GPJ0DAT);}
}static int __init s5pv210_led_init(void)
{// 用户insmod安装驱动模块时会调用该函数// 该函数的主要任务就是去使用led驱动框架提供的设备注册函数来注册一个设备int ret = -1;mydev.name = "myled";//设备的名字mydev.brightness = 255; mydev.brightness_set = s5pv210_led_set;ret = led_classdev_register(NULL, &mydev);if (ret < 0) {printk(KERN_ERR "led_classdev_register failed\n");return ret;}return 0;
}static void __exit s5pv210_led_exit(void)
{led_classdev_unregister(&mydev);
}module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL"); // 描述模块的许可证
MODULE_AUTHOR("aston <1264671872@qq.com>"); // 描述模块的作者
MODULE_DESCRIPTION("s5pv210 led driver"); // 描述模块的介绍信息
MODULE_ALIAS("s5pv210_led"); // 描述模块的别名信息
六、基于驱动框架写led驱动2
1、代码实践
(1)调试
(2)分析drivers/leds/led-class.c文件
- 我们写的驱动确实工作了,被加载了,/sys/class/leds/目录下确实多出来了一个表示设备的文件夹。
- 文件夹里面有相应的操控led硬件的2个属性brightness和max_brightness。
- led-class.c中brightness方法有一个show方法和store方法,这两个方法对应用户在/sys/class/leds/myled/brightness目录下直接去读写这个文件时实际执行的代码。
- 当我们show brightness时,实际就会执行led_brightness_show函数。
- 当我们echo 1 > brightness时,实际就会执行led_brightness_store函数。
(3)show方法实际要做的就是读取LED硬件信息,然后把硬件信息返回
- 因此show方法和store方法会去操控硬件;
- 但是led-class.c文件又属于驱动框架中的文件,它本身无法直接读取具体硬件;
- 因此在show和store的函数实现中,使用函数指针的方式调用了struct led_classdev结构体中的相应的读取/写入硬件信息的方法。
(4)struct led_classdev结构体中的实际用来读写硬件信息的函数,就是我们自己写的驱动文件leds-s5pv210.c中要提供的。
2、添加硬件操作
七、基于驱动框架写led驱动3
1、在驱动中将4个LED分开
(1)好处
- 驱动层实现对各个LED设备的独立访问,并向应用层展示出4个操作接口led1、led2、led3、led4,这样应用层可以完全按照自己的需要对LED进行控制。
- 驱动的设计理念:不要对最终需求功能进行假定(不能假定用户进行什么操作,比如是几个led一起操作还是一个操作而已?),而应该只是直接的对硬件的操作。
- 有一个概念就是:机制和策略的问题。在硬件操作上驱动只应该提供机制(具体实现)而不是策略(方法、主意、解决方案)。策略由应用程序来做。
(2)如何实现
#include <linux/module.h> // module_init module_exit
#include <linux/init.h> // __init __exit
#include <linux/fs.h>
#include <linux/leds.h>
#include <mach/regs-gpio.h>
#include <mach/gpio-bank.h>
#include <linux/io.h>
#include <linux/ioport.h>#define GPJ0CON S5PV210_GPJ0CON
#define GPJ0DAT S5PV210_GPJ0DATstatic struct led_classdev mydev1; // 定义结构体变量
static struct led_classdev mydev2; // 定义结构体变量
static struct led_classdev mydev3; // 定义结构体变量// 这个函数就是要去完成具体的硬件读写任务的
static void s5pv210_led1_set(struct led_classdev *led_cdev, enum led_brightness value)
{printk(KERN_INFO "s5pv210_led1_set\n");writel(0x11111111, GPJ0CON);// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value == LED_OFF){// 用户给了个0,希望LED灭//writel(0x11111111, GPJ0CON);// 读改写三部曲writel((readl(GPJ0DAT) | (1<<3)), GPJ0DAT);}else{// 用户给的是非0,希望LED亮//writel(0x11111111, GPJ0CON);writel((readl(GPJ0DAT) & ~(1<<3)), GPJ0DAT);}
}static void s5pv210_led2_set(struct led_classdev *led_cdev, enum led_brightness value)
{printk(KERN_INFO "s5pv2102_led_set\n");writel(0x11111111, GPJ0CON);// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value == LED_OFF){// 用户给了个0,希望LED灭//writel(0x11111111, GPJ0CON);// 读改写三部曲writel((readl(GPJ0DAT) | (1<<4)), GPJ0DAT);}else{// 用户给的是非0,希望LED亮//writel(0x11111111, GPJ0CON);writel((readl(GPJ0DAT) & ~(1<<4)), GPJ0DAT);}
}static void s5pv210_led3_set(struct led_classdev *led_cdev,enum led_brightness value)
{printk(KERN_INFO "s5pv210_led3_set\n");writel(0x11111111, GPJ0CON);// 在这里根据用户设置的值来操作硬件// 用户设置的值就是valueif (value == LED_OFF){// 用户给了个0,希望LED灭//writel(0x11111111, GPJ0CON);// 读改写三部曲writel((readl(GPJ0DAT) | (1<<5)), GPJ0DAT);}else{// 用户给的是非0,希望LED亮//writel(0x11111111, GPJ0CON);writel((readl(GPJ0DAT) & ~(1<<5)), GPJ0DAT);}
}static int __init s5pv210_led_init(void)
{// 用户insmod安装驱动模块时会调用该函数// 该函数的主要任务就是去使用led驱动框架提供的设备注册函数来注册一个设备int ret = -1;// led1mydev1.name = "led1";mydev1.brightness = 255; mydev1.brightness_set = s5pv210_led1_set;ret = led_classdev_register(NULL, &mydev1);if (ret < 0) {printk(KERN_ERR "led_classdev_register failed\n");return ret;}// led2mydev2.name = "led2";mydev2.brightness = 255; mydev2.brightness_set = s5pv210_led2_set;//这句话就把驱动框架第一部分,和第二部分关联起来了!!!!!ret = led_classdev_register(NULL, &mydev2);if (ret < 0) {printk(KERN_ERR "led_classdev_register failed\n");return ret;}// led3mydev3.name = "led3";mydev3.brightness = 255; mydev3.brightness_set = s5pv210_led3_set;ret = led_classdev_register(NULL, &mydev3);if (ret < 0) {printk(KERN_ERR "led_classdev_register failed\n");return ret;}return 0;
}static void __exit s5pv210_led_exit(void)
{led_classdev_unregister(&mydev1);led_classdev_unregister(&mydev2);led_classdev_unregister(&mydev3);
}module_init(s5pv210_led_init);
module_exit(s5pv210_led_exit);// MODULE_xxx这种宏作用是用来添加模块描述信息
MODULE_LICENSE("GPL"); // 描述模块的许可证
MODULE_AUTHOR("aston <1264671872@qq.com>"); // 描述模块的作者
MODULE_DESCRIPTION("s5pv210 led driver"); // 描述模块的介绍信息
MODULE_ALIAS("s5pv210_led"); // 描述模块的别名信息
2、和leds-s3c24xx.c的不同
3、gpiolib引入
(1)一个事实:很多硬件都要用到GPIO,GPIO会复用;
(2)如果同一个GPIO被2个驱动同时控制了,就会出现bug;
(3)内核提供gpiolib来统一管理系统中所有GPIO;
- 某个驱动需要用到GPIO时,需要申请,被许可后才可以使用,使用完后释放,其他驱动才能使用该GPIO。
- 建议性的,希望都用gpiolib。
(4)gpiolib体系,属于驱动框架的一部分。
驱动框架5——基于驱动框架写led驱动相关推荐
- 基于sys文件系统的LED驱动的移植【原创】
基于RK3188平台LED驱动程序的移植的移植.如有不正确之处,欢迎大家指点. 本文的LED驱动程序不是通过打开设备节点来访问和控制LED的,是通过sys文件系统来控制LED. 板子上有四盏灯以及对应 ...
- Linux驱动学习记录-6.设备树的LED驱动
这一章使用第五章的设备树知识来写led驱动 1.修改设备树 在根节点下面添加子节点 alphaled {#address-cells = <1>;#size-cells = <1&g ...
- 网站框架搭建——基于Django框架的天天生鲜电商网站项目系列博客(二)
系列文章目录 需求分析--基于Django框架的天天生鲜电商网站项目系列博客(一) 网站框架搭建--基于Django框架的天天生鲜电商网站项目系列博客(二) 用户注册模块--基于Django框架的天天 ...
- java中的smm,java毕业设计_springboot框架的基于SMM框架的局域网文件共享及检索系统...
这是一个基于java的毕业设计项目,毕设课题为springboot框架的基于SMM框架的局域网文件共享及检索系统, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse ...
- java ssm框架论文,基于SSM框架的个人博客系统(源码+论文)
需求分析 使用spring+springmvc+mybatis实现一个个人博客系统,可以记录个人生活日志, 进行技术分享, 并且浏览者可以对博客进行阅览与评论 本站提供了其他类型的 在线个人博客网站源 ...
- (14)[驱动开发]配置环境 VS2019 + WDK10 写 xp驱动
文章目录 安装SDK和WDK 创建项目 编写程序 其他工具 参考: 参考博客 安装SDK和WDK 我这里用的是VS2019.环境其实是早就配好了,只不过写一下而已.后来VS2019不能被visual ...
- LY3005集成驱动充电保护集成芯片多功能LED驱动控制IC
LY3005 是一款多种模式输出的单芯片LED 驱动控制芯片,集成了锂电池充电管理模块.LED 功能控制模块和保护模块,关机待机电流仅 5uA.LY3005 充电电流 0.8A,最大输出电流为1.3A ...
- android开发ssh框架搭建,基于SSH框架的Android系统的研究
摘要: 本文设计开发了一个基于SSH框架的酒店Android手机查询系统.该系统采用面向对象的设计思想进行分析与设计,利用Eclipse,MyEclipse,Android SDK,Tomcat和My ...
- 全志linux led驱动程序,芯灵思Sinlinx A64 linux通过设备树写LED驱动(附参考代码,未测试)...
#include #include #include #include #include #include #include #include #include #include #include # ...
最新文章
- html css发展前景,网页设计的发展趋势
- 蚂蚁金服11.11:支付宝和蚂蚁花呗的技术架构及实践
- mongodb之 复制集维护小结
- NOI2020 前最后的日子
- AjaxPost、冒泡示例
- Chapter 1. Introduce
- Type TIMESTAMP(3) of table field ‘onSellTime‘ does not match with the physical type TIMESTAMP(6)
- nginx缓存HtmL文件,Nginx在缓存的html文件上返回404
- 如何设置单词第一个字母大写_大写一行中每个单词的第一个和最后一个字母
- 执行计划中cpu耗时_面试被问怎么排查遇到的系统CPU飙高和频繁GC,到底该怎么回答?...
- 一些Chrome 调试小技巧汇总
- JavaScript知识点之如何使用匿名的方法做条件判断
- HDU2034 人见人爱A-B【水题】
- 思特威电子通过注册:拟募资28亿 小米红杉联想是股东
- 除了快,5G 有哪些关键技术?
- 年薪百万的市场人都在读哪些书?
- android计算器实训报告总结,计算机实训总结报告【三篇】
- NetFlix 服务注册与发现 Eureka
- jersey restful 测试_Jersey实现Restful服务
- Tomcat做成系统服务