中断
中断注册函数request_irq
request_irq(unsigned int irq, irq_handler_t handler, unsigned long flags,const char *name, void *dev)
作用:注册中断服务函数
参数:
irq:中断名称
handeler:中断函数名
flags:宏 IRQF_TRIGGER_FALLING (...)
name:中断名称(自己起)
dev:设备名所在
禁止其他中断执行disable_irq()
disable_irq((unsigned int irq)
删除中断函数free_irq()
void free_irq(unsigned int irq, void *dev_id)
等待队列
1.定义一个队列头 数据类型位wait_queue_head_t
2.初始化等待队列头 (使用带参宏init_waitqueue_head(q))
参数:wait_queue_head_t类型变量
3.阻塞wait_event(wq,condition);
condition为假才能进入函数调用
//Linux驱动编程按键(等待队列demo以及中断注册函数)
#include<linux/init.h>
#include<linux/module.h>
#include<linux/fs.h>
#include<linux/miscdevice.h>
#include<asm/uaccess.h>
#include<asm/io.h>
#include<linux/interrupt.h>
#include<mach/irqs.h>
#include<linux/wait.h>
#include<linux/sched.h>
unsigned int *regGPGCON;
unsigned int *regGPGDAT;
static int key;
static wait_queue_head_t wq;
static int condition;
/*static int key_pressed(void)
{
int ret = 0;
if(!(*regGPGDAT & 0x01))
{
return 1;
}
return ret;
}*/
static ssize_t key_device_read(struct file *fp, char __user *puser, size_t len, loff_t *offset)
{
condition = 0;
wait_event_interruptible(wq, condition);
copy_to_user(puser, &key, sizeof(key));
key = 0;
return sizeof(key);
}
int key_device_open(struct inode *pnode, struct file *fp)
{
return 0;
}
int key_device_release(struct inode *pnode, struct file *fp)
{
return 0;
}
struct file_operations fops =
{
.owner = THIS_MODULE,
.read = key_device_read,
.open = key_device_open,
.release = key_device_release
};
static struct miscdevice key_device =
{
.minor = MISC_DYNAMIC_MINOR,
.name = "key",
.fops = &fops,
};
irqreturn_t key_interrupt(int irq_num, void *dev)
{
if(irq_num == IRQ_EINT8)
{
key = 1;
}
condition = 1;
wake_up_interruptible(&wq);
return IRQ_HANDLED;
}
static int __init key_driver_init(void)
{
misc_register(&key_device);
if(request_irq(IRQ_EINT8, key_interrupt, IRQF_TRIGGER_FALLING | IRQF_DISABLED, "EINT8", &key_device) != 0)
{
misc_deregister(&key_device);
return -1;
}
init_waitqueue_head(&wq);
regGPGCON = ioremap(0x56000060, 4);
regGPGDAT = ioremap(0x56000064, 4);
*regGPGCON &= ~(0x03 << 0);
*regGPGCON |= (0x01 << 1);
return 0;
}
static void __exit key_driver_exit(void)
{
iounmap(regGPGCON);
iounmap(regGPGDAT);
disable_irq(IRQ_EINT8);
free_irq(IRQ_EINT8, &key_device);
misc_deregister(&key_device);
}
module_init(key_driver_init);
module_exit(key_driver_exit);
MODULE_LICENSE("GPL");