1、概述
(1)裸机中断处理流程回顾
(2)Linux中断处理流程分析
(3)Linux中断处理程序设计
2、裸机中断回顾
(1)中断有一个统一入口:中断向量表
(2)然后跳转到中断处理函数中,获取中断源编号,调用相应的处理函数asm_do_IRQ
(3)中断处理函数要事先注册到表中
3、中断处理程序的设计
(1)注册中断
int request(unsigned int irq, void(*handler)(int, void*, struct pt_regs*), unsigned long flags,const char *name,void *dev_id)
返回0代表注册成功,其他失败。
参数分别是:中断号,处理函数,中断选项flags,设备名字,共享中断的标识id,
中断选项flags:IRQF_DISABLE 快速中断 IRQF_SHARED共享
(2)中断处理
注意中断上下文中不能有:不能有阻塞函数,不能有调度函数。
①首先检查设备是否产生中断
②清除中断产生标识
③相应的硬件操作
(3)注销中断
void free_irq(unsigned int irq, void *dev_id)
4、实例代码
#include <linux/module.h> #include <linux/init.h> #include <linux/cdev.h> #include <linux/fs.h> #include <linux/io.h> #include <linux/interrupt.h> #include <linux/miscdevice.h> #if 0 struct miscdevice { int minor; const char *name; const struct file_operations *fops; struct list_head list; struct device *parent; struct device *this_device; const struct attribute_group **groups; const char *nodename; umode_t mode; }; #endif /**************引入中断框架**************/ #define GPFCON 0X56000050 irqreturn_t key_int(int irq, void *dev_id) { /*1、检查是否发生了中断 **2、清除中断 **3、打印按键值 */ printk("key down\n"); return 0; } void key_hw_init(void) { unsigned int *gpio_config; unsigned short data; gpio_config=ioremap(GPFCON,4); data=readw(gpio_config);//读了4节,读出来再写进去 data &= ~0b11; data |=0x10; writew(data,gpio_config);//将引脚配置成中断 } /************************************/ int key_open(struct inode *node, struct file *filp) { return 0; } struct file_operations key_fops={ .open=key_open, }; struct miscdevice key_miscdev = { .minor = 200, .name = "key", .fops = &key_fops, }; static int button_init() { misc_register(&key_miscdev);//按键下降沿触发中断 key_hw_init(); request_irq(IRQ_EINT0,key_int, IRQF_TRIGGER_FALLING,"key",0); } static void button_exit() { misc_deregister(&key_miscdev); free_irq(IRQ_EINT0, 0);//注销中断程序 } MODULE_LICENSE("GPL"); module_init(button_init);//为甚改成key_init就报错 module_exit(button_exit);