gpt4 book ai didi

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

转载 作者:IT王子 更新时间:2023-10-29 01:23:35 26 4
gpt4 key购买 nike

我用 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 输入分配一条 IRQ 线,比如 32 位。当任何 GPIO 发生中断时,该 IRQ 线将激活。这可能是您处理器上的数字 62。如果查看处理器的手册,您应该会看到 IRQ 62 对应于 GPIO bank 上的中断。

现在,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 中断处理程序调用带有 196 的 generic_handle_irq 函数,它会调用您的中断处理程序。

在虚拟 IRQ 号和物理 IRQ 号之间通常有一个由平台定义的静态映射。要查看此映射,

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

然后查看irq_domain_mapping debugfs 文件。例如。在 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

关于linux - 内核函数 asm_do_IRQ() 中的 irq 与我在模块中请求的不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15871048/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com