mini2440的按键驱动

来源:互联网 发布:php pack("h*") 编辑:程序博客网 时间:2024/05/17 21:36
#include <linux/types.h>#include <linux/fs.h>#include <linux/errno.h>#include <linux/mm.h>#include <linux/sched.h>#include <linux/init.h>#include <linux/cdev.h>#include <asm/io.h>#include <asm/system.h>#include <asm/uaccess.h>#include <linux/interrupt.h>#include <linux/irq.h>#include <linux/miscdevice.h>#include <linux/poll.h>#include <linux/delay.h>// 混杂设备的次设备号#define DEV_MINOR 1000#define DEV_NAME "button"#define GPGCON 0x56000060#define GPGDATA 0x56000064DECLARE_WAIT_QUEUE_HEAD(dev_queue);unsigned int * dev_con = NULL;unsigned int * dev_data = NULL;// 按键的状态,默认的时候是没有按键按下unsigned char volatile key_flag = 0;// 按键值unsigned char volatile key_value = 0;MODULE_LICENSE("GPL");struct dev_str {    int irq;    int num;    char * name;};static struct dev_str dev[4]= {    {IRQ_EINT8,1,"key1",},{IRQ_EINT11,2,"key2",},{IRQ_EINT13,3,"key3",},{IRQ_EINT14,4,"key4",}};static irqreturn_t  intterrupt_ser(int irq, void *dev_id){    struct dev_str * button = (struct dev_str *)dev_id;    unsigned int ret = 0;    mdelay(3);    //udelay(3);    // 读取按键值    ret = ioread32(dev_data);    if ((ret & 0x01) && !key_flag)     {        key_flag = 1;        key_value = button->num;        wake_up_interruptible(&dev_queue);    }    if ((ret & 0x08) && !key_flag)     {        key_flag = 1;        key_value = button->num;        wake_up_interruptible(&dev_queue);    }    if ((ret & 0x20) && !key_flag)     {        key_flag = 1;        key_value = button->num;        wake_up_interruptible(&dev_queue);    }    if ((ret & 0x40) && !key_flag)     {        key_flag = 1;        key_value = button->num;        wake_up_interruptible(&dev_queue);    }    return IRQ_RETVAL(IRQ_HANDLED);    }int dev_open (struct inode * dev_inode, struct file * dev_file){    int err = -1;int i = 0 ;    printk ("pi");    dev_con = ioremap (GPGCON, 4);        dev_data = ioremap (GPGDATA, 4);     // 端口为中断方式    *dev_con &= ~( (0x03<<0) | (0x03<<6) | (0x03<<10) | (0x03<<12) );*dev_con |=  ( (0x02<<0) | (0x02<<6) | (0x02<<10) | (0x02<<12) );    // 注册中断,上升沿中断for(i = 0;i < 4;i++){    err = request_irq (dev[i].irq, intterrupt_ser, IRQ_TYPE_EDGE_RISING, dev[i].name, (void *)&dev[i]);    if (err)    {        disable_irq (dev[i].irq);        free_irq (dev[i].irq, (void *)&dev[i]);        return -EBUSY;    }key_flag = 0;}    //key_flag = 0;    return 0;}int dev_close (struct inode * dev_inode, struct file * dev_file){int i = 0;for(i = 0;i < 4; i++){    disable_irq (dev[i].irq);    free_irq (dev[i].irq, (void *)&dev[i]);}    return 0;}ssize_t dev_read (struct file * dev_file, char __user * buff, size_t dev_size, loff_t * dev_loff){    int ret = -1;    if (!key_flag)    {        if (dev_file->f_flags & O_NONBLOCK)            return -EAGAIN;        else             wait_event_interruptible(dev_queue,key_flag);               }    key_flag= 0;        printk("key %d press!\n", key_value);        ret = copy_to_user (buff, (const void *)&key_value, sizeof (char));        key_value = 0;        return ret ? -EFAULT : sizeof (char);    }unsigned int dev_poll (struct file * dev_file, struct poll_table_struct * dev_table){//int i = 0;    unsigned int mask = 0;    poll_wait (dev_file, &dev_queue, dev_table);       if (key_flag)        mask |= (POLLIN | POLLRDNORM);    return mask;}struct file_operations dev_ops = {    .owner = THIS_MODULE,    .open = dev_open,    .release = dev_close,    .read = dev_read,    .poll = dev_poll,};struct miscdevice dev_misc = {    .minor = MISC_DYNAMIC_MINOR,    .name = DEV_NAME,    .fops = &dev_ops,};static int __init dev_init (void){    int ret = -1;    ret = misc_register(&dev_misc);    printk (DEV_NAME "init!\n");    return ret;    }static void __exit dev_exit (void){    // 注销混杂设备    misc_deregister (&dev_misc);}MODULE_AUTHOR("LiangPeng");module_init(dev_init);module_exit(dev_exit);


测试程序

#include <stdio.h>#include <unistd.h>#include <sys/types.h>#include <sys/time.h>#include <sys/stat.h>#include <fcntl.h>#include <stdlib.h>#include <sys/select.h>#define DEV_NAME "/dev/button"int main (){    fd_set rset;    int fd = 0;    int ret = 0;    int read_count = 0;    unsigned char key_value = 0;    fd = open(DEV_NAME ,O_RDWR);    if (fd < 0)    {        printf("Open Dev Error!\n");        return -1;    }        FD_ZERO (&rset);    FD_SET (fd, &rset);        for (;;)    {        ret = select(fd + 1, &rset, NULL, NULL, NULL);        if (FD_ISSET (fd, &rset))        {            read_count = read (fd, &key_value, 1);            printf ("the key is :%d\n", key_value);            key_value = 0;        }    }        close (fd);    return 0;    }

在测试的过程中发现连续按k1或者k2或者其他的按键 终端上偶尔会出现错误的键值,出现0的情况


后来在调试的时候 把udelay改成了mdelay之后 发现问题没有了

应该是延时的问题

原创粉丝点击