2014-11-21 49 views
3

我想在linux内核中为GPIO编写一个简单的中断处理程序。我使用request_threaded_irq来获取中断上下文处理程序和线程处理程序。如何使用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); 

在这里,我只是请求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; 
} 

在这里,在中断处理程序简单地镜像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; 
} 

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

我该如何设置/使用request_threaded_irq()以便中断处理程序总是被称为“准时”,即使线程处理程序是一些大工作要做的事情?

+0

在ISR和线程化处理程序之间建立一个信号量。只有使用'IRQ_WAKE_THREAD',如果线程人员给了信号量,并且没有更多的工作要做。这就是说,这很奇怪。您没有提供内核版本或您可能已经调查过的任何来源,以了解问题出现的原因。 – 2014-11-21 16:57:58

+0

应该使用信号量来保护数据,但这里没有涉及的数据。内核版本是3.13。我试图弄清楚问题:为什么线程中断处理程序改变中断处理程序的时序? – 2014-11-21 23:30:42

+0

信号量可以保护任何东西。如果你在中断处理程序中做了一个'尝试'并且失败了,那么你返回'IRQ_HANDLED'。如果通过,则返回'IRQ_WAKE_THREAD'。*线程*接受信号量(或者你喜欢的任何无锁的原语)。一个* atomic_t *可能会起作用。 – 2014-11-22 16:28:55

回答

3

我终于明白发生了什么事。根据this answer on 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; 
} 

现在,中断处理程序被调用,一个正确的时机!