1

我正在学习 linux 内核中的中断处理,并尝试下面的代码片段在 IRQ2 上注册一个虚拟 irq 处理程序。但它似乎没有被注册,因为我在内核中看到一个负返回值和一条消息,如下所示,这是由试图执行的清理函数引起的free_irq()

[ 2203.989585] Trying to free already-free IRQ 2

下面是内核日志中的 printk,表明它尚未注册:

Here with registering IRQ handler on IRQ2 for flowTest...retval_irqreg= -22

下面是我的代码的相关部分,它有四个功能

1 the bottom half 
2. handler 
3. init function 
4. cleanup function

我还没有安排下半部分,尽管它在下面。我正在开发内核 3.5.0-17。

//Bottom half for the irq handler
static void bh_flowTest()
    {
        printk(KERN_INFO "Inside bottom half for flowTest.\n");
    }
// IRQ handler function
static irqreturn_t flow_irq_handler(int irq, void *dev_id, struct pt_regs *regs)
                {
                printk(KERN_INFO "This is flowTest IRQ handler.\n");

        //static struct tq_struct task = {NULL, 0, bh_flowTest, NULL};
                /* Schedule bottom half to run */
        //queue_task(&task, &tq_immediate);

        // mark_bh(IMMEDIATE_BH);
    return IRQ_HANDLED;             
        }

static int flow_init(void)
    {
    printk(KERN_ALERT "Here with flowTest module ... loading...\n");
 int result=0;
 dev_t dev=0;
result = alloc_chrdev_region(&dev, minor_num,
num_devices,"mod_flowtest");                              // allocate major number dynamically.

i=MAJOR(dev);
printk(KERN_ALERT "Major allocated = %d",i);

cdev_init(&ms_flow_cd,&flow_fops);
cdev_add(&ms_flow_cd,dev,1);

//Registering interrupt handler on IRQ2 since IRQ2 is free as per /proc/interrupts
int retval_irqreg;
retval_irqreg=request_irq(2,(irq_handler_t)flow_irq_handler, /* our handler. It has been typecasted to remove warnings of incompatible pointer type , and enum irqreturn_t. Try removing the cast and see the warnings */
              IRQF_SHARED, 
              "test_flow_irq_handler", NULL);
printk(KERN_ALERT "Here with registering IRQ handler on IRQ2 for flowTest...retval_irqreg= %d\n",retval_irqreg);

return 0;
    }

static void flow_terminate(void)
    {
    dev_t devno=MKDEV(i,0);         // wrap major/minor numbers in a dev_t structure , to pass for deassigning.
    printk(KERN_ALERT "Going out... exiting...\n");
    unregister_chrdev_region(devno,num_devices);        //remove entry from the /proc/devices

    free_irq(2, NULL);
    }

我觉得有一些基本的错误,但如果有人能指出我,请..!

4

1 回答 1

2

您的硬件上似乎IRQ 2还不存在。即,当您调用request_irq()Linux 内核时,它还不知道必须将来自哪个外围硬件的哪个物理线路上的哪个中断视为 IRQ 编号“ 2 ”的触发器,因为它只是一个尚未与任何实际物理中断相关联的数字)。

基本上,在尝试为该 IRQ 号注册 ISR 之前,首先需要将特定的 IRQ 号与实际的物理硬件中断相关联。thsi 通常在 Linux 内核中使用irq_domain_add_linear().

过去,可以选择 IRQ 编号,以便它们将硬件 IRQ 线匹配到根中断控制器(即实际向 CPU 发出中断线的组件),现在这个数字只是一个数字。

irq_alloc_desc*()和API 提供 irq 编号的irq_free_desc*()分配,但它们不提供任何支持将控制器本地 IRQ (hwirq) 编号反向映射到 Linux IRQ 编号空间。

Linux 内核的当前设计使用单个大数字空间,其中每个单独的 IRQ 源分配一个不同的数字。当只有一个中断控制器时这很简单,但在具有多个中断控制器的系统中,内核必须确保为每个中断控制器分配不重叠的 Linux IRQ 编号。

Linux-kernel Documentation/IRQ-domain.txt中的更多详细信息。

此外,您可能有兴趣为现有中断注册 ISR(比如键盘 IRQ?)当为单个 IRQ 注册多个 ISR 时,Linux 内核将调用每个注册共享 irq 的驱动程序中的每个 ISR 。

于 2013-08-09T06:55:44.757 回答