当前位置: > 华清远见教育科技集团 > 嵌入式学习 > 讲师博文 > FS_2416按键驱动实现
FS_2416按键驱动实现
时间:2016-12-12作者:华清远见

一.驱动源代码实现:

#include < linux/module.h>
        #include < linux/kernel.h>
        #include < linux/init.h>
        #include < linux/fs.h>
        #include < linux/cdev.h>
        #include < linux/ interrupt.h>
        #include < linux/irq.h>
        #include < linux/types.h>
        #include < linux/errno.h>
        #include < linux/mm.h>
        #include < linux/sched.h>
        #include < linux/slab.h>
        #include < linux/poll.h>
        #include < asm/io.h>
        #include < asm/uaccess.h>
        #include < asm/system.h>
        #include < mach/regs-gpio.h>
        #include < mach/irqs.h>
        #define GPGCON 0x56000060
        static volatile unsigned int *gpgcon;
        #define GPGDAT 0x56000064
        static volatile unsigned int *gpgdat;
        #define GPGUDP 0x56000068
        static volatile unsigned int *gpgudp;

MODULE_LICENSE("Dual BSD/GPL");
        MODULE_AUTHOR("farsight");

static int irq_major = 251;
        static int irq_minor = 0;
        static struct cdev irq_cdev;
        static int key;
        struct fasync_struct *async_queue;
        static int irq_open(struct inode *inode, struct file *filp)
        {
                return 0;
 nbsp;       }
        static int irq_release(struct inode *inode, struct file *filp)
        {
                return 0;
        }

static ssize_t irq_read(struct file *filp, char __user *buf, size_t count, loff_t *ppos)
        {
                if(copy_to_user(buf, (char *)&key, count))
                return -ENOMEM;
                return count;
        }

static int irq_fasync(int fd, struct file *filp, int mode)
        {
                return fasync_helper(fd, filp, mode, &async_queue);
        }

static struct file_operations fs2416_ops = {
                .owner = THIS_MODULE,
                .open = irq_open,
                .release = irq_release,
                .read = irq_read,
                .fasync = irq_fasync,
        };

static int irq_setup_cdev(struct cdev *cdev, struct file_operations *fops)
        {
                int result;
                dev_t devno = MKDEV(irq_major, irq_minor);
                cdev_init(cdev, fops);
                cdev->owner = THIS_MODULE;
    &nbsnbsp;           result = cdev_add(cdev, devno, 1);
                if(result)
                {                         printk("irq: cdev add faiirq\n");
                        return result;
                }
                return 0;
        }

static irqreturn_t irqhandler(int irqno, void *dev_id)
        {
        printk("irq: interrupt %d\n", irqno);
        switch(irqno)
                {
                case IRQ_EINT(10):
                //printk("eint 10\n");
                key = 2;
                break;
                case IRQ_EINT(11):
                //printk("eint 11\n");
                key = 4;
                break;
        case IRQ_EINT(12):
                //printk("eint 12\n");
                key = 3;
                break;
        case IRQ_EINT(13):
      &nbnbsp;         //printk("eint 13\n");
                key = 5;
                break;
                }
        if (async_queue)
                kill_fasync(&async_queue, SIGIO, POLL_IN);
                return IRQ_HANDLED;
        }

static int __init fs2416_init(void)
        {
        int result;
        dev_t devno = MKDEV(irq_major, irq_minor);
        result = register_chrdev_region(devno, 1, "fs2416");
        if(result)
                {
                        printk("irq: unable to get major %d\n", irq_major);
                        return result;
                }
        result = irq_setup_cdev(&irq_cdev, &fs2416_ops);
        if(result)
                goto err_add_cdev;
        gpgcon = ioremap(GPGCON, 0x04);
        gpgdat = ioremap(GPGDAT, 0x04);
        gpgudp = ioremap(GPGUDP, 0x04);
        // interrupts mode:
                //gpg2 k2
        *gpgcon= (*gpgcon &(~(0x3<<4))) | (0x2 << 4);
                //gpg3 k4
        *gpgcon= (*gpgcon &(~(0x3<<6))) | (0x2 << 6);
                //gpg4 k3
        *gpgcon= (*gpgcon &(~(0x3<<8))) | (0x2 << 8);
                //gpg5 k5
        *gpgcon= (*gpgcon &(~(0x3<<10))) | (0x2 << 10);
        *gpgudp= (*gpgudp &(~(0x3<<4))) | (0x2 << 4);
        *gpgudp= (*gpgudp &(~(0x3<<6))) | (0x2 << 6);
        *gpgudp= (*gpgudp &(~(0x3<<8))) | (0x2 << 8);
        *gpgudp= (*gpgudp &(~(0x3<<10))) | (0x2 << 10);
        result = request_irq(IRQ_EINT(10), irqhandler, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "EINT 10", NULL);
        //printk("req 10 result : %d\n",result);
        if(result)
                goto err1;
        result = request_irq(IRQ_EINT(11), irqhandler, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "EINT 11", NULL);
        //printk("req 11 result : %d\n",result);
        if(result)
                goto err2;
        result = request_irq(IRQ_EINT(12), irqhandler, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "EINT 12", NULL);
        //printk("req 12 result : %d\n",result);
        if(result)
                goto err3;
        result = request_irq(IRQ_EINT(13), irqhandler, IRQF_DISABLED|IRQF_TRIGGER_FALLING, "EINT 13", NULL);
        //printk("req 13 result : %d\n",result);
        if(result)
                goto err4;
        printk("irq: driver installirq, with major %d!\n", irq_major);
        return 0;
      &nbnbsp; err4:
                free_irq(IRQ_EINT(13), NULL);
        err3:
                free_irq(IRQ_EINT(12), NULL);
        err2:
                free_irq(IRQ_EINT(11), NULL);
        err1:
                cdev_del(&irq_cdev);
        err_add_cdev:
                unregister_chrdev_region(devno, 1);
                return result;
        }

static void __exit fs2416_exit(void)
        {
                dev_t devno = MKDEV(irq_major, irq_minor);
                cdev_del(&irq_cdev);
                unregister_chrdev_region(devno, 1);
                free_irq(IRQ_EINT(10), NULL);
                free_irq(IRQ_EINT(11), NULL);
                free_irq(IRQ_EINT(12), NULL);
                free_irq(IRQ_EINT(13), NULL);
                printk("irq: driver uninstalirq!\n");
        }

module_init(fs2416_init);
        module_exit(fs2416_exit);

二.测试程序:

#include < sys/types.h>
        #include < sys/stat.h>
        #include < stdio.h>
        #include < fcntl.h>
  nbsp;      #include < signal.h>
        #include < unistd.h>
        int    fd, oflags;

void input_handler(int signum)
        {
                int key;
                read(fd, (char *)&key, sizeof(key));
                printf("get key data = %d\n", key);
        }
        int main()
        {
                fd = open("/dev/irq", O_RDWR, S_IRUSR | S_IWUSR);
                if(fd < 0)
                        {
                                perror("open");
                                exit(1);
                        }
                int key=-1;
                signal(SIGIO, input_handler);
                fcntl(fd, F_SETOWN, getpid());
                oflags = fcntl(fd, F_GETFL);
                fcntl(fd, F_SETFL, oflags | FASYNC);
                while(1)
                        {
  &nbnbsp;                             sleep(1);
                        }
        }

三.硬件设备:

四.测试

将按键的驱动代码编译后,插入模块。

中断注册申请完成。

创建设备节点。

运行测试程序,按下按键,可以看到中断产生并且获得键值。

发表评论
评论列表(网友评论仅供网友表达个人看法,并不表明本站同意其观点或证实其描述)