基于platform的ok6410按键中断实验

来源:互联网 发布:在淘宝买电脑可靠吗 编辑:程序博客网 时间:2024/05/17 23:55

plat_btn_device.c

[cpp] view plaincopy
  1. #include <linux/module.h>  
  2. #include <linux/types.h>  
  3. #include <linux/fs.h>  
  4. #include <linux/init.h>  
  5. #include <linux/platform_device.h>  
  6. #include <linux/interrupt.h>  
  7. #include <linux/device.h>  
  8. #include <linux/io.h>  
  9.   
  10.   
  11. #define DEVICE_NAME "ok6410_plat_btn"  
  12.   
  13.   
  14. /*平台资源的定义,按键中断*/  
  15. static struct resource s3c_buttons_resource[] = {  
  16.     [0]={  
  17.         .start = IRQ_EINT(0),  
  18.         .end   = IRQ_EINT(0),  
  19.         .flags = IORESOURCE_IRQ,  
  20.     },  
  21.     [1]={  
  22.         .start = IRQ_EINT(1),  
  23.         .end   = IRQ_EINT(1),  
  24.         .flags = IORESOURCE_IRQ,  
  25.     },  
  26.     [2]={  
  27.         .start = IRQ_EINT(2),  
  28.         .end   = IRQ_EINT(2),  
  29.         .flags = IORESOURCE_IRQ,  
  30.     },  
  31.     [3]={  
  32.         .start = IRQ_EINT(3),  
  33.         .end   = IRQ_EINT(3),  
  34.         .flags = IORESOURCE_IRQ,  
  35.     },  
  36.     [4]={  
  37.         .start = IRQ_EINT(4),  
  38.         .end   = IRQ_EINT(4),  
  39.         .flags = IORESOURCE_IRQ,  
  40.     },  
  41.     [5]={  
  42.         .start = IRQ_EINT(5),  
  43.         .end   = IRQ_EINT(5),  
  44.         .flags = IORESOURCE_IRQ,  
  45.     }  
  46. };  
  47.   
  48. static struct platform_device *s3c_buttons;  
  49.   
  50.   
  51. static int __init platform_init(void)  
  52. {  
  53.   
  54.     s3c_buttons = platform_device_alloc(DEVICE_NAME,-1);  
  55.   
  56.     //为平台设备s3c_buttons添加平台资源  
  57.     platform_device_add_resources(s3c_buttons,&s3c_buttons_resource,6);  
  58.   
  59.     /*平台设备的注册*/  
  60.     platform_device_add(s3c_buttons);  
  61.   
  62.   
  63. }  
  64.   
  65. static void __exit platform_exit(void)  
  66. {  
  67.     platform_device_unregister(s3c_buttons);  
  68. }  
  69.   
  70. module_init(platform_init);  
  71. module_exit(platform_exit);  
  72.   
  73. MODULE_AUTHOR("Sola");  
  74. MODULE_LICENSE("GPL");  
  75. MODULE_ALIAS("platform:ok6410_buttons");  




plat_btn_driver.c

