platform之按键驱动多种写法(笔记)
来源:互联网 发布:销售管理论文数据 编辑:程序博客网 时间:2024/04/28 06:32
platform之按键驱动多种写法(笔记)
- 1.读引脚电平高低(ioctl方式)(应用层采用查询ioctl的方式)
缺点:无阻塞、不能按键防抖
- 2.外部中断方式(key_read方式)(应用层调用read)
缺点:无阻塞、不能按键防抖
- 3.再加定时器方式(key_read方式)(应用层调用read)
优点:按键能防抖缺点:无阻塞
- 4.再加中断顶半步方式(key_read方式)(应用层调用read)
优点:按键能防抖,中断响应更合理缺点:无阻塞
- 5.再加消息队列(key_read方式)(应用层调用read)
优点:按键能防抖,中断响应更合理,有阻塞
通用部分
1.模块三要素
1.1 初始化模块 1.2 退出模块 1.3 模块签证
2.platform总线的三个步骤
2.1 实例化platform_driver结构体i)实例化回掉函数probe,并为成员.probe赋值ii)实例化回掉函数remove,并为成员.remove赋值iii)选择一种匹配方式进行匹配(设备树,ACPI,名字,ID四选一)2.2 注册2.3 注销
3.字符设备框架流程(天龙八部)
3.1 申请设备号3.2 注册设备号3.3 实例化cdev结构体3.4 实例化file_operations结构体,并初始化3.5 初始化cdev结构体3.6 注册cdev结构体3.7 注销cdev结构体3.8 注销设备号
4.自动创建设备节点
4.1 创建class4.2 创建设备节点4.3 注销设备节点4.4 注销class
方式一:读引脚电平高低
(ioctl方式,无中断,无阻塞)(应用层采用查询方式)
//***********************head.h中***************************//#define MAGIC 'k'#define KEY_STATUS _IO(MAGIC,1)//***********************key_probe函数中*********************//gpx1dat = ioremap(pdev->resource[2].start,pdev->resource[2].end - pdev->resource[2].start);//***********************key_ioctl函数中*********************//long key_ioctl (struct file * file, unsigned int cmd, unsigned long arg){ int ret; printk("key_ioctl cmd=%x \n",cmd); switch(cmd) { case KEY_STATUS: ret = *gpx1dat & (0x1 << 1); printk("key1 = %d",ret); break; default: printk("no such the cmd!\n"); return -EFAULT; break; } return 0;}//***********************key_remove函数中***************************//iounmap(gpx1dat);
方式二:加外部中断
//*******************************全局变量*****************************//#define IRQ1_NAME "key2"#define IRQ2_NAME "key3"int key;//*******************************key_read函数*****************************//ssize_t key_read (struct file *file, char __user *buf, size_t size, loff_t * loft){ int ret; printk(" key_read!!!\n"); if (size < 0) return -EFAULT; if (size > sizeof(key)) size = sizeof(key); ret = copy_to_user(buf,&key,size); return sizeof(key) - ret;}//*******************************key_handler中断函数*****************************//irqreturn_t key_handler(int num,void *dev){ if (mydev->resource[0].start == num) { key = 2; } if (mydev->resource[1].start == num) { key = 3; } return IRQ_HANDLED;}//*******************************probe_key函数*****************************//ret = request_irq(pdev->resource[0].start,key_handler,IRQF_TRIGGER_FALLING | IRQF_DISABLED,IRQ1_NAME,NULL);if (ret < 0){ printk("request irq fail!!!\n"); return -EFAULT;}ret = request_irq(pdev->resource[1].start,key_handler,IRQF_TRIGGER_FALLING | IRQF_DISABLED,IRQ2_NAME,NULL);if (ret < 0){ printk(" request_irq fail!!!\n"); return -EFAULT;}//***********key_remove函数中*********//free_irq(pdev->resource[0].start,NULL);free_irq(pdev->resource[1].start,NULL);
方式三:再加消息队列和内核定时器
//************************head.h****************************//#define IRQ1_NAME "key2"#define IRQ2_NAME "key3"//struct tasklet_struct my_tasklet;struct work_struct my_wq;wait_queue_head_t wqt;static int flag;static int irq;struct timer_list my_timer;struct resource * res1;struct resource * res2;struct resource * res3;volatile unsigned int * gpx1dat;static int key;//************************key_probe函数****************************//init_waitqueue_head(&wqt);init_timer(&my_timer);my_timer.function = do_my_timer;my_timer.expires = jiffies + 40;add_timer(&my_timer);// tasklet_init(&my_tasklet,do_tasklet_fun,0);INIT_WORK(&my_wq,work_func_t wq_do_work);res1 = platform_get_resource(pdev,IORESOURCE_IRQ,0);res2 = platform_get_resource(pdev,IORESOURCE_IRQ,1);res3 = platform_get_resource(pdev,IORESOURCE_MEM,0);ret = request_irq(res1->start,key_irq_handler,IRQF_TRIGGER_FALLING | IRQF_DISABLED,IRQ1_NAME,NULL);if(ret < 0){ printk("request_irq fail!\n"); return ret;}ret = request_irq(res2->start,key_irq_handler,IRQF_TRIGGER_FALLING | IRQF_DISABLED,IRQ2_NAME,NULL);if(ret < 0){ printk("request_irq fail!\n"); return ret;}gpx1dat = ioremap(res3->start,res3->end - res3->start);if(gpx1dat == NULL){ printk("ioremap fail!\n"); return ret;}//************************key_remove函数****************************//del_timer(&my_timer);iounmap(gpx1dat);free_irq(res1->start,NULL);free_irq(res2->start,NULL);//************************key_read函数****************************//ssize_t key_read (struct file * file, char __user * buf, size_t size, loff_t * loft){ int ret; if(size < 0) { return-EFAULT; } if(size > sizeof(key)) { size = sizeof(key); } wait_event_interruptible(wqt,flag == 1); flag = 0; ret = copy_to_user(buf,&key,size); return size -ret;}//************************key_irq_handler函数****************************//irqreturn_t key_irq_handler(int num,void * dev){ irq = num;// tasklet_schedule(&my_tasklet); schedule_work(&my_wq); return IRQ_HANDLED;}//************************wq_do_work函数****************************//void wq_do_work(struct work_struct *work){ mod_timer(&my_timer,jiffies + 40);}//************************do_my_timer函数****************************//void do_my_timer(unsigned long num){ if(res1->start == irq) { if(*gpx1dat & (0x1 << 1)) { key = 2; wake_up_interruptible(&wqt); flag = 1; } } if(res2->start == irq) { if(*gpx1dat & (0x1 << 2)) { key = 3; wake_up_interruptible(&wqt); flag = 1; } }}
加中断顶半步
未完待续
0 0
- platform之按键驱动多种写法(笔记)
- 驱动之路-platform按键驱动
- platform设备驱动之按键扫描(cdev设备)
- platform设备驱动之按键扫描(misc设备)
- platform按键驱动学习之测试实例
- Platform总线按键驱动分析(精华版)
- platform总线按键驱动分析(精华版)
- 按键驱动:platform架构
- platform按键驱动学习
- 一步一步学习 Linux 驱动之 platform 机制(tiny210 按键驱动)
- 驱动案例三:platform按键驱动(二、驱动)
- 驱动案例三:platform按键驱动(一、设备)
- 驱动案例三:platform按键驱动(三、应用程序)
- platform下的按键驱动
- platform总线按键驱动分析
- tiny6410按键platform(平台)驱动的实现
- tiny6410按键platform(平台)驱动的实现
- 2416开发记录十一:按键驱动(platform/中断)
- 顺序表存储结构
- leetcode 445. Add Two Numbers II
- MySQL主从复制技术(纯干货)
- 轮回 第十章 醒来,吃馒头?
- Tensorflow的Bazel编程(四)
- platform之按键驱动多种写法(笔记)
- Effective c++ 读书笔记 4
- 命令模式
- 2318 Mod(哈尔滨理工大学)
- Android okHttp网络请求之Get/Post请求
- 关于 LF will be replaced by CRLF 问题出现的原因以及解决方式
- 读书笔记第一章第四节1.4各存储引擎直接的比较
- 2017-1-8
- python 常用知识点总结