GPIO中断


主要功能:通过两个GPIO(S5PV210_GPJ2(7)和S5PV210_GPJ3(0))作为输出,来控制两个作为中断的GPIO(S5PV210_GPH1(4)和S5PV210_GPH1(2)),从而触发两个LED灯( S5PV210_GPH0(6)和S5PV210_GPH0(7))。


主要参考文件linux/interrupt.h, kernel/irq/manage.c, linux/irq.h, kernel/arch/arm/mach-s5pv210/include/mach/irqs.h, kernel/arch/arm/mach-s5pv210/include/mach/gpiolib.c

GPIO中断申请的主要步骤:

1.GPIO注册

2.GPIO中断设置

3.设置GPIO中断的触发方式

4.使能GPIO中断

5.中断注册


GPIO中断驱动

点击(此处)折叠或打开

  1. /*
  2.  * gpio_light.c
  3.  * @Date :11.15.2012
  4.  */
  5.    
  6. #include <mach/irqs.h>
  7. #include <asm/uaccess.h>
  8. #include <mach/regs-gpio.h>
  9. #include <mach/hardware.h>
  10. #include <linux/interrupt.h>
  11. #include <linux/cdev.h>
  12. #include <linux/device.h>
  13. #include <linux/errno.h>
  14. #include <linux/fs.h>
  15. #include <linux/gpio.h>
  16. #include <linux/init.h>
  17. #include <linux/irq.h>
  18. #include <linux/kernel.h>
  19. #include <linux/module.h>
  20. #include <linux/types.h>



  21. #define LIGHT_ON    1
  22. #define LIGHT_OFF    0

  23. #define DEVICE_NAME    "gpio_light"
  24. #define CLASS_NAME    "light_class"

  25. static dev_t devid;
  26. static struct cdev light_cdev;
  27. static struct class *light_class;

  28. static struct gpio gpios_light[] = {
  29.     { S5PV210_GPH0(6), GPIOF_OUT_INIT_HIGH, "LED1" },
  30.     { S5PV210_GPH0(7), GPIOF_OUT_INIT_HIGH, "LED2" },
  31.     { S5PV210_GPJ2(7), GPIOF_OUT_INIT_LOW, "CONTROL1" },
  32.     { S5PV210_GPJ3(0), GPIOF_OUT_INIT_LOW, "CONTROL2" },
  33. };

  34. struct gpio_irqs_desc {
  35.     int irq;
  36.     int irq_type;
  37.     int pin;
  38.     int pin_setting;
  39.     int number;
  40.     char *name;
  41. };
  42. static struct gpio_irqs_desc gpio_irqs [] = {
  43.     {IRQ_EINT12, IRQ_TYPE_EDGE_RISING, S5PV210_GPH1(4), S3C_GPIO_SFN(0xf), 0, "GPIO_IRQ_LED1"},
  44.     {IRQ_EINT10, IRQ_TYPE_EDGE_RISING, S5PV210_GPH1(2), S3C_GPIO_SFN(0xf), 1, "GPIO_IRQ_LED2"},
  45. };


  46. void led_on(int cmd)
  47. {
  48.      gpio_set_value(gpios_light[cmd].gpio, 0);
  49.      printk("Sucess to turn on the %s ! \n", gpios_light[cmd].label);
  50. }
  51. void led_off(int cmd)
  52. {
  53.      gpio_set_value(gpios_light[cmd].gpio, 1);
  54.      printk("Sucess to turn off the %s ! \n", gpios_light[cmd].label);
  55. }
  56.       
  57. static irqreturn_t light_intHandle(int irq, void *dev_id)
  58. {
  59.     struct gpio_irqs_desc *gpio_irqs = (struct gpio_irqs_desc *)dev_id;
  60.     led_on(gpio_irqs->number);
  61.     printk("Sucess to link GPIO with LED ! \n");
  62.     return IRQ_HANDLED;
  63. }
  64.   
  65. static void real_gpio_irqs_init(void)
  66. {
  67.     int err, i;
  68.     for (i = 0; i < sizeof(gpio_irqs)/sizeof(gpio_irqs[0]); i++)
  69.     {
  70.         err = gpio_request(gpio_irqs[i].pin, gpio_irqs[i].name); //1.GPIO注册
  71.         if (err) {
  72.             pr_err("Failed to request %s ! \n", gpio_irqs[i].name);
  73.         }

  74.         err = s3c_gpio_cfgpin(gpio_irqs [i].pin, gpio_irqs[i].pin_setting); //2.将GPIO设置为中断状态
  75.         if (err) {
  76.             pr_err("Failed to set the %s with interrupting !\n",
  77.                     gpio_irqs[i].name);
  78.         }

  79.         set_irq_type(gpio_irqs[i].irq, gpio_irqs [i].irq_type); //3.设置GPIO中断的触发方式

  80.         disable_irq(gpio_irqs[i].irq);
  81.         enable_irq(gpio_irqs[i].irq); //4.使能GPIO中断
  82.         err = request_irq(gpio_irqs[i].irq,light_intHandle, 0,gpio_irqs[i].name, //5.中断注册
  83.                         (void *)&gpio_irqs[i]);
  84.         printk("request_irq = %d !!!\n", err);
  85.         if(err)
  86.             pr_err("Failed to request the %s ! \n", gpio_irqs[i].name);
  87.     }

  88. }

  89. static int gpios_light_open(struct inode *inode, struct file *filp)
  90. {
  91.     int err;
  92.     printk("Sucess to open the gpios_light_open ! \n");
  93.     real_gpio_irqs_init();//完成GPIO中断注册
  94.     err = gpio_request_array(gpios_light, ARRAY_SIZE(gpios_light));
  95.     if (err) {
  96.         pr_err("Failed to request GPIO LIGHT ! \n");
  97.     }
  98.     return err;
  99. }

  100. static int gpios_light_close(struct inode *inode, struct file *filp)
  101. {
  102.     int i;
  103.     for (i = 0; i < sizeof(gpio_irqs)/sizeof(gpio_irqs[0]); i++)
  104.     {
  105.         free_irq(gpio_irqs[i].irq,(void *)&gpio_irqs[i]);
  106.         gpio_free(gpio_irqs[i].pin);
  107.     }


  108.     gpio_free_array(gpios_light, ARRAY_SIZE(gpios_light));
  109.     pr_err("Sucess to close ! \n");
  110.     return 0;
  111. }

  112. static int gpios_light_ioctl(struct inode *inode, struct file *filp,
  113.         unsigned int cmd, unsigned long arg)
  114. {
  115.     switch (cmd) {
  116.         case LIGHT_ON:
  117.             gpio_set_value(gpios_light[arg + 1].gpio, 1);
  118.             break;
  119.         case LIGHT_OFF:
  120.             gpio_set_value(gpios_light[arg + 1].gpio, 0);
  121.             led_off(arg-1);
  122.             break;
  123.         default:
  124.             return -EINVAL;
  125.     }
  126.     return 0;
  127. }


  128. static struct file_operations gpio_light_fops = {

  129.     .owner        = THIS_MODULE,
  130.     .open        = gpios_light_open,
  131.     .release    = gpios_light_close,
  132.     .ioctl        = gpios_light_ioctl,
  133. };

  134. static int __init gpio_light_init(void)
  135. {
  136.     int err;
  137.     struct device *pdev;

  138.     err = alloc_chrdev_region(&devid, 0, 1, DEVICE_NAME);
  139.     if (err < 0) {
  140.         pr_err("Failed to allocate LIGHT device numbers\n");
  141.         goto fail;
  142.     }

  143.     cdev_init(&light_cdev, &gpio_light_fops);
  144.     light_cdev.owner = THIS_MODULE;
  145.     err = cdev_add(&light_cdev, devid, 1);
  146.     if (err < 0) {
  147.         pr_err("Failed to add LIGHT device\n");
  148.         goto unregister_dev_num;
  149.     }

  150.     light_class = class_create(THIS_MODULE, CLASS_NAME);
  151.     if (IS_ERR(light_class)) {
  152.         pr_err("Failed to create LIGHT class\n");
  153.         err = PTR_ERR(light_class);
  154.         goto delete_cdev;
  155.     }

  156.     pdev = device_create(light_class, NULL, devid, NULL, DEVICE_NAME);
  157.     if (IS_ERR(pdev)) {
  158.         pr_err("Failed to create LIGHT device\n");
  159.         err = PTR_ERR(pdev);
  160.         goto destroy_class;
  161.     }

  162.     return 0;

  163. destroy_class:
  164.     class_destroy(light_class);

  165. delete_cdev:
  166.     cdev_del(&light_cdev);

  167. unregister_dev_num:
  168.     unregister_chrdev_region(devid, 1);

  169. fail:
  170.     return err;
  171. }

  172. static void __exit gpio_light_exit(void)
  173. {
  174.     device_destroy(light_class, devid);
  175.     class_destroy(light_class);
  176.     cdev_del(&light_cdev);
  177.     unregister_chrdev_region(devid, 1);
  178. }

  179. module_init(gpio_light_init);
  180. module_exit(gpio_light_exit);
  181. MODULE_LICENSE("GPL");


测试程序

点击(此处)折叠或打开

  1. /*
  2.  * lighttest.c
  3.  *
  4.  * Created on: 2012-11-13
  5.  *
  6.  */

  7. #include <stdio.h>
  8. #include <fcntl.h>
  9. #include <unistd.h>
  10. #include <errno.h>
  11. #include <string.h>
  12. #include <sys/ioctl.h>

  13. #define DEVICE_PATH        "/dev/gpio_light"

  14. int main(void)
  15. {
  16.     int fd;
  17.     int input,led;

  18.     fd = open(DEVICE_PATH, O_RDWR);
  19.     printf("open = %d\n", fd);
  20.     if (fd == -1)
  21.     {
  22.         perror("Can't open " DEVICE_PATH);
  23.         return fd;
  24.     }else
  25.         printf("Sucess to open " DEVICE_PATH);

  26.     printf("\nPlease input which led (1, 2)\n");
  27.     printf("and input switch mode (1, 0):\n");
  28.     while (scanf("%d %d",&led, &input) == 2) {
  29.         int ret = ioctl(fd, input, led);    
  30.         printf("ret = %d \n",ret);
  31.     }

  32.     close(fd);
  33.     return 0;
  34. }


你可能感兴趣的:(GPIO中断)