如何使用request_threaded_irq以便在线程处理程序工作时调用中断处理程序?

Gil*_*ire 5 c arm interrupt linux-kernel

我正在尝试为linux内核中的GPIO编写一个简单的中断处理程序.我request_threaded_irq用来获取一个中断上下文处理程序和一个线程处理程序.

我的问题是线程处理程序完成的工作对调用中断处理程序的时间有很大影响.

设置中断的代码是:

gpio_request(93, "test")
gpio_direction_input(93);
gpio_request(33, "mirror");
gpio_direction_output(33, 1);

request_threaded_irq(gpio_to_irq(93),
        interrupt_handler,
        threaded_interrupt_handler,
        IRQF_TRIGGER_RISING | IRQF_TRIGGER_FALLING | IRQF_TIMER,
        "test", NULL);
Run Code Online (Sandbox Code Playgroud)

在这里,我只是要求gpio 93在上升沿和下降沿触发中断.我还要求gpio 33用作镜子,见下文.

(在我的设置中,我在gpio 93上放了一个时钟源).

中断处理程序的代码是这样的:

static irqreturn_t interrupt_handler(int irq, void *data)
{
    int state = gpio_get_value(93);
    gpio_set_value(33, state);
    return IRQ_WAKE_THREAD;
}
Run Code Online (Sandbox Code Playgroud)

这里,中断处理程序只是将gpio 93输入值镜像为gpio 33的输出值.这使我可以监视调用的有效速率interrupt_handler.

最后,线程处理程序:

static irqreturn_t threaded_interrupt_handler(int irq, void *data)
{
    /* doing msleep here is apparently problematic... */
    msleep(1);
    return IRQ_HANDLED;
}
Run Code Online (Sandbox Code Playgroud)

在线程中断处理程序中,调用msleep(或实际执行工作)是有问题的:通过在gpio输出33处查看范围,我可以看到interrupt_handlerthreaded_interrupt_handler休眠或执行太多工作时回调率急剧变化.

我如何设置/使用,request_threaded_irq()以便中断处理程序始终被称为"按时",即使线程处理程序作为一些大工作要做?

Gil*_*ire 6

我终于明白发生了什么.根据SO上的这个答案,在处理中断线程中断处理程序时屏蔽中断.

所以我似乎误解了它的意思request_threaded_irq:应该真正使用它,以便中断处理在调度程序安排的任务中.

根据我的需要,我真正想要的只是一个wait_queue.我删除了代码的线程中断处理程序,并将中断处理程序更改为:

static wait_queue_head_t wq;

static irqreturn_t interrupt_handler(int irq, void *data)
{
    int state = gpio_get_value(93);
    gpio_set_value(33, state);
    wake_up_interruptible(&wq);
    return IRQ_HANDLED;
}
Run Code Online (Sandbox Code Playgroud)

现在,以正确的时序调用中断处理程序!