输入系统之led灯控制

来源:互联网 发布:java项目输出日志文件 编辑:程序博客网 时间:2024/04/30 17:13

      目前下面的程序在卸载时会出现问题,原因有待查找,问题出现在input_unregister_device(),程序如下:

     

#include <linux/module.h>#include <linux/kernel.h>#include <linux/fs.h>#include <linux/init.h>#include <linux/delay.h>#include <asm/uaccess.h>#include <linux/gpio.h> #include <asm/irq.h>#include <linux/sched.h>   #include <linux/irq.h>#include <asm/io.h>#include <linux/device.h>#include <linux/interrupt.h>#include <linux/wait.h>#include <linux/cdev.h>#include <linux/platform_device.h>#include <linux/timer.h>#include <linux/poll.h>#include <linux/fcntl.h>#include <linux/input.h>#define DRVNAME "s5pv210_gpio"struct led_device_ops{        struct input_dev *input;        wait_queue_head_t my_waitqueue;        struct timer_list timer;        /* statistic timer */        int irq;        unsigned long virt;};static struct led_device_ops led_info;static uint32_t last_timer; static volatile int press = 0; struct pin_desc{        unsigned char key_val;};static unsigned char witch_key = 0;static struct pin_desc key_descs[8] ={     [0] = {         .key_val = KEY_1,     },     [1] = {         .key_val = KEY_2,     },      [2] = {         .key_val = KEY_3,     },      [3] = {         .key_val = KEY_4,     },      [4] = {         .key_val = KEY_5,     },      [5] = {         .key_val = KEY_6,     },      [6] = {          .key_val = KEY_7,     },      [7] = {         .key_val = KEY_8,     },  };volatile unsigned long *GPC0CON, *GPC0DAT;//用与存放两个个寄存器的地址volatile unsigned long *GPH0CON, *GPH0DAT;//按键static unsigned char KeyFlag;static void all_leds_off(void);static void led_config(void){        volatile unsigned long  phys;//用于存放虚拟地址和物理地址        phys = 0xE0200060;         led_info.virt =(unsigned long)ioremap(phys, 0xf00);        GPC0CON = (unsigned long *)(led_info.virt + 0x00);//指定需要操作的三个寄存器的地址        GPC0DAT = (unsigned long *)(led_info.virt + 0x04);        GPH0CON = (unsigned long *)(led_info.virt + 0xc00-0x60); //keY1配置为输入        GPH0DAT = (unsigned long *)(led_info.virt + 0xc00-0x60+0x04);        *GPC0CON &= ~(0xFF << 12);        *GPC0CON |= 0x11 << 12;                 // 配置GPC0_3和GPC0_4为输出        *GPH0CON &= ~0x0F; //配置为输入        all_leds_off();}static void led1_on(void){        *GPC0DAT |= 1 << 3;        *GPC0DAT &= ~(0x01 << 4);//      printk("led1 light\n");}static void led2_on(void){        *GPC0DAT |= 1 << 4;        *GPC0DAT &= ~(0x01 << 3);//      printk("led2 light\n");}static void all_leds_on(void){                *GPC0DAT |= 1 << 3;             // 点亮LED1                *GPC0DAT |= 1 << 4;             // 点亮LED2                printk("all leds light\n");}static void all_leds_off(void){        *GPC0DAT &= ~(0x3 << 3);                // 熄灭LED1和LED2        printk("all leds off\n");}static void led_timer_event(unsigned long arg){        press = 1;        KeyFlag = !KeyFlag;        if(KeyFlag)        {                led1_on();        }        else        {                        led2_on();        }        printk("Timer event time = %ld\n",jiffies-last_timer);        input_event(led_info.input, EV_KEY, witch_key, 0);        input_sync(led_info.input);}static irqreturn_t led_handler(int irq, void *devid){        struct pin_desc * pindesc = (struct pin_desc *)devid;        mod_timer(&led_info.timer,jiffies+HZ);  //这里设置定时中断程序多久之后执行,可适当变短些,        last_timer=jiffies;                                                                      //这里为了使程序实验效果更加明显,直接用1s        witch_key = pindesc->key_val;        printk("KERNEL:irq == %d  witch_key= %d\n",irq,witch_key);        return IRQ_RETVAL(IRQ_HANDLED); }static int led_device_open(struct inode *inode, struct file *file){        printk("led_drv_open\n");        file->private_data = &led_info;        return 0;}static int led_device_release(struct inode *inode, struct file *file){        return 0;}static const struct file_operations led_device_fileops = {        .owner   = THIS_MODULE,        .open    = led_device_open,        .release = led_device_release,};static int led_device_init(void){          int rc,i,error;                //struct led_device_ops *ddata;                //struct input_dev *input;                //ddata = kzalloc(sizeof(struct led_device_ops),GFP_KERNEL);                led_info.input = input_allocate_device();                if (!led_info.input) {                    printk(KERN_ERR"failed to allocate state\n");                    error = -ENOMEM;                    goto fail1;                }                //ddata->input = input;                led_info.input->name = "key_device";                set_bit(EV_KEY, led_info.input->evbit);                set_bit(KEY_1, led_info.input->keybit);                set_bit(KEY_2, led_info.input->keybit);                set_bit(KEY_3, led_info.input->keybit);                set_bit(KEY_4, led_info.input->keybit);                set_bit(KEY_5, led_info.input->keybit);                set_bit(KEY_6, led_info.input->keybit);                set_bit(KEY_7, led_info.input->keybit);                set_bit(KEY_8, led_info.input->keybit);                //led_info.input = ddata->input;                error = input_register_device(led_info.input);                if (error) {                                printk(KERN_ERR"Unable to register input device, error: %d\n",                                error);                                goto fail2;                }          input_sync(led_info.input);        for(i=0;i<5;i++)        {                    rc = request_irq(IRQ_EINT(i), &led_handler, IRQ_TYPE_EDGE_FALLING,"led_irq",  &key_descs[i]);                    if(rc)                    {                                    printk(KERN_ERR"function request_irq(%d) excute error\n",i);                                    goto led_request_irq_error;                    }                }                init_timer(&led_info.timer);                led_info.timer.function = led_timer_event;                add_timer(&led_info.timer);                led_config();                all_leds_off();                return 0; /* succeed */ led_request_irq_error:   fail2: fail1:                input_free_device(led_info.input);                return error;}static void led_device_exit(void){        iounmap((void *)led_info.virt); //撤销映射关系        free_irq(IRQ_EINT(0), &key_descs[0]);        free_irq(IRQ_EINT(1), &key_descs[1]);        free_irq(IRQ_EINT(2), &key_descs[2]);        free_irq(IRQ_EINT(3), &key_descs[3]);        free_irq(IRQ_EINT(4), &key_descs[4]);        printk("led_drv_exit ....excute ok\n");        //all_leds_off();        printk("led_drv_exit ....excute ok0\n");        printk("led_drv_exit ....excute ok1\n");        printk("led_drv_exit ....excute ok2\n");         input_free_device(led_info.input);        printk("led_drv_exit ....excute ok3\n");         input_unregister_device(led_info.input); //此处有段错误出现        printk("led_drv_exit ....excute ok4\n");  }module_init(led_device_init);module_exit(led_device_exit);MODULE_AUTHOR("Ethyn blog:http://blog.csdn.net/humanspider1");MODULE_DESCRIPTION("cortex a8 S5pv210 led test Driver");


0 0
原创粉丝点击