inux按键中断驱动程序——S3C2440

来源:互联网 发布:淘宝erp软件哪个好 编辑:程序博客网 时间:2024/04/27 18:55
原文地址http://blog.csdn.net/qishi_blog/article/details/6922621

[plain]
view plaincopy
  1. <pre name="code" class="html">驱动程序</pre><pre name="code" class="html">#include<linux/module.h>  
  2. #include<linux/init.h>  
  3. #include<linux/types.h>  
  4. #include<linux/kdev_t.h>  
  5. #include<linux/kernel.h>      //可以使用ptintk函数  
  6. #include<linux/fs.h>  
  7. #include<linux/interrupt.h>   //与中断相关的头文件  
  8. #include<linux/cdev.h>           //字符设备的注册  
  9. #include<linux/err.h>           //出错检查函数  
  10. #include<linux/slab.h>         //与内存分配相关  
  11. #include<linux/sched.h>        //与中断相关的头文件  
  12. #include<asm/io.h>             //操作IO端口  
  13. #include<linux/wait.h>         //等待队列   
  14. #include<asm/uaccess.h>         //用户和内核空间数据的拷贝  
  15. #include<asm/arch/regs-gpio.h>  //I/O口的寄存器地址及使用方式(输入、输出、中断或其他)  
  16. #include<asm/arch/regs-irq.h>   //与中断相关的寄存器  
  17. #include<asm/arch-s3c2410/irqs.h>//与平台相关的中断号的定义  
  18. #include<linux/delay.h>          //时间延迟函数  
  19.   
  20. #define key_major 234         //定义主设备号  
  21. #define key_minor 0           //定义次设备号  
  22. #define DEVICE_NAME "key_interrupt"  
  23. //static struct cdev * key_cdev;  
  24. //static dev_t dev_num;  
  25. static volatile int key_flags=0;        //作为等待队列的标志  
  26. DECLARE_WAIT_QUEUE_HEAD(queue);         //初始化等待队列  
  27. static volatile int key_value[]={1,2,3,4};  //按键值  
  28. static volatile int key_press=0;            //记录那个键被按下了  
  29. static dev_t dev_num;                       //设备号的dev_t表示  
  30. static struct cdev *key_cdev;  
  31.   
  32. struct key_irq_description{  
  33.     unsigned int irq;  
  34.     unsigned long flags;  
  35.     const char *dev_name;  
  36. };  
  37.   
  38. struct key_irq_description key_irq[]={  
  39.     {IRQ_EINT0,SA_INTERRUPT,"key"},  
  40.     {IRQ_EINT2,SA_INTERRUPT,"key"},  
  41.     {IRQ_EINT3,SA_INTERRUPT,"key"},  
  42.     {IRQ_EINT4,SA_INTERRUPT,"key"},  
  43. };  
  44. /*中断处理函数*/  
  45. static irqreturn_t key_interrupt(int irq, void *dev_id,struct pt_regs *regs)  
  46. {  
  47.     __raw_writel(__raw_readl(S3C2410_SRCPND)&0xffffffda,S3C2410_SRCPND);//clear srcpnd 0 2 3 4(这个很重要)  
  48.     mdelay(1);  
  49.     key_press= *(int *) dev_id;                  //把按键值付给key_press  
  50.     key_flags=1;                                 //等待队列标志置一   
  51.     wake_up_interruptible(&queue);               //唤醒等待队列  
  52.         return IRQ_HANDLED;    
  53. }  
  54. /*在这里只申请中断,可以节省中断资源*/  
  55. static int key_open(struct inode *inode, struct file *filp)  
  56. {  
  57.         printk("now in key_open\n");  
  58.     int ret;  
  59.     int i;  
  60.     for(i=0;i<sizeof(key_irq)/sizeof(key_irq[0]);i++){  
  61.     ret=request_irq(key_irq[i].irq,key_interrupt,key_irq[i].flags,key_irq[i].dev_name,(void *)&key_value[i]);//申请中断  
  62.     printk("please irq\n");  
  63.     if(ret) break;  
  64.     }  
  65.     if(ret){  
  66.         printk("now at free_irq\n");  
  67.         i--;  
  68.         for(;i>=0;i--){  
  69.             free_irq(key_irq[i].irq,(void *)&key_value[i]);  
  70.             return -EBUSY;  
  71.         }  
  72.     }  
  73.         return 0;  
  74. }  
  75.   
  76. /*不使用相关资源时释放中断*/  
  77. static int key_close(struct inode *inode, struct file *filp)  
  78. {  
  79.     int i;  
  80.     for(i=0;i<sizeof(key_irq)/sizeof(key_irq[0]);i++){  
  81.         free_irq(key_irq[i].irq,(void *)&key_value[i]);  
  82.     }  
  83.     return 0;  
  84. }  
  85.   
  86. /*完成数据从内核空间到用户控件的拷贝*/  
  87. static ssize_t key_read(struct file *filp, char __user *buf, size_t count , loff_t * offp)  
  88. {  
  89.     unsigned long err;  
  90.     wait_event_interruptible(queue,key_flags);                 //开启等待队列  
  91.     key_flags=0;                                               //当key_flags=1时可释放等待队列  
  92.     err=copy_to_user(buf,(const void *)&key_press,count);      //注意表示方法  
  93.     key_press=0;  
  94.     return err?-EFAULT:0;  
  95. }  
  96.   
  97. static struct file_operations key_fops={  
  98.     .owner    = THIS_MODULE,  
  99.     .read     = key_read,  
  100.     .open     = key_open,  
  101.     .release = key_close,  
  102. };  
  103.   
  104. /*填充cdev结构*/  
  105. static void key_cdev_setup(void)  
  106. {  
  107.     int err;  
  108.     cdev_init(key_cdev,&key_fops);                               //初始化已分配到的结构  
  109.     key_cdev->owner=THIS_MODULE;                                 //设置所有者字段  
  110.     key_cdev->ops=&key_fops;  
  111.     err=cdev_add(key_cdev,dev_num,1);                            //告诉内核该结构的信息  
  112.     if(IS_ERR(&err)){                                            //检查返回的指针是否是一个错误编码  
  113.         printk(KERN_NOTICE "Error %d adding key_interrupt",err);  
  114.     }  
  115. }  
  116.   
  117. /*初始化相关寄存器*/  
  118. static void initbutton(void)  
  119. {  
  120.     __raw_writel((__raw_readl(S3C2410_GPFCON)&(~((3<<8)|(3<<6)|(3<<4)|(3<<0))))|((2<<8)|(2<<6)|(2<<4)|(2<<0)),S3C2410_GPFCON) ;  //GPF2,0,3,4 set EINT  
  121.     __raw_writel((__raw_readl(S3C2410_EXTINT0)&(~(7|(7<<8)|(7<<12)|(7<<16)))),S3C2410_EXTINT0);  
  122.     __raw_writel((__raw_readl(S3C2410_EXTINT0)|(0|(0<<8)|(0<<12)|(0<<16))),S3C2410_EXTINT0);   //set eint0,2,3,4 falling edge int  
  123.     __raw_writel((__raw_readl(S3C2410_EINTPEND)|((1<<4))),S3C2410_EINTPEND);                   //clear eint 4  
  124.     __raw_writel((__raw_readl(S3C2410_EINTMASK)&(~((1<<4)))),S3C2410_EINTMASK);                //enable eint 4  
  125.   
  126. }  
  127. /*模块初始化函数,分配设备编号,初始化寄存器,为cdev结构分配内存并初始化cdev结构*/  
  128. static int __init key_init(void)          
  129. {  
  130.     int ret;  
  131.     initbutton();                                 //初始化相关寄存器  
  132.     if(key_major){                                  
  133.        dev_num=MKDEV(key_major,key_minor);  
  134.        ret=register_chrdev_region(dev_num,1,DEVICE_NAME);    //静态分配设备编号  
  135.     }  
  136.     else{  
  137.         ret=alloc_chrdev_region(&dev_num,key_minor,1,DEVICE_NAME);    //动态分配设备编号  
  138.     }  
  139.     if(ret<0){  
  140.         printk(KERN_WARNING "key: can't get key_major %d\n",key_major);  
  141.         return ret;  
  142.     }  
  143.     key_cdev=kmalloc(sizeof(struct cdev),GFP_KERNEL);                     //为cdev结构分配内存  
  144.     if(!key_cdev){  
  145.         printk("can't get this RAM\n");  
  146.         ret=-ENOMEM;  
  147.     }  
  148.     memset(key_cdev,0,sizeof(struct cdev));                               //cdev结构内存区清零  
  149.     key_cdev_setup();                                                     //注册设备结构cdev  
  150.     return 0;  
  151. }  
  152.   
  153. /*模块退出函数,内部函数执行顺序要与模块初始化的顺序相反*/  
  154. static void __exit key_exit(void)  
  155. {  
  156.     cdev_del(key_cdev);                          //删除cdev结构  
  157.     kfree(key_cdev);                             //释放分配的内存  
  158.     unregister_chrdev_region(dev_num,1);         //释放设备编号  
  159. }  
  160. module_init(key_init);  
  161. module_exit(key_exit);  
  162. MODULE_LICENSE("GPL");    
  163. MODULE_AUTHOR("lizhibin");    
  164. MODULE_DESCRIPTION("key and interrupt");</pre><br>  
  165. <pre></pre>  
  166. <pre name="code" class="plain"&gt;</pre><pre name="code" class="plain"></pre><pre name="code" class="plain">测试程序</pre><pre name="code" class="plain"><pre name="code" class="plain">#include <stdio.h>    
  167. #include <stdlib.h>    
  168. #include <unistd.h>    
  169. #include <sys/ioctl.h>    
  170.      
  171. int main(int argc,char **argv)    
  172. {    
  173.     int i;    
  174.     int ret;    
  175.     int fd;    
  176.     char press_cnt;    
  177.     printf("Hi I am come in\n");  
  178.     sleep(5);  
  179.     printf("5 seconds after\n");    
  180.     fd=open("/dev/key_interrupt",0);  
  181.     printf("key_interrupt by open\n");    
  182.     if(fd<0)  {    
  183.         printf("Can't open /dev/interrupt \n");    
  184.         return -1;    
  185.     }    
  186.    
  187.     while(1) {    
  188.         printf("come in while(1)\n");  
  189.         ret = read(fd,&press_cnt,sizeof(press_cnt));    
  190.         if(ret<0)  {    
  191.             printf("read err !\n");    
  192.             continue;    
  193.         }    
  194.             if(press_cnt)    
  195.                 printf("Key%d has been pressed  \n",press_cnt);    
  196.    
  197.         
  198.     }            
  199.         
  200. }</pre><br>  
  201. 编译之后下载到开发板,使用insmod加载驱动程序、mknod创建设备节点、运行测试程序之后按下按键时就可以DNW上看到结果了,呵呵。  
  202. <pre></pre>  
  203. <pre></pre>  
  204.   
  205. </pre> 

0 0
原创粉丝点击