2010-12-07 109 views
2

傳遞ARGS考慮我們正在編寫固件的baremetal MCU,即沒有操作系統。我被告知它不可能(非法?)將參數傳遞給中斷處理函數?在中斷處理程序

我無法準確理解爲什麼是這樣嗎?這有什麼問題?

PS。是否有可能在某些RTOS-es,嵌入式Linux等中使用,或者它從根本上錯誤?

回答

3

唯一的其他東西我會指出(尚未到目前爲止提到)是一個「軟件中斷」的概念(有時稱爲「陷阱」),其中大部分處理器的支持。

的想法是,一個特殊的指令導致異常發生,並經常與軟件中斷,無論是操作碼導致異常,或登記成立前的異常,可以包含值/參數。

例如,在ARM處理器中,根據您的體系結構查找「SWI」或「SVC」。我相信隨着SWI指令,低8位不是操作碼的一部分 - 你可以填寫任何你想要的值0-255(這裏的內存有點模糊)。

不同於硬件啓動中斷,這是完全異步的CPU上運行的代碼,軟件中斷是同步的 - 它在執行啓動指令時(禁止中斷屏蔽,嵌套等)

3

中斷處理程序是由硬件調用。無論硬件通過它的「參數」是「通過」。

就是這樣。

4

沒有參數可以明確地傳遞給中斷處理程序,因爲它的設計是由硬件來調用。每個體系結構在調用時會施加特定的堆棧幀,通常包括CPU的已保存狀態。

如果您還打算從代碼中的其他地方調用中斷處理程序,那麼您有一個設計缺陷,或者有一些可能被分解出來以便在中斷處理程序和算法代碼之間共享的代碼。

+0

感謝您的答覆。如果我理解你的話,最重要的是IRQ處理程序與程序流異步調用,編譯器在傳遞參數時不知道*何時。 – Mark 2010-12-07 03:40:18

4

中斷。做那個......中斷。想象一下家中的門鈴,在任何特定的隨機時間白天或晚上打斷你。您是否可以期望在任何時候都可以在您的手中擁有所有可能發生的特定中斷的正確項目。您必須能夠烹飪晚餐,洗澡,摺疊衣物,但是在門鈴響起之前,您必須根據敲響鈴聲的人準確掌握正確的物品,而無需知道它們在那裏,或者即將或即將響起的鐘聲。不太可能。同樣的處理,中斷在任何特定時間發生,對於大多數處理器在當前正在執行的指令之後立即調用中斷處理程序,這意味着每一條指令都必須嘗試執行前臺應用程序,同時保留中斷的所有參數處理程序,並在一個指令時間內完成所有這些操作。

現在是什麼是可能與操作系統或RTOS或者叫什麼你會,一些層。爲了讓真正的中斷處理程序知道什麼都沒有進入並且必須弄清楚,一旦它發現中斷將收集信息,然後調用傳遞參數的高級中斷處理程序。當然可能和大多數/多種操作系統都是這樣做的。

+0

很好的例子!最佳答案。換句話說:在裸機硬件層面上,沒有參數,沒有返回值等。在Linux {和其他RTOSes}平臺上,有一個「中斷驅動程序」(所有中斷使用的通用代碼)該驅動程序( 1)通常讀取硬件寄存器以確定發生了哪個中斷,(2)將該數字用作索引軟件在表格中查找以查找處理函數和可能的參數。相反,微芯片RTOS(Cortex M3)在硬件上做了一些不同的事情,硬件爲每個中斷調用不同的功能 – user3696153 2014-06-14 04:46:56

0
發生

當你使用下面的調用設置中斷處理程序時,它看起來像中斷處理程序需要一些參數並返回irqreturn_t。這是不是中斷處理程序OP在說什麼?

int request_irq(unsigned int irq, 
       irqreturn_t (*handler)(int, void *, struct pt_regs *), 
       unsigned long flags, 
       const char *dev_name, 
       void *dev_id); 
0

可以使用共享變量正常碼流期間設置影響下一次它運行的中斷處理程序的行爲。但是因爲你不直接調用ISR,所以你不能傳遞參數。這不是合法性問題,而是技術性問題。

如:

volatile enum 
{ 
    DO_NOTHING, 
    DO_A, 
    DO_B, 
    DO_C 

} isr_action ; 

__interrupt (SOME_IRQ) myISR() 
{ 
    switch isr_action 
    { 
     case DO_A : 
     { 
      // A 
     } 
     break ; 

     case DO_B : 
     { 
      // B 
     } 
     break ; 

     case DO_C : 
     { 
      // C 
     } 
     break ; 
    } 
} 

int main() 
{ 
    // Make ISR do A on next SOME_IRQ 
    isr_action = DO_A ; 

    for(;;) 
    { 
     // wait for interrupt 
    } 
}