我是靠谱客的博主 清新大门,这篇文章主要介绍linux中断处理,现在分享给大家,希望可以做个参考。

linux中断处理的特点。
(1)中断上下文,不能和用户空间数据交互
(2)不能交出CPU(不能休眠、不能schedule)
(3)ISR运行时间尽可能短,越长则系统响应特性越差

中断下半部2种解决方案
(1)中断分上半部(top half,又叫顶半部)和下半部(bottom half,又叫底半部)
(2)下半部处理策略1:tasklet(小任务),类似一直软件中断方式。
(3)下半部处理策略2:workqueue(工作队列),利用线程完成。

中断上下半部处理原则
(1)必须立即进行紧急处理的极少量任务放入在中断的顶半部中,此时屏蔽了与自己同类型的中断,由于任务量少,所以可以迅速不受打扰地处理完紧急任务。
(2)需要较少时间的中等数量的急迫任务放在tasklet中。此时不会屏蔽任何中断(包括与自己的顶半部同类型的中断),所以不影响顶半部对紧急事务的处理;同时又不会进行用户进程调度,从而保证了自己急迫任务得以迅速完成。
(3)需要较多时间且并不急迫(允许被操作系统剥夺运行权)的大量任务放在workqueue中。此时操作系统会尽量快速处理完这个任务,但如果任务量太大,期间操作系统也会有机会调度别的用户进程运行,从而保证不会因为这个任务需要运行时间将其它用户进程无法进行。
(4)可能引起睡眠的任务放在workqueue中。因为在workqueue中睡眠是安全的。在需要获得大量的内存时、在需要获取信号量时,在需要执行阻塞式的I/O操作时,用workqueue很合适。

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
#include <linux/input.h> #include <linux/module.h> #include <linux/init.h> #include <asm/irq.h> #include <asm/io.h> #include <mach/irqs.h> // arch/arm/mach-s5pv210/include/mach/irqs.h #include <linux/interrupt.h> #include <linux/gpio.h> /* * X210: * * POWER -> EINT1 -> GPH0_1 * LEFT -> EINT2 -> GPH0_2 * DOWN -> EINT3 -> GPH0_3 * UP -> KP_COL0 -> GPH2_0 * RIGHT -> KP_COL1 -> GPH2_1 * MENU -> KP_COL3 -> GPH2_3 (KEY_A) * BACK -> KP_COL2 -> GPH2_2 (KEY_B) */ #define BUTTON_IRQ IRQ_EINT2 static struct input_dev *button_dev; // 下半部函数 void func(unsigned long data) { int flag; printk("key-s5pv210: this is bottom halfn"); s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0)); // input模式 flag = gpio_get_value(S5PV210_GPH0(2)); s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f)); // eint2模式 input_report_key(button_dev, KEY_LEFT, !flag); input_sync(button_dev); } DECLARE_TASKLET(mytasklet, func, 0); static irqreturn_t button_interrupt(int irq, void *dummy) { printk("key-s5pv210: this is top halfn"); tasklet_schedule(&mytasklet); return IRQ_HANDLED; } static int __init button_init(void) { int error; error = gpio_request(S5PV210_GPH0(2), "GPH0_2"); if(error) printk("key-s5pv210: request gpio GPH0(2) fail"); s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f)); // eint2模式 if (request_irq(BUTTON_IRQ, button_interrupt, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "button-x210", NULL)) { printk(KERN_ERR "key-s5pv210.c: Can't allocate irq %dn", BUTTON_IRQ); return -EBUSY; } button_dev = input_allocate_device(); if (!button_dev) { printk(KERN_ERR "key-s5pv210.c: Not enough memoryn"); error = -ENOMEM; goto err_free_irq; } button_dev->evbit[0] = BIT_MASK(EV_KEY); button_dev->keybit[BIT_WORD(KEY_LEFT)] = BIT_MASK(KEY_LEFT); error = input_register_device(button_dev); if (error) { printk(KERN_ERR "key-s5pv210.c: Failed to register devicen"); goto err_free_dev; } return 0; err_free_dev: input_free_device(button_dev); err_free_irq: free_irq(BUTTON_IRQ, button_interrupt); return error; } static void __exit button_exit(void) { input_unregister_device(button_dev); free_irq(BUTTON_IRQ, button_interrupt); } module_init(button_init); module_exit(button_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("aston <1264671872@qq.com>"); MODULE_DESCRIPTION("key driver for x210 button.");

 

 

