8.1中断处理
1 中断: 2 3 涉及到的头文件: 4 #include <linux/interrupt.h> 5 6 7 注册中断需要的函数接口: 8 9 int 10 request_irq( 11 unsigned int irq, //中断号 12 irq_handler_t handler, //中断处理函数 13 unsigned long flags, //中断注册的标记 14 const char *name, //中断的名字 15 void *dev //中断处理函数需要的点心 16 ); 17 18 19 @irq 20 <1> 外部中断号 21 方法一: 22 arch/arm/plat-samsung/include/plat/irqs.h 23 IRQ_EINT(X); //X代表外部中断号 24 25 方法二: 26 将对应gpio的编号转换成注册中断号返回: 27 gpio_to_irq(gpionum); 28 29 30 <2> 内部中断号 31 32 /linux-3 .5/arch/arm/mach-exynos/include/mach/irqs.h 33 34 35 @handler 36 37 //中断处理函数的类型如下: 38 39 typedef irqreturn_t (*irq_handler_t)(int, void *); 40 41 中断处理函数的第一个参数是发生中断的中断号,第二个参数是注册中断的对后一个参数。 42 43 中断处理函数的返回值: 44 enum irqreturn { 45 IRQ_NONE = (0 << 0), 46 IRQ_HANDLED = (1 << 0), 47 IRQ_WAKE_THREAD = (1 << 1), 48 }; 49 50 typedef enum irqreturn irqreturn_t; 51 52 @flags 53 54 #define IRQF_TRIGGER_NONE 0x00000000 55 #define IRQF_TRIGGER_RISING 0x00000001 56 #define IRQF_TRIGGER_FALLING 0x00000002 57 #define IRQF_TRIGGER_HIGH 0x00000004 58 #define IRQF_TRIGGER_LOW 0x00000008 59 60 #define IRQF_SHARED 0x00000080 61 62 63 @name 64 65 ================================================== 66 67 68 tasklet 机制实现中断的下半部 69 70 涉及接口体类型: 71 72 struct tasklet_struct 73 { 74 struct tasklet_struct *next; 75 unsigned long state; 76 atomic_t count; 77 void (*func)(unsigned long); //下半部的函数 78 unsigned long data; //下半部函数的点心 79 }; 80 81 82 83 struct tasklet_struct tsk; 84 85 下半部任务对象的初始化: 86 void tasklet_init( 87 struct tasklet_struct *t, 88 void (*func)(unsigned long), 89 unsigned long data 90 ); 91 92 在中断的上半部,调用如下函数将下半部的任务交给调度器 93 调度。 94 void tasklet_schedule(struct tasklet_struct *t);
Makefile
1 obj-m := demo.o 2 3 KERNEL := /linux-3.5 4 5 all: 6 make -C $(KERNEL) M=`pwd` 7 clean: 8 make -C $(KERNEL) M=`pwd` clean 9
demo.c
1 /* head file */ 2 #include <linux/init.h> 3 #include <linux/module.h> 4 #include <plat/irqs.h> 5 6 #include <linux/interrupt.h> 7 8 struct mill_key{ //结构体类型 9 int irqnum; //中断号 10 char *name; //中断名 11 u32 cnt; //发生中断的次数 12 }millkeys[] = { //定义该结构体类型的数组 13 {IRQ_EINT(26), "key1", 0}, 14 {IRQ_EINT(27), "key2", 0}, 15 {IRQ_EINT(28), "key3", 0}, 16 {IRQ_EINT(29), "key4", 0}, 17 }; 18 19 static void mill_unregister_irqkey(void)//封装按键移除函数 20 { 21 int i; 22 23 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) {//一一释放中断 24 free_irq(millkeys[i].irqnum, &millkeys[i]); 25 } 26 27 } 28 29 static irqreturn_t do_handler(int irqnum, void *dev)//void *类型的dev来接中断注册函数的第五个参数cookie/void *编译器隐式转换类型 30 { 31 struct mill_key *ptr = dev;//将结构体数组地址&millkeys[i]赋给 定义的结构体指针ptr 32 33 ptr->cnt++;//中断的次数 34 35 printk("%s is %s!\n", ptr->name, (ptr->cnt%2)?"down":"up"); 36 37 return IRQ_HANDLED;//返回中断处理函数处理完的内核规范赋值 38 } 39 40 static int mill_register_irqkey(void)//封装按键注册函数 41 { 42 int i; 43 int ret; 44 45 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) {//注册按键中断 46 ret = request_irq( 47 millkeys[i].irqnum, do_handler, 48 IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING, 49 millkeys[i].name, &millkeys[i]); 50 if (ret < 0) { 51 goto error0;//注册失败须把之前注册好的去一一释放中断 52 } 53 } 54 55 return 0; 56 error0: 57 while (i--) { 58 free_irq(millkeys[i].irqnum, &millkeys[i]); 59 } 60 61 return ret; 62 } 63 64 /* driver module entry */ 65 static int __init demo_init(void) 66 { 67 return mill_register_irqkey();// 68 } 69 70 module_init(demo_init); 71 72 73 /* driver module exit */ 74 static void __exit demo_exit(void) 75 { 76 mill_unregister_irqkey(); 77 } 78 module_exit(demo_exit); 79 80 /* driver module description */ 81 MODULE_LICENSE("GPL"); 82 83 MODULE_AUTHOR("millet9527"); 84 MODULE_VERSION("millet plus 18"); 85 MODULE_DESCRIPTION("example for driver module arch");




浙公网安备 33010602011771号