1、中断时系统的稀缺资源,一旦不再使用,最好将中断号释放。释放中断通过free_irq()实现。与request_irq()一样,free_ire()函数在中声明,其函数原型如下:void free_irq(unsigned int irq, void *dev_id)第一个参数是将要释放的irq中断号。第二个参数标志设备。如果中断是该设备独占的,这里设置为NULL;如果是共享中断,需要设置为中断处理程序指针。3 设置触发条件中断需要设置触发条件,如上升沿中断或者下降沿中断等。Linux提设置触发条件的接口函数为irq_set_irq_type(),在定义,函数原型为:extern int irq
2、_set_irq_type(unsigned int irq, unsigned int type);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 = 0
3、x00000008,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(),在中定义,函数原型如下:extern void enable_irq(unsigned int
4、 irq);irq为需要使能的中断号。5 禁止中断如果一个中断使用完毕不再使用,可以将该中断禁止。禁止中断的函数为disable_irq(),在extern void disable_irq(unsigned int irq);irq为要禁止的中断号。1.1.2 中断处理程序编写中断处理程序返回值irqreturn_t,接受两个参数:中断号irq和dev_id,dev_id就是request_irq时传递给系统的参数dev:typedef irqreturn_t (*irq_handler_t)(int irq, void *dev_id);中断处理完毕,通常返回IRQ_HANDLED。通常,
5、一个中断处理程序如程序清单2.24所示。程序清单2.24中断处理程序static irqreturn_t xxxx_interrupt(int irq, void *dev_id).中断处理代码return IRQ_HANDLED; /* 中断已经处理完毕 */至于中断处理程序要做些什么,应当做些什么,取决于具体系统的具体应用,没有统一的要求,但是中断处理程序应当尽量短,处理只能在中断上下文中处理的事情,能放到进程上下文的工作都不要放到中断上下文中处理。1.1.3 按键驱动1 背景交代本节提供的按键驱动范例基于EPC-28x工控主板。EPC-28x硬件上有不少用户可用GPIO,本节选取其中一个
6、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。第1013的
7、3个宏定义分别行定义了IO端口、中断编号和设备名称。第2026行列举了可用的中断触发条件,在代码中根据实际需要来使用。根据硬件情况,代码中实际使用下降沿中断IRQ_TYPE_EDGE_FALLING。范例代码中有一点需要说明一下,就是代码中使用了GPIO申请和释放函数,见第59行和108行。在Linux系统中,为了防止某个IO被在多个地方被重复使用,在使用之前需通过gpio_request_one()函数进行申请。在没有被释放之前,其它驱动程序是不能获得该IO端口的,能有效防止资源混乱。使用完毕,可通过gpio_free()函数释放该端口。程序清单2.25按键驱动范例1 #include 2
8、#include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 9 10 #define KEY_GPIO 70 /* GPIO2_6 */11 #define KEY_GPIO_IRQ gpio_to_irq(KEY_GPIO) /* 中断号12 #define DEVICE_NAME key_irq13 14 static int major;15 static int minor;16 struct cdev *key_irq; /* cdev数据结构17 static dev_t devno; /*
9、设备编号18 static struct class *key_irq_class;19 20 char const irq_types5 = 21 IRQ_TYPE_EDGE_RISING,22 IRQ_TYPE_EDGE_FALLING,23 IRQ_TYPE_EDGE_BOTH,24 IRQ_TYPE_LEVEL_HIGH,25 IRQ_TYPE_LEVEL_LOW26 ;27 28 static int key_irq_open(struct inode *inode, struct file *file )29 30 try_module_get(THIS_MODULE);31 pr
10、intk(KERN_INFO DEVICE_NAME opened!n); 32 return 0;33 34 35 static int key_irq_release(struct inode *inode, struct file *file )36 37 closed!38 module_put(THIS_MODULE);3940 41 42 static irqreturn_t key_irq_irq_handler (unsigned int irq, void *dev_id)43 44 printk(KEY IRQ HAPPENED!45 return IRQ_HANDLED;
11、46 47 48 struct file_operations key_irq_fops = 49 .owner = THIS_MODULE,50 .open = key_irq_open,51 .release = key_irq_release,52 ;53 54 static int _init key_irq_init(void)55 56 int ret;57 58 gpio_free(KEY_GPIO);59 ret = gpio_request_one(KEY_GPIO, GPIOF_IN, KEY IRQ /* 申请IO 60 if (ret owner = THIS_MODU
12、LE;83 if (cdev_add(key_irq, devno, 1) != 0) /* 增加key_irq到系统中84add cdev error!85 goto error;8687 else 88cdev_alloc error!899091 92 key_irq_class = class_create(THIS_MODULE, key_irq_class93 if (IS_ERR(key_irq_class) 94 printk(KERN_INFO create class errorn959697 98 device_create(key_irq_class, NULL, de
13、vno, NULL, DEVICE_NAME);99100 101 error:102 unregister_chrdev_region(devno, 1); /* 释放已经获得的设备号 */103 return ret;104 105 106 static void _exit key_irq_exit(void)107 108109110 free_irq(KEY_GPIO_IRQ, NULL);111 cdev_del(key_irq); /* 移除字符设备112 /* 释放设备号113 device_destroy(key_irq_class, devno);114 class_des
14、troy(key_irq_class);115 116 117 module_init(key_irq_init);118 module_exit(key_irq_exit);119 120 MODULE_LICENSE(GPL121 MODULE_AUTHOR(Chenxibing, linux3 驱动测试编译驱动后,将驱动模块插入系统,然后按下按键,可以看到按键中断发生并打印提示信息:rootEPC-28x mnt# insmod key_irq.ko此时,查看/proc/interrupts文件,可以看到中断的发生次数:rootEPC-28x mnt# cat /proc/interruptsCPU0.220: 26 GPIO key_irq irq
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1