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

 

 

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