[cpp] view plaincopy
  1. #include <linux/module.h>  
  2. #include <linux/types.h>  
  3. #include <linux/miscdevice.h>  
  4. #include <linux/fs.h>  
  5. #include <linux/init.h>  
  6. #include <linux/platform_device.h>  
  7. #include <linux/interrupt.h>  
  8. #include <linux/clk.h>  
  9. #include <linux/uaccess.h>  
  10. #include <linux/io.h>  
  11. #include <mach/map.h>  
  12. #include <linux/poll.h>  
  13. #include <linux/irq.h>  
  14. #include <asm/unistd.h>  
  15. #include <linux/device.h>  
  16.   
  17.   
  18. #define DRIVER_NAME "ok6410_plat_btn"  
  19.   
  20.   
  21. //定义并初始化等待队列头  
  22. static DECLARE_WAIT_QUEUE_HEAD(button_waitq);  
  23.   
  24. static volatile int ev_press = 0;  
  25.   
  26.   
  27. static int key_value;  
  28. static struct device     *buttons_dev;  /* platform device attached to */  
  29. static struct resource   *buttons_irq;  
  30.   
  31.   
  32. static int button_irqs[6];//中断号  
  33.   
  34.   
  35.   
  36.   
  37. /*按键中断处理函数*/  
  38. static irqreturn_t buttons_interrupt(int irq, void *dev_id)  
  39. {  
  40.     int i;  
  41.     for(i=0; i<6; i++){  
  42.         if(irq == button_irqs[i]){  
  43.             //printk("==>interrput number:%d\n",irq);    
  44.             key_value = i;  
  45.             ev_press =1;  
  46.             wake_up_interruptible(&button_waitq);         
  47.         }  
  48.     }  
  49.       
  50.     return IRQ_RETVAL(IRQ_HANDLED);  
  51.       
  52. }  
  53.   
  54.   
  55.   
  56. static int s3c6410_buttons_open(struct inode *inode, struct file *file)  
  57. {  
  58.     int i;  
  59.     int err = 0;  
  60.     /*注册中断*/  
  61.     for(i=0; i<6; i++){  
  62.         if (button_irqs[i] < 0)   
  63.             continue;  
  64.                               
  65.         /*中断触发方式:下降沿触发,中断接口函数*/  
  66.         err = request_irq(button_irqs[i],buttons_interrupt,IRQF_TRIGGER_FALLING,NULL,NULL);  
  67.         if(err)  
  68.           break;  
  69.     }  
  70.   
  71.     if (err) {  
  72.         i--;  
  73.         for (; i >= 0; i--) {  
  74.             if (button_irqs[i] < 0) {  
  75.                 continue;  
  76.             }  
  77.             disable_irq(button_irqs[i]);  
  78.             free_irq(button_irqs[i], NULL);  
  79.         }  
  80.         return -EBUSY;  
  81.     }  
  82.   
  83.     ev_press = 0;     
  84.     return 0;  
  85. }  
  86.   
  87. static int s3c6410_buttons_close(struct inode *inode, struct file *file)  
  88. {  
  89.     int i;      
  90.     for (i=0; i<6; i++) {  
  91.             if (button_irqs[i] < 0) {  
  92.                 continue;  
  93.             }  
  94.             free_irq(button_irqs[i],NULL);  
  95.     }  
  96.     return 0;  
  97. }  
  98.   
  99. static int s3c6410_buttons_read(struct file *filp, char __user *buff, size_t count, loff_t *offp)  
  100. {  
  101.     unsigned long err;  
  102.     if (!ev_press) {//如果键没有被按下  
  103.         if (filp->f_flags & O_NONBLOCK)//如果是非阻塞模式,就直接返回  
  104.             return -EAGAIN;  
  105.         else  
  106.             //阻塞,直到按键按下  
  107.             wait_event_interruptible(button_waitq, ev_press);  
  108.     }      
  109.     ev_press = 0;  
  110.       
  111.     //将键值送回到用户空间  
  112.     err = copy_to_user(buff, &key_value, sizeof(key_value));  
  113.     return sizeof(key_value);  
  114. }  
  115.   
  116. static unsigned int s3c6410_buttons_poll( struct file *file, struct poll_table_struct *wait)  
  117. {  
  118.     unsigned int mask = 0;  
  119.     poll_wait(file, &button_waitq, wait);//添加等待队列头  
  120.     if (ev_press){  
  121.         mask |= POLLIN | POLLRDNORM;  
  122.     }  
  123.       
  124.     //返回掩码  
  125.     return mask;  
  126. }  
  127.   
  128.   
  129.   
  130. static struct file_operations ok6410_buttons_fops = {  
  131.     .owner   =   THIS_MODULE,  
  132.     .open    =   s3c6410_buttons_open,  
  133.     .release =   s3c6410_buttons_close,  
  134.     .read    =   s3c6410_buttons_read,  
  135.     .poll    =   s3c6410_buttons_poll,  
  136. };  
  137.   
  138.   
  139.   
  140. //声明一个混杂设备,设备名称为"buttons"  
  141. static struct miscdevice ok6410_miscdev = {  
  142.       
  143.     .minor = MISC_DYNAMIC_MINOR,  
  144.     .name ="buttons",  
  145.     .fops = &ok6410_buttons_fops,//操作集  
  146. };  
  147.   
  148. /* device interface ,当发现匹配设备时会调用此函数*/  
  149. static int ok6410_buttons_probe(struct platform_device *pdev)  
  150. {  
  151.     struct resource *res;  
  152.     struct device *dev;  
  153.     int ret;  
  154.     int size;  
  155.     int i;  
  156.       
  157.     printk("probe:%s\n", __func__);  
  158.     dev = &pdev->dev;  
  159.     buttons_dev = &pdev->dev;  
  160.       
  161.     /*平台资源获取*/  
  162.  /*get irq number*/  
  163.   for(i=0; i<6; i++){  
  164.     //获取中断号  
  165.      buttons_irq = platform_get_resource(pdev,IORESOURCE_IRQ,i);  
  166.      if(buttons_irq == NULL){  
  167.         dev_err(dev,"no irq resource specified\n");  
  168.           ret = -ENOENT;  
  169.         return ret;  
  170.     }  
  171.     button_irqs[i] = buttons_irq->start;  
  172.     //printk("button_irqs[%d]=%d\n",i,button_irqs[i]);    
  173.     }  
  174.       
  175.     //注册混杂设备  
  176.     ret = misc_register(&ok6410_miscdev);  
  177.           
  178.       
  179.   
  180.     return ret;  
  181. }  
  182.   
  183. static int ok6410_buttons_remove(struct platform_device *dev)  
  184. {  
  185.       
  186.     misc_deregister(&ok6410_miscdev);  
  187.     return 0;  
  188. }  
  189.   
  190. /*平台驱动定义*/  
  191. static struct platform_driver ok6410_buttons_driver = {  
  192.     .probe      = ok6410_buttons_probe,//探针函数  
  193.     .remove     = ok6410_buttons_remove,  
  194.     .driver     = {  
  195.         .owner  = THIS_MODULE,  
  196.         .name   = DRIVER_NAME,  
  197.     },  
  198. };  
  199.   
  200. static char banner[] __initdata =  
  201.      "ok6410 Buttons Driver\n";  
  202.   
  203. static int __init buttons_init(void)  
  204. {  
  205.     printk(banner);  
  206.     /*平台驱动注册*/  
  207.     platform_driver_register(&ok6410_buttons_driver);  
  208.     return 0;  
  209. }  
  210.   
  211. static void __exit buttons_exit(void)  
  212. {  
  213.     //平台驱动的注销  
  214.     platform_driver_unregister(&ok6410_buttons_driver);  
  215. }  
  216.   
  217. module_init(buttons_init);  
  218. module_exit(buttons_exit);  
  219.   
  220. MODULE_AUTHOR("David Xie");  
  221. MODULE_DESCRIPTION("ok6410 Buttons Driver");  
  222. MODULE_LICENSE("GPL");  




