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");

 

 

 

 

posted @ 2017-03-22 20:11  bkycrmn  阅读(202)  评论(0)    收藏  举报