内核函数asm_do_IRQ()中的irq与我在模块中请求的irq不同

我用cortex-A9开发板做了一些实验。我使用gpio_to_irq()来获取一个irq

num,然后我请求了irq并编写了一个小驱动程序,在syslog中为196。我在asm_do_IRQ中添加了一些printks。当我触发gpio中断时,驱动程序工作正常,但是asm_do_IRQ中的irq

num是62。我不明白。为什么irq号码与我要求的号码不同?驱动程序如下:

    #include <linux/module.h>

#include <linux/interrupt.h>

#include <linux/irq.h>

#include <linux/gpio.h>

#define GPIO_N 36 //gpio number

int flag = 0;

static irqreturn_t handler(int irq,void *dev_id)

{

printk("hello world hahahahahhahahah \n\n");

return 0;

}

static int __init gpio_test_init(void)

{

if(gpio_request_one(GPIO_N,GPIOF_DIR_IN,"some test")<0)

{

printk(KERN_ERR "Oops! BAD! BAD! BAD!\n\n");

return 0;

}

int irq,irq2;

irq = OMAP_GPIO_IRQ(TEST_GPIO);

printk("irq : %d \n",irq,irq2);

// ..................

// irq : 196 in dmesg

//......................

set_irq_type(irq,IRQ_TYPE_EDGE_FALLING);

enable_irq(gpio_to_irq(GPIO_N));

int err;

// request the irq ...

if((err = request_irq(irq,&handler,0,NULL,NULL))<0)

{

printk("err : %d\n",err);

return 0;

}

printk("gpio test init success!\n");

flag = 1;

return 0;

}

static void __exit gpio_test_exit(void)

{

int irq = gpio_to_irq(TEST_GPIO);

if(flag == 1)free_irq(irq,NULL);

gpio_free(TEST_GPIO);

printk("gpio test exit byebye!\n");

}

module_init(gpio_test_init);

module_exit(gpio_test_exit);

MODULE_LICENSE("GPL");

在arch / arm / kernel / irq.c中的asm_do_IRQ

    asmlinkage void __exception_irq_entry

asm_do_IRQ(unsigned int irq, struct pt_regs *regs)

{

struct pt_regs *old_regs = set_irq_regs(regs);

printk("the irq : %d\n",irq);

//...............

// I get 62 here

//...............

irq_enter();

/*

* Some hardware gives randomly wrong interrupts. Rather

* than crashing, do something sensible.

*/

if (unlikely(irq >= nr_irqs)) {

if (printk_ratelimit())

printk(KERN_WARNING "Bad IRQ%u\n", irq);

ack_bad_irq(irq);

} else {

generic_handle_irq(irq);

}

/* AT91 specific workaround */

irq_finish(irq);

irq_exit();

set_irq_regs(old_regs);

}

回答:

这种观察可能是由于物理和虚拟IRQ编号之间的映射。驱动程序中显示的数字是虚拟IRQ数字,仅在使用通用Linux中断处理子系统时有效。中的中断号asm_do_IRQ将是内核中断结构提供的物理中断号。

我相信OMAP处理器支持GPIO引脚上的中断。通常的实现方式是为一组GPIO输入(例如32位)分配一条IRQ线。当任何GPIO发生中断时,该IRQ线将被激活。这可能是处理器上的数字62。如果查看处理器手册,则应该看到IRQ

62对应于GPIO组中的中断。

现在,Linux GPIO子系统将允许您将中断处理程序分配给任何GPIO,从而为您提供从linux irq号到物理irq号的映射。您的linux

irq数为196。GPIO子系统配置为处理所有GPIO中断(例如中断62),读取GPIO寄存器以确定存储库中的哪些GPIO位可能已产生中断,然后调出您分配给的中断处理程序

request_irq

这是GPIO中断的基本控制流程:

  1. GPIO组中的中断发生更改。IRQ 62升高。
  2. asm_do_IRQ 在IRQ 62上运行。GPIO子系统已通过平台初始化代码注册为处理IRQ 62。
  3. GPIO子系统读取GPIO寄存器,并确定GPIO位X引起了中断。它计算从位X到linux虚拟IRQ编号的映射,在这种情况下为196。
  4. GPIO中断处理程序然后generic_handle_irq使用196 调用该函数,该函数调用您的中断处理程序。

平台通常在虚拟IRQ编号和物理IRQ编号之间定义 。要查看此映射,

  • CONFIG_VIRQ_DEBUG在早于linux-3.4的内核上启用,或
  • CONFIG_IRQ_DOMAIN_DEBUG在较新的内核上启用。

然后看一下irq_domain_mappingdebugfs文件。例如在PowerPC上:

# mount -t debugfs none /sys/kernel/debug

# cat /sys/kernel/debug/irq_domain_mapping

irq hwirq chip name chip data domain name

16 0x00009 IPIC 0xcf801c80 /soc8347@e0000000/pic@700

18 0x00012 IPIC 0xcf801c80 /soc8347@e0000000/pic@700

19 0x0000e IPIC 0xcf801c80 /soc8347@e0000000/pic@700

20 0x0000f IPIC 0xcf801c80 /soc8347@e0000000/pic@700

21 0x00010 IPIC 0xcf801c80 /soc8347@e0000000/pic@700

77 0x0004d IPIC 0xcf801c80 /soc8347@e0000000/pic@700

以上是 内核函数asm_do_IRQ()中的irq与我在模块中请求的irq不同 的全部内容, 来源链接: utcz.com/qa/428099.html

回到顶部