如何在驱动中使用中断.docx
- 文档编号:3369040
- 上传时间:2022-11-22
- 格式:DOCX
- 页数:7
- 大小:18.57KB
如何在驱动中使用中断.docx
《如何在驱动中使用中断.docx》由会员分享,可在线阅读,更多相关《如何在驱动中使用中断.docx(7页珍藏版)》请在冰豆网上搜索。
如何在驱动中使用中断
如何在驱动中使用中断
1.1.1申请和释放中断
中断是一个处理器的稀缺资源,在系统中非常重要,通过中断能够及时高效的响应外部事件,提高系统的响应能力,增加系统吞吐量。
在驱动中使用中断,其实比较简单,先申请中断号,并注册一个中断中断处理程序,在中断程序实现对外部事件的处理。
1.申请中断
通过request_irq()可以申请中断号,并同时安装中断处理程序。
request_irq()在中声明,函数原型如下:
staticinlineint__must_checkrequest_irq(unsignedintirq,irq_handler_thandler,unsignedlongflags,
constchar*name,void*dev);
通常情况下,返回值为0表示申请并安装成功,负值表示出错。
其中的参数简单介绍一下:
●irq
是要申请的硬件中断号。
●handler
是指实际中断处理程序的函数指针。
只要系统接收到中断,系统调用这个函数。
●flags
设置与中断有关的一些选项。
比较重要的有SA_INTERRUPT,标明中断处理程序是快速处理程序(设置SA_INTERRUPT)还是慢速处理程序(不设置SA_INTERRUPT)。
快速处理程序被调用时屏蔽所有中断,慢速处理程序不屏蔽。
还有一个SA_SHIRQ属性,设置了以后运行多个设备共享中断,处理程序之间通过dev来进行区分。
如果中断由某个处理程序独占,则dev可以设置为NULL。
●*name
传递给request_irq的字符串,用来在/proc/interrupts显示中断的拥有者。
使用cat命令查看。
●*dev
在中断共享时会用到。
一般设置为这个设备的device结构本身或者NULL。
中断处理程序可以用dev找到相应的控制这个中断的设备。
在没有强制使用共享方式时,dev可以被设置为NULL,不过,将它指向设备的数据结构是比较好的方法。
函数会将dev原封不动的传递给中断处理程序,因而可以很方便的用于向中断传递额外数据。
2.释放中断
中断时系统的稀缺资源,一旦不再使用,最好将中断号释放。
释放中断通过free_irq()实现。
与request_irq()一样,free_ire()函数在中声明,其函数原型如下:
voidfree_irq(unsignedintirq,void*dev_id)
第一个参数是将要释放的irq中断号。
第二个参数标志设备。
如果中断是该设备独占的,这里设置为NULL;如果是共享中断,需要设置为中断处理程序指针。
3.设置触发条件
中断需要设置触发条件,如上升沿中断或者下降沿中断等。
Linux提设置触发条件的接口函数为irq_set_irq_type(),在
externintirq_set_irq_type(unsignedintirq,unsignedinttype);
irq为中断号,type为终端类型。
在
IRQ_TYPE_NONE =0x00000000,
IRQ_TYPE_EDGE_RISING =0x00000001,
IRQ_TYPE_EDGE_FALLING =0x00000002,
IRQ_TYPE_EDGE_BOTH =(IRQ_TYPE_EDGE_FALLING|IRQ_TYPE_EDGE_RISING),
IRQ_TYPE_LEVEL_HIGH =0x00000004,
IRQ_TYPE_LEVEL_LOW =0x00000008,
IRQ_TYPE_LEVEL_MASK =(IRQ_TYPE_LEVEL_LOW|IRQ_TYPE_LEVEL_HIGH),
IRQ_TYPE_SENSE_MASK =0x0000000f,
IRQ_TYPE_PROBE =0x00000010,
通常情况下,一般采用边沿触发和电平触发类型,具体如何设置,还需与实际硬件匹配。
4.使能和禁止中断
如果没有在系统中使能中断,就算设置了触发条件,即使满足了触发条件也是不会产生中断的。
Linux下使能中断的函数为enable_irq(),在
externvoidenable_irq(unsignedintirq);
irq为需要使能的中断号。
5.禁止中断
如果一个中断使用完毕不再使用,可以将该中断禁止。
禁止中断的函数为disable_irq(),在
externvoiddisable_irq(unsignedintirq);
irq为要禁止的中断号。
1.1.2中断处理程序编写
中断处理程序返回值irqreturn_t,接受两个参数:
中断号irq和dev_id,dev_id就是request_irq时传递给系统的参数dev:
typedefirqreturn_t(*irq_handler_t)(intirq,void*dev_id);
中断处理完毕,通常返回IRQ_HANDLED。
通常,一个中断处理程序如程序清单2.24所示。
程序清单2.24中断处理程序
staticirqreturn_txxxx_interrupt(intirq,void*dev_id)
{
...中断处理代码
returnIRQ_HANDLED; /*中断已经处理完毕*/
}
至于中断处理程序要做些什么,应当做些什么,取决于具体系统的具体应用,没有统一的要求,但是中断处理程序应当尽量短,处理只能在中断上下文中处理的事情,能放到进程上下文的工作都不要放到中断上下文中处理。
1.1.3按键驱动
1.背景交代
本节提供的按键驱动范例基于EPC-28x工控主板。
EPC-28x硬件上有不少用户可用GPIO,本节选取其中一个GPIO,用作按键,并编写驱动,用于演示中断的基本用法。
本节范例按键对应的GPIO为GPIO2_6,对应IO在系统中的编号为70。
IO端口平时处于高电平,按键按下后为低电平。
Linux系统为每个中断都分配了一个编号。
i.MX28x处理器的每个IO端口都可以产生中断,IO引脚编号GPIOn和中断号IRQn之间的换算公式为:
IRQn=GPIOn+128,在代码中可通过gpio_to_irq函数来完成转换。
2.驱动实现
按键通常来说无需进行读写操作,也无需进行其它ioctl操作,因此,这些方法都无需实现。
范例程序仅仅实现了open、release和close三种方法,参考程序清单2.25。
第10~13的3个宏定义分别行定义了IO端口、中断编号和设备名称。
第20~26行列举了可用的中断触发条件,在代码中根据实际需要来使用。
根据硬件情况,代码中实际使用下降沿中断IRQ_TYPE_EDGE_FALLING。
范例代码中有一点需要说明一下,就是代码中使用了GPIO申请和释放函数,见第59行和108行。
在Linux系统中,为了防止某个IO被在多个地方被重复使用,在使用之前需通过gpio_request_one()函数进行申请。
在没有被释放之前,其它驱动程序是不能获得该IO端口的,能有效防止资源混乱。
使用完毕,可通过gpio_free()函数释放该端口。
程序清单2.25按键驱动范例
1#include
2#include
3#include
4#include
5#include
6#include
7#include
8#include
9
10#defineKEY_GPIO 70 /*GPIO2_6 */
11#defineKEY_GPIO_IRQ gpio_to_irq(KEY_GPIO) /*中断号 */
12#defineDEVICE_NAME "key_irq"
13
14staticintmajor;
15staticintminor;
16structcdev*key_irq; /*cdev数据结构 */
17staticdev_tdevno; /*设备编号 */
18staticstructclass*key_irq_class;
19
20charconstirq_types[5]={
21 IRQ_TYPE_EDGE_RISING,
22 IRQ_TYPE_EDGE_FALLING,
23 IRQ_TYPE_EDGE_BOTH,
24 IRQ_TYPE_LEVEL_HIGH,
25 IRQ_TYPE_LEVEL_LOW
26};
27
28staticintkey_irq_open(structinode*inode,structfile*file)
29{
30 try_module_get(THIS_MODULE);
31 printk(KERN_INFODEVICE_NAME"opened!
\n");
32 return0;
33}
34
35staticintkey_irq_release(structinode*inode,structfile*file)
36{
37 printk(KERN_INFODEVICE_NAME"closed!
\n");
38 module_put(THIS_MODULE);
39 return0;
40}
41
42staticirqreturn_tkey_irq_irq_handler(unsignedintirq,void*dev_id)
43{
44 printk("KEYIRQHAPPENED!
\n");
45 returnIRQ_HANDLED;
46}
47
48structfile_operationskey_irq_fops={
49 .owner =THIS_MODULE,
50 .open =key_irq_open,
51 .release=key_irq_release,
52};
53
54staticint__initkey_irq_init(void)
55{
56 intret;
57
58 gpio_free(KEY_GPIO);
59 ret=gpio_request_one(KEY_GPIO,GPIOF_IN,"KEYIRQ"); /*申请IO */
60 if(ret<0){
61 printk(KERN_ERR"FailedtorequestGPIOforKEY\n");
62 }
63
64 gpio_direction_input(KEY_GPIO); /*设置GPIO为输入 */
65 if(request_irq(KEY_GPIO_IRQ,key_irq_irq_handler,IRQF_DISABLED,"key_irqirq",NULL))
{ /*申请中断*/
66 printk(KERN_WARNINGDEVICE_NAME":
Can'tgetIRQ:
%d!
\n",KEY_GPIO_IRQ);
67 }
68 set_irq_type(KEY_GPIO_IRQ,irq_types[1]);
69 disable_irq(KEY_GPIO_IRQ);
70 enable_irq(KEY_GPIO_IRQ);
71
72 ret=alloc_chrdev_region(&devno,minor,1,DEVICE_NAME); /*从系统获取主设备号 */
73 major=MAJOR(devno);
74 if(ret<0){
75 printk(KERN_ERR"cannotgetmajor%d\n",major);
76 return-1;
77 }
78
79 key_irq=cdev_alloc(); /*分配key_irq结构 */
80 if(key_irq!
=NULL){
81 cdev_init(key_irq,&key_irq_fops); /*初始化key_irq结构 */
82 key_irq->owner=THIS_MODULE;
83 if(cdev_add(key_irq,devno,1)!
=0){ /*增加key_irq到系统中 */
84 printk(KERN_ERR"addcdeverror!
\n");
85 gotoerror;
86 }
87 }else{
88 printk(KERN_ERR"cdev_allocerror!
\n");
89 return-1;
90 }
91
92 key_irq_class=class_create(THIS_MODULE,"key_irq_class");
93 if(IS_ERR(key_irq_class)){
94 printk(KERN_INFO"createclasserror\n");
95 return-1;
96 }
97
98 device_create(key_irq_class,NULL,devno,NULL,DEVICE_NAME);
99 return0;
100
101error:
102 unregister_chrdev_region(devno,1); /*释放已经获得的设备号*/
103 returnret;
104}
105
106staticvoid__exitkey_irq_exit(void)
107{
108 gpio_free(KEY_GPIO);
109 disable_irq(KEY_GPIO_IRQ);
110 free_irq(KEY_GPIO_IRQ,NULL);
111 cdev_del(key_irq); /*移除字符设备 */
112 unregister_chrdev_region(devno,1); /*释放设备号 */
113 device_destroy(key_irq_class,devno);
114 class_destroy(key_irq_class);
115}
116
117module_init(key_irq_init);
118module_exit(key_irq_exit);
119
120MODULE_LICENSE("GPL");
121MODULE_AUTHOR("Chenxibing,linux@");
3.驱动测试
编译驱动后,将驱动模块插入系统,然后按下按键,可以看到按键中断发生并打印提示信息:
[root@EPC-28xmnt]#insmodkey_irq.ko
KEYIRQHAPPENED!
KEYIRQHAPPENED!
KEYIRQHAPPENED!
此时,查看/proc/interrupts文件,可以看到中断的发生次数:
[root@EPC-28xmnt]#cat/proc/interrupts
CPU0
...
220:
26 GPIO key_irqirq
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 如何 驱动 使用 中断