天天看點

handle_level_irq 與handle_edge_irq 的差別【轉】

版權聲明:本文為部落客原創文章,未經部落客允許不得轉載。

handle_level_irq

 *    Level type interrupts are active as long as the hardware line has

 *    the active level. This may require to mask the interrupt and unmask

 *    it after the associated handler has acknowledged the device, so the

 *    interrupt line is back to inactive.

     當中斷線電平達到激活電平,中斷一直會被激活。 是以需要剛進中斷處理函數就要屏蔽掉中斷,

等handler 處理完後再打開中斷(unmask)

 Pesudo code

handle_level_irq()  

{  

  mask( irq );  

  ack( irq );  

  status |=IRQ_INPROGRESS;  

  handle_IRQ_event();   

  status &=~IRQ_INPROGRESS;   

  unmask( irq );  

}  

      由于irq在整個處理過程中都被屏蔽,是以需要handle_level_irq裡的action要盡量簡短

handle_edge_irq

 *    Interrupt occures on the falling and/or rising edge of a hardware

 *    signal. The occurence is latched into the irq controller hardware

 *    and must be acked in order to be reenabled. After the ack another

 *    interrupt can happen on the same source even before the first one

 *    is handled by the assosiacted event handler. If this happens it

 *    might be necessary to disable (mask) the interrupt depending on the

 *    controller hardware. This requires to reenable the interrupt inside

 *    of the loop which handles the interrupts which have arrived while

 *    the handler was running. If all pending interrupts are handled, the

 *    loop is left.

    中斷發生在上升沿/下降沿, 它會被中斷控制器鎖存起來,需要ack 後才能重新使能。 Ack 後新的

中斷可以在前一個中斷正在被處理時産生,如果這種情況發生,則需要屏蔽中斷。同時,需要用一個loop

來進行中斷處理過程中又有中斷産生的情況,在這個loop中重新把中斷屏蔽打開。 如果所有pending的

中斷都處理完了,loop就可以離開。

Pesudo code

handle_edge_irq()  

   if( status & IRQ_INPROGRESS ) {  

      status |= (IRQ_PENDING | IRQ_MASKED);  

      mask();  

      ack();  

      return;  

   }  

   ack();  

   status |= IRQ_INPROGRESS;  

   do{  

       if( status & (IRQ_PENDING | IRQ_MASKED ) )  

         umask();  

       handle_IRQ_event();  

   }while( status & IRQ_PENDING );   

   status &= ~IRQ_INPROGRESS;  

中斷觸發方式的比較

http://blog.21ic.com/user1/2662/archives/2007/37347.html

    沿觸發: 這是很最常見的觸發方式,我們可以用數字電路的方法來解釋它的特性。沿觸發應該應觸發器來描述:  輸入引腳(當作觸發器的CLK) ----> 觸發器------> 中斷控制器 ,當輸入引腳的相應的沿到來時,就會将觸發器置1,并觸發中斷,觸發器會一直保持電平1除非在ISR中用一條語句清0,否則會不斷的觸發中斷,這也就是每 次觸發中斷都要清0的原因。當有高優先級的中斷運作後退出時,處理器檢測到觸發器的值為1,是以依然會進入中斷服務程式。

    電平觸發: 有的時候,邊沿觸發很容易産生毛刺并導緻誤中斷,這時候就要使用電平觸發,電平觸發是持續觸發,可以用數字電路的緩沖器來描述

     輸入引腳 ----> 緩沖器 ----> 中斷控制器  , 緩沖器的作用就是對信号整形,并增加驅動能力,緩沖器輸出的資料和輸入的資料相同,可以看出輸入引腳的電平直接放映到輸出引腳,以高電平觸發為例,隻要輸 入引腳的電平為高就立即觸發中斷,當ISR退出時如果電平依然為高則會再次觸發中斷,這也就是持續觸發的來由,是以采用電平觸發時必須保證電平的持續時間 不能太長,在ISR中可能需要适當的延時操作保證退出時電平為低,或者讀出電平值,電平變低時才退出。 在帶用 OS的系統中,很多關鍵的資料或者代碼區(臨界區)都需要關閉中斷,那麼它對中斷有什麼影響呢?  電平觸發如果電平的持續時間比較短,很可能在關閉中斷後再開中斷之前電平已經變低,結果開中斷後中斷就沒有觸發,結果是這次中斷被漏掉了,是以在帶OS的 系統中一定不能關閉中斷太久,在允許中斷嵌套的情況下必須保證高優先級的中斷執行時間不能超過電平的持續時間。 綜合考慮,電平觸發的持續時間不能太短也不能太長,在自己的系統中要仔細地考慮好中斷地持續時間。

      另外,開關中斷也是很講究的,在我的開發中我就發現一種“ISR優先級翻轉現象”,比如我有三個ISR,按照優先級的高低次序一次是 ISR0   ISR1  ISR2,我在ISR3 關閉ISR0的中斷(因為共享資料需要互斥),可知ISR3 運作時ISR0不能得到響應,然而ISR1的優先級高于ISR2,是以在支援嵌套的情況下ISR1會打斷ISR2的執行,顯然這時即使ISR0中斷到來也 不會得到響應,這也就是我遇到的ISR優先級翻轉問題,當然這可能是我編寫程式的風格不好,但是分析起來也是很有趣的,類似于任務的優先級翻轉。

本文轉自張昺華-sky部落格園部落格,原文連結:http://www.cnblogs.com/sky-heaven/p/7457906.html,如需轉載請自行聯系原作者

繼續閱讀