8.2中断共享
中断共享:(一个中断号对应多个中断处理函数,很少见,了解)
1.flag必须加上IRQF_SHARED,这个标志表明多个中断处理程序可以共享一个中断号。
2.中断注册函数第五个参数必须非NULL.
实现共享中断号的情况下,在调用free_irq()时,通过对应的标记,内核才会知道该释放哪个中断处理函数。
内核通过dev_id对应中断处理函数handler。另外,也可以通过它来传参给中断处理函数。
1318 /**
1319 * request_threaded_irq - allocate an interrupt line
1320 * @irq: Interrupt line to allocate
1321 * @handler: Function to be called when the IRQ occurs.
1322 * Primary handler for threaded interrupts
1323 * If NULL and thread_fn != NULL the default
1324 * primary handler is installed
1325 * @thread_fn: Function called from the irq handler thread
1326 * If NULL, no irq thread is created
1327 * @irqflags: Interrupt type flags
1328 * @devname: An ascii name for the claiming device
1329 * @dev_id: A cookie passed back to the handler function
1330 *
1331 * This call allocates interrupt resources and enables the
1332 * interrupt line and IRQ handling. From the point this
1333 * call is made your handler function may be invoked. Since
1334 * your handler function must clear any interrupt the board
1335 * raises, you must take care both to initialise your hardware
1336 * and to set up the interrupt handler in the right order.
1337 *
1338 * If you want to set up a threaded irq handler for your device
1339 * then you need to supply @handler and @thread_fn. @handler is
1340 * still called in hard interrupt context and has to check
1341 * whether the interrupt originates from the device. If yes it
1342 * needs to disable the interrupt on the device and return
1343 * IRQ_WAKE_THREAD which will wake up the handler thread and run
1344 * @thread_fn. This split handler design is necessary to support
1345 * shared interrupts.
1346 *
1347 * Dev_id must be globally unique. Normally the address of the
1348 * device data structure is used as the cookie. Since the handler
1349 * receives this value it makes sense to use it.
1350 *
1351 * If your interrupt is shared you must pass a non NULL dev_id
1352 * as this is required when freeing the interrupt.
1353 *
1354 * Flags:
1355 *
1356 * IRQF_SHARED Interrupt is shared
1357 * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy
1358 * IRQF_TRIGGER_* Specify active edge(s) or level
1359 *
1360 */
//
1361 int request_threaded_irq(unsigned int irq, irq_handler_t handler,
1362 irq_handler_t thread_fn, unsigned long irqflags,
1363 const char *devname, void *dev_id)
-----------------------------------------------------------------------------------------------------------------
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 10 again: 11 make clean;make
demo.c
1 /* head file */ 2 #include <linux/init.h> 3 #include <linux/module.h> 4 #include <plat/irqs.h> 5 #include <linux/delay.h> 6 7 #include <linux/interrupt.h> 8 9 struct mill_key{ 10 int irqnum; 11 char *name; 12 u32 cnt; 13 }millkeys[] = { 14 {IRQ_EINT(26), "key1", 0}, 15 {IRQ_EINT(27), "key2", 0}, 16 {IRQ_EINT(28), "key3", 0}, 17 {IRQ_EINT(29), "key4", 0}, 18 }; 19 20 static void mill_unregister_irqkey(void) 21 { 22 int i; 23 24 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 25 free_irq(millkeys[i].irqnum, &millkeys[i]);//通过对应标记,内核会知道该释放哪个中断处理函数 26 free_irq(millkeys[i].irqnum, (void *)(i+1)); 27 } 28 } 29 30 static irqreturn_t do_handler0(int irqnum, void *dev) 31 { 32 struct mill_key *ptr = dev; 33 34 ptr->cnt++; 35 36 printk("%s is %s!\n", ptr->name, (ptr->cnt%2)?"down":"up"); 37 return IRQ_HANDLED; 38 } 39 40 static irqreturn_t do_handler1(int irqnum, void *dev) 41 { 42 printk("i+1 = %d\n\n", (int)dev);// 43 44 // msleep(100); 45 46 return IRQ_HANDLED; 47 } 48 49 /*4个按键对应的中断注册封装*/ 50 static int mill_register_irqkey(void) 51 { 52 int i; 53 int ret; 54 55 for (i = 0; i < ARRAY_SIZE(millkeys); ++i) { 56 ret = request_irq( 57 millkeys[i].irqnum, do_handler0, 58 IRQF_TRIGGER_RISING | 59 IRQF_TRIGGER_FALLING | IRQF_SHARED,//中断共享标记 60 millkeys[i].name, &millkeys[i]);//中断注册函数的第五个参数定义为void *型,中断发生时会传递给中断处理函数的第二个> 参数,内核通过它:dev对应中断处理函数handler,同时也可以通过它来传参给中断处理函数。 61 if (ret < 0) {//释放同irq程序 62 goto error0; 63 } 64 65 ret = request_irq( 66 millkeys[i].irqnum, do_handler1, 67 IRQF_TRIGGER_RISING | 68 IRQF_TRIGGER_FALLING | IRQF_SHARED,//中断共享标记 69 millkeys[i].name, (void *)(i+1));//中断注册函数的第五个参数定义为void *型,中断发生时会传递给中断处理函数的第二个参数 70 if (ret < 0) { 71 free_irq(millkeys[i].irqnum, &millkeys[i]); 72 goto error0; 73 } 74 } 75 76 return 0; 77 error0: 78 while (i--) { 79 free_irq(millkeys[i].irqnum, &millkeys[i]); 80 free_irq(millkeys[i].irqnum, (void *)(i+1));//中断释放 81 } 82 83 return ret; 84 } 85 86 /* driver module entry */ 87 static int __init demo_init(void) 88 { 89 return mill_register_irqkey(); 90 } 91 92 module_init(demo_init); 93 94 95 /* driver module exit */ 96 static void __exit demo_exit(void) 97 { 98 mill_unregister_irqkey(); 99 } 100 module_exit(demo_exit); 101 102 /* driver module description */ 103 MODULE_LICENSE("GPL"); 104 105 MODULE_AUTHOR("millet9527"); 106 MODULE_VERSION("millet plus 18"); 107 MODULE_DESCRIPTION("example for driver module arch");

cat /proc/interrupts


浙公网安备 33010602011771号