内核
- 中断
- 中断注册函数request_irq
- 禁止其他中断执行disable_irq()
- 删除中断函数free_irq()
- 等待队列
中断
中断注册函数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");