复制代码
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
#include <linux/input.h> #include <linux/module.h> #include <linux/init.h> #include <asm/irq.h> #include <asm/io.h> #include <mach/irqs.h> // arch/arm/mach-s5pv210/include/mach/irqs.h #include <linux/interrupt.h> #include <linux/gpio.h> #include <linux/workqueue.h> /* * X210: * * POWER -> EINT1 -> GPH0_1 * LEFT -> EINT2 -> GPH0_2 * DOWN -> EINT3 -> GPH0_3 * UP -> KP_COL0 -> GPH2_0 * RIGHT -> KP_COL1 -> GPH2_1 * MENU -> KP_COL3 -> GPH2_3 (KEY_A) * BACK -> KP_COL2 -> GPH2_2 (KEY_B) */ #define BUTTON_IRQ IRQ_EINT2 static struct input_dev *button_dev; // 下半部函数 void func(struct work_struct *work) { int flag; printk("key-s5pv210: this is workqueue bottom halfn"); s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0)); // input模式 flag = gpio_get_value(S5PV210_GPH0(2)); s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f)); // eint2模式 input_report_key(button_dev, KEY_LEFT, !flag); input_sync(button_dev); } DECLARE_WORK(mywork, func); static irqreturn_t button_interrupt(int irq, void *dummy) { printk("key-s5pv210: this is workqueue top halfn"); schedule_work(&mywork); return IRQ_HANDLED; } static int __init button_init(void) { int error; error = gpio_request(S5PV210_GPH0(2), "GPH0_2"); if(error) printk("key-s5pv210: request gpio GPH0(2) fail"); s3c_gpio_cfgpin(S5PV210_GPH0(2), S3C_GPIO_SFN(0x0f)); // eint2模式 if (request_irq(BUTTON_IRQ, button_interrupt, IRQF_TRIGGER_FALLING | IRQF_TRIGGER_RISING, "button-x210", NULL)) { printk(KERN_ERR "key-s5pv210.c: Can't allocate irq %dn", BUTTON_IRQ); return -EBUSY; } button_dev = input_allocate_device(); if (!button_dev) { printk(KERN_ERR "key-s5pv210.c: Not enough memoryn"); error = -ENOMEM; goto err_free_irq; } button_dev->evbit[0] = BIT_MASK(EV_KEY); button_dev->keybit[BIT_WORD(KEY_LEFT)] = BIT_MASK(KEY_LEFT); error = input_register_device(button_dev); if (error) { printk(KERN_ERR "key-s5pv210.c: Failed to register devicen"); goto err_free_dev; } return 0; err_free_dev: input_free_device(button_dev); err_free_irq: free_irq(BUTTON_IRQ, button_interrupt); return error; } static void __exit button_exit(void) { input_unregister_device(button_dev); free_irq(BUTTON_IRQ, button_interrupt); } module_init(button_init); module_exit(button_exit); MODULE_LICENSE("GPL"); MODULE_AUTHOR("aston <1264671872@qq.com>"); MODULE_DESCRIPTION("key driver for x210 button.");

 

最后

以上就是清新大门最近收集整理的关于linux中断处理的全部内容,更多相关linux中断处理内容请搜索靠谱客的其他文章。

本图文内容来源于网友提供,作为学习参考使用,或来自网络收集整理,版权属于原作者所有。
点赞(128)

评论列表共有 0 条评论

立即
投稿
返回
顶部