基於platform的ok6410按鍵中斷實驗

plat_btn_device.c

  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

  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

  1. /* 
  2.  *      Buttons Example for Matrix V 
  3.  * 
  4.  *      Copyright (C) 2004 capbily - friendly-arm 
  5.  *  [email protected] 
  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:

  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



實驗結果如下:



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章