飞凌 ok6410 按键驱动源码及测试代码
生活随笔
收集整理的這篇文章主要介紹了
飞凌 ok6410 按键驱动源码及测试代码
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
2019獨角獸企業重金招聘Python工程師標準>>>
由于OK6410的GPIO按鍵中斷已經被飛凌自帶的按鍵驅動注冊,所以運行我們編寫的按鍵驅動前要先去掉飛凌自帶的按鍵驅動,方法:make menuconfig->Device Drivers->input device support->Key Boards->GPIO Buttons 去掉前面的*,即不選該項即可。
key.c
#include?<linux/kernel.h>#include?<linux/module.h>#include?<linux/init.h>#include?<linux/fs.h>#include?<linux/gpio.h>#include?<linux/types.h>#include?<linux/cdev.h>#include?<linux/interrupt.h>#include?<linux/sched.h>#include?<linux/device.h>#include?<linux/poll.h>#include?<linux/semaphore.h>#include?<linux/timer.h>#include?<asm/irq.h>#include?<asm/uaccess.h>//#include?<mach/hardware.h>#include?<mach/irqs.h>#define?DEVICE_NAME?"keyint"#define?KEYNUM?6dev_t?devid;//static?DEFINE_SEMAPHORE(key_lock);??//declare?a?mutex?lock?for?keyint//定義一個信號量struct?semaphore?key_lock;static?struct?fasync_struct?*key_async;static?struct?timer_list?key_timer;struct?key_irq_desc?{int?irq;????????//irq?numunsigned?long?flags;????//irq?flags,identified?the?way?of?irq?here,eq.edge,levelchar?*name;????????//irq?name};static?struct?key_irq_desc?key_irqs[]?=?{//下降沿產生中斷{IRQ_EINT(0),?IRQF_TRIGGER_FALLING,?"KEY1"},{IRQ_EINT(1),?IRQF_TRIGGER_FALLING,?"KEY2"},{IRQ_EINT(2),?IRQF_TRIGGER_FALLING,?"KEY3"},{IRQ_EINT(3),?IRQF_TRIGGER_FALLING,?"KEY4"},{IRQ_EINT(4),?IRQF_TRIGGER_FALLING,?"KEY5"},{IRQ_EINT(5),?IRQF_TRIGGER_FALLING,?"KEY6"},};/*define?a?waiting?queue?here*/static?DECLARE_WAIT_QUEUE_HEAD(key_waitq);/*define?a?event?flag?ev_press*/static?volatile?int?ev_press?=?0;static?volatile?int?press_cnt[KEYNUM]?=?{0,0,0,0,0,0};/*中斷處理函數*/static?irqreturn_t?keys_interrupt(int?irq,?void?*dev_id){volatile?int?*press_cnt?=?(volatile?int?*)?dev_id;/*set?the?pressed?key?flag(must?do?here?due?to?not?be?static?value)*/*press_cnt?=?*press_cnt?+?1;//延時10ms后執行定時器處理函數mod_timer(&key_timer,jiffies+HZ/100);????????//start?timer?after?10msreturn?IRQ_RETVAL(IRQ_HANDLED);}//定時器處理函數static?void?key_timer_func(unsigned?long?data){ev_press?=?1;//喚醒等待隊列wake_up_interruptible(&key_waitq);kill_fasync(&key_async,?SIGIO,?POLL_IN);}static?int?key_fasync(int?fd,?struct?file?*filp,?int?on){printk("Function?key_fasync\n");return?fasync_helper(fd,filp,on,&key_async);}static?unsigned?key_poll(struct?file?*file,?poll_table?*wait){unsigned?int?mask=0;//指明要使用的等待隊列poll_wait(file,&key_waitq,wait);//返回掩碼if(ev_press)mask?|=?POLL_IN?|?POLLRDNORM;printk("poll?wait\n");return?mask;}static?int?key_open(struct?inode?*inode,?struct?file?*file){int?num;if(file->f_flags?&?O_NONBLOCK)?{if(down_trylock(&key_lock))?return?-EBUSY;}else?{down(&key_lock);}//為每個按鍵注冊中斷處理程序for(num=0;num<KEYNUM;num++)?{request_irq(key_irqs[num].irq,?keys_interrupt,?key_irqs[num].flags,?key_irqs[num].name,?(void?*)&press_cnt[num]);}return?0;}static?int?key_close(struct?inode?*inode,?struct?file?*file){int?num;//釋放中斷號for(num=0;num<6;num++)?{free_irq(key_irqs[num].irq,?(void?*)&press_cnt[num]);}up(&key_lock);printk("key_close?free?irqs\n");return?0;}static?int?key_read(struct?file?*filp,?char?__user?*buff,?size_t?count,?loff_t?*offp){//????unsigned?int?err;//判斷是阻塞讀還是非阻塞讀if(filp->f_flags?&?O_NONBLOCK)?{if(!ev_press)??return?-EAGAIN;}else?{/*if?ev_press==0,then?sleep*//*阻塞,當有按鍵按下時(中斷)被喚醒*/wait_event_interruptible(key_waitq,ev_press);}//阻塞結束,有鍵按下了ev_press?=?0;//拷貝數據到用戶空間copy_to_user(buff,(const?void?*)press_cnt,min(sizeof(press_cnt),count));memset((void?*)press_cnt,0,sizeof(press_cnt));//????printk("read?and?clean?press_cnt\n");return?1;}static?struct?file_operations?key_ops?=?{.owner?????=?THIS_MODULE,.open?????=?key_open,.release?=?key_close,.read?????=?key_read,.poll?????=?key_poll,.fasync?????=?key_fasync,};static?struct?cdev?*cdev_keyint;static?struct?class?*keyint_class;//模塊初始化函數static?int?__init?s3c6410_keyint_init(void)?{int?val;/*timer?initial?*/init_timer(&key_timer);key_timer.function?=?key_timer_func;add_timer(&key_timer);/*初始化信號量*/init_MUTEX(&key_lock);/*register?device*/val?=?alloc_chrdev_region(&devid,0,1,DEVICE_NAME);if(val)?{return?-1;printk("register?keyint?error\n");}cdev_keyint?=?cdev_alloc();cdev_init(cdev_keyint,?&key_ops);cdev_keyint->owner?=?THIS_MODULE;cdev_keyint->ops???=?&key_ops;val?=?cdev_add(cdev_keyint,devid,1);if(val)?{return?-1;printk("add?device?error\n");}keyint_class?=?class_create(THIS_MODULE,DEVICE_NAME);device_create(keyint_class,NULL,devid,NULL,"%s",DEVICE_NAME);printk("KEY?initialezed?^_^\n");return?0;}static?void?__exit?s3c6410_keyint_exit(void){cdev_del(cdev_keyint);device_destroy(keyint_class,devid);class_destroy(keyint_class);unregister_chrdev_region(devid,1);}module_init(s3c6410_keyint_init);module_exit(s3c6410_keyint_exit);MODULE_LICENSE("GPL");Makefile
ifneq?($(KERNELRELEASE),)obj-m?:=?key.o elseKDIR?:=?/forlinux/linux-3.0.1 all:make?-C?$(KDIR)?M=$(PWD)?modules?ARCH=arm?CROSS_COMPILE=arm-linux- clean:rm?-f?*.ko?*.o?*.mod.o?*.mod.c?*.symvers endif產生.ko文件進行安裝模塊和設備 insmod,這里不需要mknod因為函數里調用了class_create和device_create會自動創建設備節點。
測試代碼
#include?<stdio.h>#include?<stdlib.h>#include?<unistd.h>#include?<sys/ioctl.h>int?main(int?argc,?char?**argv){int?fd;int?val;int?i;int?key_value[6];fd?=?open("/dev/keybutton",0);if(fd<0)?{printf("open?devie?error\n");return?-1;}while(1)?{val?=?read(fd,key_value,?sizeof(key_value));if(val<0)?{printf("read?error\n");continue;}for(i=0;i<6;i++)?{if(key_value[i])printf("KEY%d?pressed\n",(i+1),key_value[i]);}??}close(fd);return?0;}轉載于:https://my.oschina.net/u/274829/blog/286067
總結
以上是生活随笔為你收集整理的飞凌 ok6410 按键驱动源码及测试代码的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: ARC和MRC 兼容的单例模式
- 下一篇: 正则表达式 使用分支