主要功能:通过两个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中断驱动
- /*
- * gpio_light.c
- * @Date :11.15.2012
- */
-
- #include <mach/irqs.h>
- #include <asm/uaccess.h>
- #include <mach/regs-gpio.h>
- #include <mach/hardware.h>
- #include <linux/interrupt.h>
- #include <linux/cdev.h>
- #include <linux/device.h>
- #include <linux/errno.h>
- #include <linux/fs.h>
- #include <linux/gpio.h>
- #include <linux/init.h>
- #include <linux/irq.h>
- #include <linux/kernel.h>
- #include <linux/module.h>
- #include <linux/types.h>
- #define LIGHT_ON 1
- #define LIGHT_OFF 0
- #define DEVICE_NAME "gpio_light"
- #define CLASS_NAME "light_class"
- static dev_t devid;
- static struct cdev light_cdev;
- static struct class *light_class;
- static struct gpio gpios_light[] = {
- { S5PV210_GPH0(6), GPIOF_OUT_INIT_HIGH, "LED1" },
- { S5PV210_GPH0(7), GPIOF_OUT_INIT_HIGH, "LED2" },
- { S5PV210_GPJ2(7), GPIOF_OUT_INIT_LOW, "CONTROL1" },
- { S5PV210_GPJ3(0), GPIOF_OUT_INIT_LOW, "CONTROL2" },
- };
- struct gpio_irqs_desc {
- int irq;
- int irq_type;
- int pin;
- int pin_setting;
- int number;
- char *name;
- };
- static struct gpio_irqs_desc gpio_irqs [] = {
- {IRQ_EINT12, IRQ_TYPE_EDGE_RISING, S5PV210_GPH1(4), S3C_GPIO_SFN(0xf), 0, "GPIO_IRQ_LED1"},
- {IRQ_EINT10, IRQ_TYPE_EDGE_RISING, S5PV210_GPH1(2), S3C_GPIO_SFN(0xf), 1, "GPIO_IRQ_LED2"},
- };
- void led_on(int cmd)
- {
- gpio_set_value(gpios_light[cmd].gpio, 0);
- printk("Sucess to turn on the %s ! \n", gpios_light[cmd].label);
- }
- void led_off(int cmd)
- {
- gpio_set_value(gpios_light[cmd].gpio, 1);
- printk("Sucess to turn off the %s ! \n", gpios_light[cmd].label);
- }
-
- static irqreturn_t light_intHandle(int irq, void *dev_id)
- {
- struct gpio_irqs_desc *gpio_irqs = (struct gpio_irqs_desc *)dev_id;
- led_on(gpio_irqs->number);
- printk("Sucess to link GPIO with LED ! \n");
- return IRQ_HANDLED;
- }
-
- static void real_gpio_irqs_init(void)
- {
- int err, i;
- for (i = 0; i < sizeof(gpio_irqs)/sizeof(gpio_irqs[0]); i++)
- {
- err = gpio_request(gpio_irqs[i].pin, gpio_irqs[i].name); //1.GPIO注册
- if (err) {
- pr_err("Failed to request %s ! \n", gpio_irqs[i].name);
- }
- err = s3c_gpio_cfgpin(gpio_irqs [i].pin, gpio_irqs[i].pin_setting); //2.将GPIO设置为中断状态
- if (err) {
- pr_err("Failed to set the %s with interrupting !\n",
- gpio_irqs[i].name);
- }
- set_irq_type(gpio_irqs[i].irq, gpio_irqs [i].irq_type); //3.设置GPIO中断的触发方式
- disable_irq(gpio_irqs[i].irq);
- enable_irq(gpio_irqs[i].irq); //4.使能GPIO中断
- err = request_irq(gpio_irqs[i].irq,light_intHandle, 0,gpio_irqs[i].name, //5.中断注册
- (void *)&gpio_irqs[i]);
- printk("request_irq = %d !!!\n", err);
- if(err)
- pr_err("Failed to request the %s ! \n", gpio_irqs[i].name);
- }
- }
- static int gpios_light_open(struct inode *inode, struct file *filp)
- {
- int err;
- printk("Sucess to open the gpios_light_open ! \n");
- real_gpio_irqs_init();//完成GPIO中断注册
- err = gpio_request_array(gpios_light, ARRAY_SIZE(gpios_light));
- if (err) {
- pr_err("Failed to request GPIO LIGHT ! \n");
- }
- return err;
- }
- static int gpios_light_close(struct inode *inode, struct file *filp)
- {
- int i;
- for (i = 0; i < sizeof(gpio_irqs)/sizeof(gpio_irqs[0]); i++)
- {
- free_irq(gpio_irqs[i].irq,(void *)&gpio_irqs[i]);
- gpio_free(gpio_irqs[i].pin);
- }
- gpio_free_array(gpios_light, ARRAY_SIZE(gpios_light));
- pr_err("Sucess to close ! \n");
- return 0;
- }
- static int gpios_light_ioctl(struct inode *inode, struct file *filp,
- unsigned int cmd, unsigned long arg)
- {
- switch (cmd) {
- case LIGHT_ON:
- gpio_set_value(gpios_light[arg + 1].gpio, 1);
- break;
- case LIGHT_OFF:
- gpio_set_value(gpios_light[arg + 1].gpio, 0);
- led_off(arg-1);
- break;
- default:
- return -EINVAL;
- }
- return 0;
- }
- static struct file_operations gpio_light_fops = {
- .owner = THIS_MODULE,
- .open = gpios_light_open,
- .release = gpios_light_close,
- .ioctl = gpios_light_ioctl,
- };
- static int __init gpio_light_init(void)
- {
- int err;
- struct device *pdev;
- err = alloc_chrdev_region(&devid, 0, 1, DEVICE_NAME);
- if (err < 0) {
- pr_err("Failed to allocate LIGHT device numbers\n");
- goto fail;
- }
- cdev_init(&light_cdev, &gpio_light_fops);
- light_cdev.owner = THIS_MODULE;
- err = cdev_add(&light_cdev, devid, 1);
- if (err < 0) {
- pr_err("Failed to add LIGHT device\n");
- goto unregister_dev_num;
- }
- light_class = class_create(THIS_MODULE, CLASS_NAME);
- if (IS_ERR(light_class)) {
- pr_err("Failed to create LIGHT class\n");
- err = PTR_ERR(light_class);
- goto delete_cdev;
- }
- pdev = device_create(light_class, NULL, devid, NULL, DEVICE_NAME);
- if (IS_ERR(pdev)) {
- pr_err("Failed to create LIGHT device\n");
- err = PTR_ERR(pdev);
- goto destroy_class;
- }
- return 0;
- destroy_class:
- class_destroy(light_class);
- delete_cdev:
- cdev_del(&light_cdev);
- unregister_dev_num:
- unregister_chrdev_region(devid, 1);
- fail:
- return err;
- }
- static void __exit gpio_light_exit(void)
- {
- device_destroy(light_class, devid);
- class_destroy(light_class);
- cdev_del(&light_cdev);
- unregister_chrdev_region(devid, 1);
- }
- module_init(gpio_light_init);
- module_exit(gpio_light_exit);
- MODULE_LICENSE("GPL");
测试程序
- /*
- * lighttest.c
- *
- * Created on: 2012-11-13
- *
- */
- #include <stdio.h>
- #include <fcntl.h>
- #include <unistd.h>
- #include <errno.h>
- #include <string.h>
- #include <sys/ioctl.h>
- #define DEVICE_PATH "/dev/gpio_light"
- int main(void)
- {
- int fd;
- int input,led;
- fd = open(DEVICE_PATH, O_RDWR);
- printf("open = %d\n", fd);
- if (fd == -1)
- {
- perror("Can't open " DEVICE_PATH);
- return fd;
- }else
- printf("Sucess to open " DEVICE_PATH);
- printf("\nPlease input which led (1, 2)\n");
- printf("and input switch mode (1, 0):\n");
- while (scanf("%d %d",&led, &input) == 2) {
- int ret = ioctl(fd, input, led);
- printf("ret = %d \n",ret);
- }
- close(fd);
- return 0;
- }
阅读(3047) | 评论(1) | 转发(1) |