以下内容源于朱有鹏《物联网大讲堂》课程的学习整理,如有侵权,请告知删除。

五、基于驱动框架写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驱动相关推荐

  1. 基于sys文件系统的LED驱动的移植【原创】

    基于RK3188平台LED驱动程序的移植的移植.如有不正确之处,欢迎大家指点. 本文的LED驱动程序不是通过打开设备节点来访问和控制LED的,是通过sys文件系统来控制LED. 板子上有四盏灯以及对应 ...

  2. Linux驱动学习记录-6.设备树的LED驱动

    这一章使用第五章的设备树知识来写led驱动 1.修改设备树 在根节点下面添加子节点 alphaled {#address-cells = <1>;#size-cells = <1&g ...

  3. 网站框架搭建——基于Django框架的天天生鲜电商网站项目系列博客(二)

    系列文章目录 需求分析--基于Django框架的天天生鲜电商网站项目系列博客(一) 网站框架搭建--基于Django框架的天天生鲜电商网站项目系列博客(二) 用户注册模块--基于Django框架的天天 ...

  4. java中的smm,java毕业设计_springboot框架的基于SMM框架的局域网文件共享及检索系统...

    这是一个基于java的毕业设计项目,毕设课题为springboot框架的基于SMM框架的局域网文件共享及检索系统, 是一个采用b/s结构的javaweb项目, 开发工具eclipsei/eclipse ...

  5. java ssm框架论文,基于SSM框架的个人博客系统(源码+论文)

    需求分析 使用spring+springmvc+mybatis实现一个个人博客系统,可以记录个人生活日志, 进行技术分享, 并且浏览者可以对博客进行阅览与评论 本站提供了其他类型的 在线个人博客网站源 ...

  6. (14)[驱动开发]配置环境 VS2019 + WDK10 写 xp驱动

    文章目录 安装SDK和WDK 创建项目 编写程序 其他工具 参考: 参考博客 安装SDK和WDK 我这里用的是VS2019.环境其实是早就配好了,只不过写一下而已.后来VS2019不能被visual ...

  7. LY3005集成驱动充电保护集成芯片多功能LED驱动控制IC

    LY3005 是一款多种模式输出的单芯片LED 驱动控制芯片,集成了锂电池充电管理模块.LED 功能控制模块和保护模块,关机待机电流仅 5uA.LY3005 充电电流 0.8A,最大输出电流为1.3A ...

  8. android开发ssh框架搭建,基于SSH框架的Android系统的研究

    摘要: 本文设计开发了一个基于SSH框架的酒店Android手机查询系统.该系统采用面向对象的设计思想进行分析与设计,利用Eclipse,MyEclipse,Android SDK,Tomcat和My ...

  9. 全志linux led驱动程序,芯灵思Sinlinx A64 linux通过设备树写LED驱动(附参考代码,未测试)...

    #include #include #include #include #include #include #include #include #include #include #include # ...

最新文章

  1. html css发展前景,网页设计的发展趋势
  2. 蚂蚁金服11.11:支付宝和蚂蚁花呗的技术架构及实践
  3. mongodb之 复制集维护小结
  4. NOI2020 前最后的日子
  5. AjaxPost、冒泡示例
  6. Chapter 1. Introduce
  7. Type TIMESTAMP(3) of table field ‘onSellTime‘ does not match with the physical type TIMESTAMP(6)
  8. nginx缓存HtmL文件,Nginx在缓存的html文件上返回404
  9. 如何设置单词第一个字母大写_大写一行中每个单词的第一个和最后一个字母
  10. 执行计划中cpu耗时_面试被问怎么排查遇到的系统CPU飙高和频繁GC,到底该怎么回答?...
  11. 一些Chrome 调试小技巧汇总
  12. JavaScript知识点之如何使用匿名的方法做条件判断
  13. HDU2034 人见人爱A-B【水题】
  14. 思特威电子通过注册:拟募资28亿 小米红杉联想是股东
  15. 除了快,5G 有哪些关键技术?
  16. 年薪百万的市场人都在读哪些书?
  17. android计算器实训报告总结,计算机实训总结报告【三篇】
  18. NetFlix 服务注册与发现 Eureka
  19. jersey restful 测试_Jersey实现Restful服务
  20. Tomcat做成系统服务

热门文章

  1. opencv:图像的基本变换
  2. 数据结构比较型排序算法分析及选择
  3. CAS单点登录配置[3]:服务器端配置
  4. BZOJ-1036 [ZJOI2008]树的统计
  5. 《梦断代码》阅读笔记之第8章至最后
  6. uva 10716 Evil Straw Warts Live
  7. 计算机中整数加法满足结合律吗
  8. ★Linux磁盘配额的使用 ★——牛刀小试
  9. C++中的结构体函数
  10. 安卓自定义View进阶-分类与流程