测试程序:

app-button.c

[cpp] view plaincopy
  1. /* 
  2.  *      Buttons Example for Matrix V 
  3.  * 
  4.  *      Copyright (C) 2004 capbily - friendly-arm 
  5.  *  capbily@hotmail.com 
  6.  */  
  7. #include <stdio.h>  
  8. #include <stdlib.h>  
  9. #include <unistd.h>  
  10. #include <sys/ioctl.h>  
  11. #include <sys/types.h>  
  12. #include <sys/stat.h>  
  13. #include <fcntl.h>  
  14. #include <sys/select.h>  
  15. #include <sys/time.h>  
  16. #include <errno.h>  
  17.   
  18. int main(void)  
  19. {  
  20.     int buttons_fd;  
  21.     int key_value;  
  22.   
  23.     buttons_fd = open("/dev/buttons", 0);  
  24.     if (buttons_fd < 0) {  
  25.         perror("open device buttons");  
  26.         exit(1);  
  27.     }  
  28.   
  29.     for (;;) {  
  30.         fd_set rds;  
  31.         int ret;  
  32.   
  33.         FD_ZERO(&rds);  
  34.         FD_SET(buttons_fd, &rds);  
  35.   
  36.         ret = select(buttons_fd + 1, &rds, NULL, NULL, NULL);  
  37.         if (ret < 0) {  
  38.             perror("select");  
  39.             exit(1);  
  40.         }  
  41.         if (ret == 0) {  
  42.             printf("Timeout.\n");  
  43.         } else if (FD_ISSET(buttons_fd, &rds)) {  
  44.             int ret = read(buttons_fd, &key_value, sizeof key_value);  
  45.             if (ret != sizeof key_value) {  
  46.                 if (errno != EAGAIN)  
  47.                     perror("read buttons\n");  
  48.                 continue;  
  49.             } else {  
  50.                 printf("buttons_value: %d\n", key_value+1);  
  51.             }  
  52.                   
  53.         }  
  54.     }  
  55.   
  56.     close(buttons_fd);  
  57.     return 0;  
  58. }  




Makefile:

[plain] view plaincopy
  1. ifneq ($(KERNELRELEASE),)  
  2.   
  3. obj-m := plat_btn_device.o plat_btn_driver.o  
  4.   
  5. else  
  6.       
  7. KDIR := /home/ok6410/kernel/linux2.6.28  
  8. all:  
  9.     make -C $(KDIR) M=$(PWD) modules ARCH=arm CROSS_COMPILE=arm-linux-  
  10. clean:  
  11.     rm -f *.ko *.o *.mod.o *.mod.c *.symvers  modul*  
  12.   
  13. endif  





实验步骤,分别编译生成内核模块plat_btn_drvice.ko     plat_btn_driver.ko

然后先加载plat_btn_device.ko内核模块,再加载plat_tbn_driver.ko



最后运行测试程序:app-button



实验结果如下:



原创粉丝点击