一.驱动源代码实现:
#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);
}
}
三.硬件设备:
四.测试
将按键的驱动代码编译后,插入模块。
中断注册申请完成。
创建设备节点。
运行测试程序,按下按键,可以看到中断产生并且获得键值。