2014-11-21 79 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; 
} 

現在,中斷處理程序被調用,一個正確的時機!