ARM-Linux下的GPIO中断程序


    今日为了调试ARM板上的GPIO引脚中断效果,以便在后续项目使用ARM与ZLG7290按键LED中断芯片连接中随意选择空闲的GPIO引脚来作为ZLG7290的中断信号线,特意编写了一个小的Linux GPIO中断驱动程序下载到开发板上做实验。经验证,这种软件中断方式也还差强人意。下面贴出自己编写的不成熟的代码,见笑(<-_->)。

    实验的硬件电路为ARM GPIO的PB17连接一个共阴LED,PB18与PB19连接,PB18由中断驱动设置为低电平触发,PB19由GPIO驱动程序控制,上层应用程序通过驱动控制PB19高低电平变化,从而引发PB18发生中断,中断程序中控制PB17的LED亮和灭。

    Linux中断驱动部分:    

 
  1. /*  
  2.  * PB18_IRQTest.c  
  3.  * This is  a test program for sam9260, using PB19(J5_18 pin) input a signal to PB18(J5_16 pin),  
  4.  * PB18 receive this signal as IRQ and make the LED linking on PB17((J5_14 pin)) turn on or turn off     
  5.  *  
  6.  *           @Author: Cun Tian Rui   
  7.  *           @Date :March.18.2011  
  8.  */  
  9.   
  10. #include <linux/types.h>   
  11. #include <linux/kernel.h>   
  12. #include <linux/module.h>   
  13. #include <linux/init.h>   
  14. #include <linux/platform_device.h>   
  15. #include <linux/cdev.h>   
  16. #include <linux/ioctl.h>   
  17. #include <linux/fs.h>   
  18. #include <linux/gpio.h>   
  19. #include <asm/arch/hardware.h>   
  20. #include <asm/arch/gpio.h>   
  21. #include <linux/interrupt.h>   
  22. #include <asm/io.h>   
  23. #include <asm/arch/board.h>   
  24. #include <linux/cdev.h>   
  25. #include <asm/arch/gpio.h>   
  26. #include <asm/uaccess.h>   
  27. #include <asm/io.h>   
  28. #include <asm/arch/at91_pio.h>   
  29. #include <asm/arch/at91_aic.h>   
  30. #include <asm/arch/at91_pmc.h>   
  31.   
  32. void led_on()   
  33. {       
  34.      at91_set_gpio_output(AT91_PIN_PB17,1);   
  35. }   
  36.   
  37. void led_off()   
  38. {       
  39.      at91_set_gpio_output(AT91_PIN_PB17 ,0);   
  40. }   
  41.   
  42. struct light_dev *light_devp;   
  43. int light_major = 200;   
  44.   
  45. struct light_dev   
  46. {   
  47.     struct cdev cdev;   
  48.     unsigned char value;   
  49. };   
  50.   
  51. MODULE_AUTHOR("Cun Tian Rui");   
  52. MODULE_LICENSE("Dual BSD/GPL");   
  53.   
  54.   
  55. static void io_init(void)   
  56. {   
  57.     at91_set_gpio_input(AT91_PIN_PB18, 1);           
  58.     at91_set_deglitch(AT91_PIN_PB18, 1);    
  59.     at91_sys_write(1 + PIO_IDR,  1<<18);   
  60.     at91_sys_write(1 + PIO_IER,  (~(1<<18)));   
  61.     at91_sys_write(AT91_PMC_PCER, 1 << 3);   
  62. }   
  63.   
  64.   
  65. struct gpio_irq_desc   
  66. {   
  67.     int irq;   
  68.     unsigned long flags;   
  69.     char *name;   
  70. };   
  71.   
  72. static struct gpio_irq_desc PB18_IRQ={AT91_PIN_PB18,AT91_AIC_SRCTYPE_LOW,"PB18"};   
  73.   
  74. static irqreturn_t PB18_intHandle(int irq, void *dev_id)   
  75. {   
  76.     led_on();   
  77.     return IRQ_RETVAL(IRQ_HANDLED);   
  78. }   
  79.   
  80. int light_open(struct inode *inode,struct file *filp)   
  81. {   
  82.     int err;   
  83.     struct light_dev *dev;   
  84.     dev = container_of(inode->i_cdev,struct light_dev,cdev);   
  85.     filp->private_data = dev;   
  86.     io_init();   
  87.     err = request_irq(PB18_IRQ.irq,PB18_intHandle,PB18_IRQ.flags,PB18_IRQ.name,(void*)0);   
  88.     if(err)    
  89.         {   
  90.         free_irq(PB18_IRQ.irq,(void*)0);   
  91.         return  -EBUSY;   
  92.     }   
  93.        
  94.     return 0;   
  95. }   
  96.   
  97. int light_release(struct inode *inode,struct file *filp)   
  98. {   
  99.     free_irq(PB18_IRQ.irq,(void*)0);   
  100.     return 0;       
  101. }   
  102.   
  103.   
  104.   
  105. // ioctl   
  106. int light_ioctl(struct inode *inode,struct file *filp,unsigned int cmd,   
  107. unsigned long arg)   
  108. {   
  109.     struct light_dev *dev = filp->private_data;   
  110.   
  111.     switch(cmd)   
  112.     {   
  113.         case 0:   
  114.             at91_set_gpio_output(AT91_PIN_PB19,0);        
  115.         break;   
  116.   
  117.         case 1:   
  118.           at91_set_gpio_output(AT91_PIN_PB19,1);   
  119.        led_off();   
  120.         break;   
  121.   
  122.         default:   
  123.   
  124.             return -ENOTTY;   
  125.         // break;   
  126.     }   
  127.   
  128.     return 0;   
  129. }        
  130.   
  131. struct file_operations light_fops =    
  132. {   
  133.     .owner = THIS_MODULE,   
  134.     .ioctl = light_ioctl,   
  135.     .open  = light_open,   
  136.     .release = light_release,   
  137. };   
  138.   
  139.   
  140. static void light_setup_cdev(struct light_dev *dev,int index)   
  141. {   
  142.     int err,devno = MKDEV(light_major,index);   
  143.   
  144.     cdev_init(&dev->cdev,&light_fops);   
  145.     dev->cdev.owner = THIS_MODULE;   
  146.     dev->cdev.ops = &light_fops;   
  147.   
  148.     err = cdev_add(&dev->cdev,devno,1);   
  149.   
  150.     if(err)   
  151.     {   
  152.         printk(KERN_NOTICE "Error %d adding LED%d",err,index);   
  153.     }   
  154. }   
  155.   
  156.   
  157. int light_init(void)   
  158. {   
  159.     int result;   
  160.   
  161.     dev_t dev = MKDEV(light_major,0);   
  162.     if(light_major)   
  163.     {   
  164.            
  165.         result = register_chrdev_region(dev,1,"PB18_IRQTest");   
  166.     }   
  167.   
  168.     if(result < 0)   
  169.     {   
  170.         return result;   
  171.     }   
  172.   
  173.     light_devp = kmalloc(sizeof(struct light_dev),GFP_KERNEL);   
  174.     if(!light_devp)   
  175.     {   
  176.         result = - ENOMEM;   
  177.         goto fail_malloc;   
  178.     }   
  179.   
  180.     memset(light_devp,0,sizeof(struct light_dev));   
  181.     light_setup_cdev(light_devp,0);   
  182.        
  183.   
  184.     return 0;   
  185.   
  186.     fail_malloc:unregister_chrdev_region(dev,light_devp);   
  187.     return result;   
  188.        
  189. }   
  190.   
  191. void light_cleanup(void)   
  192. {   
  193.     cdev_del(&light_devp->cdev);      
  194.     kfree(light_devp);   
  195.     unregister_chrdev_region(MKDEV(light_major,0),1);     
  196. }   
  197.   
  198. module_init(light_init);   
  199. module_exit(light_cleanup);          
  • 1
  • 2
  • 下一页

相关内容