中斷同時發生時會發生什麼?

在各種嵌入式編程中都對此有所疑惑。比如兩個中斷源同時到達,會產生什麼效果。是否會有一個中斷會忽略掉?

在AVR、ARM中都有個全局中斷標識,將其關閉則所有中斷都收不到。而當打開時就允許了中斷的發生,此時發生中斷並進入中斷處理常式時,AVR會暫時關閉全局中斷。而軟體可以將其重新打開,使得中斷可以嵌套發生。但是並沒有人解釋如果不用中斷嵌套,則正在處理中斷時,發生的中斷事件會被如何處理?

ARM的方式則是提供了中斷優先順序,使得同時發生的中斷可以有個先被處理。但同樣的問題,當一個中斷正在被處理時,進入的中斷會被如何處理?

此類情況很難用自己編程來模擬。當前我有個猜測,就是各個中斷源在硬體上互相獨立,並且可以並發處理中斷源。但是如果正在有中斷髮生時,會設置自己組件的中斷標誌位,然後就自己忽略掉了。


不是外界事件首先引發了中斷跳轉,跳轉時順便置上中斷標誌,而是外界事件導致置上了中斷標誌,然後中斷標誌再進一步引發了跳轉。

標誌置上了並不等於立即就會引發跳轉。標誌本身只是用來看的,就是說,得等CPU看到這個標誌,才能真正引發跳轉。

觸發中斷的,實質上既不是外部設備,也不是標誌,而是CPU自己。

CPU只在每個指令周期的開頭瞅一眼中斷標誌,有,則進入處理過程,沒有,則繼續做它自己的事。如果不巧,標誌置晚了,CPU已經瞅完了,那就只能等下一輪指令周期。

所謂的屏蔽中斷,就是人為在中斷標誌前面掛個幕布,不許瞅。只是不許瞅而已,但沒有不許立標誌,外部設備盡可以來立標誌,只是立得再久也沒人處理而已,直到幕布被摘下。

當CPU瞅到了一個標誌、並進入其處理過程之時,還會自己給自己戴個眼罩,此時哪怕還有別的標誌,也瞅不見了,所以此時別的中斷髮生,也得不到處理。

當CPU處理完了這個中斷,會自己把眼罩摘掉,於是又能愉快的瞅標誌了。如果有別的標誌正巧豎在那,那就處理吧。

顯而易見,當CPU放眼一瞅的時候,瞅到不止一個中斷標誌是完全可能的,而它一次只能選一個來處理。一般來說肯定挑出其中最有價值的一個,剩下的先放著,等下回瞅。這就是傳說中的中斷優先順序。

再刨根問底一點,當CPU已經開始處理一個中斷的時候,這標誌會怎樣?——根據中斷的具體類型不同,這標誌可能被CPU自動清除掉,也可能不會,而要等用戶程序來手動清除。

如果用戶犯2了沒清除標誌怎麼辦?那麼下次CPU放眼瞅的時候,這個標誌還在!會不會再被處理一遍?——會的,而且不止一遍,只要你不清,它就根本停不下來。

為什麼系統要這麼設計,給用戶以犯2的機會?——有一種情況是,向量表不夠裝,多個中斷共用一個向量,那麼進入處理程序時,要有手段來區分到底是發生了哪個中斷。所以標誌要活到那個時候來給用戶檢查。

然後我們終於面對了這個問題:如果一個標誌還沒被處理呢,就有人要來豎一個同樣的標誌(重點是:同樣的),會怎樣?——沒錯,前一個會丟失。豎標誌的場地只有一個,只能記錄標誌有沒有,不能記錄標誌有幾個。——這不是很可怕?——別急,先來仔細分析下:

很多中斷,屬於不作不死型:即,只有發起相應操作,才能收到相應結果的中斷。不種瓜不可能得瓜。——對於這種,只要在收到前一個操作的結果中斷之前不發起後一個操作(且不管機能上能不能做得到),就不會面臨中斷丟失的情況。

還有一些中斷,來幾個意義都不變。比如我媽喊我吃飯,沒等我去,我爸又來喊我一遍,最後我妹又來喊我一遍。無論如何,我最終都是去吃這一頓飯而已,不會吃三頓。這種中斷自然也不怕丟失。

若非以上情況,就沒辦法了,只能儘快處理,不要浪費太多時間在眼罩階段,而耽誤了瞅標誌。然而……世事不盡如人意,如果長時間戴眼罩不可避免,又必須及時處理另一個中斷,怎麼辦?

有的系統具備一種功能,能讓某些中斷標誌發出動感光波,射穿眼罩直達狗眼。媽媽再也不怕我瞅不著標誌了,哪怕正在處理一個中斷,也立即給你扔下,跑去處理另一個更NB的中斷。這就是中斷嵌套。

自然不能所有中斷標誌都能發出動感光波,那世界就亂了。這種特權要嚴密控制,只能交給少量真正高大上的中斷源。

而當CPU進入這種中斷的處理程序的時候,給自己戴的也不是一般的眼罩了,而是超強合金眼罩,連光波都能抵擋的,這保證了多個光波中斷源之間也不會搶來搶去而亂了規矩。

不過當然規矩也是人定的,沒準某個系統里就需要有更更更高級的中斷源,需要更更更強的光波,連合金眼罩也能射穿,同時自己還得具備更更更強的氪金眼罩……OK這是可行的,根據中斷源不同,光波也好眼罩也好都存在多個級別,這叫做中斷的嵌套優先順序。而前面說的優先順序則叫做中斷的響應優先順序。

響應優先順序和嵌套優先順序是兩個不同的概念,但有時被搞混。理論上,響應優先順序再高也沒法讓你能打斷別人的中斷處理過程,嵌套優先順序再高也沒法讓你比人優先被瞅到(當然先瞅到別人再被你打斷另說)。當然,系統的關鍵中斷往往兩種優先順序都很高。

另外,多個中斷的響應優先順序一般沒有同級的,因為事到臨頭總是要分個高下的。而嵌套優先順序則可以同級,而同級一般是不能互相打斷的。

說回來,以上描述的參照的是答主自己熟悉的平台,別的平台可能有細微差別,但精神都是類似的。


首先你要清楚,中斷時發生了什麼,以及如何實現現場的保護與恢復、中斷屏蔽、自動響應,然後再看多個中斷同時到達時如何排隊判優、嵌套,也就是你想知道的同時中斷時發生了什麼

一些廢話得先說下:

中斷指在程序運行過程中,由於異常或特殊請求,而終止現行程序,轉去處理異常或特殊請求,再恢復原運行程序的過程。

中斷過程的完成依賴於中斷系統,由軟硬體組成,是I/O系統的一部分。但中斷不只用於主機與外設的數據交換。

CPU設中斷允許標誌位IF或中斷屏蔽標誌位IM實現對特定中斷的屏蔽與響應。這裡就有可屏蔽中斷INTR和不可屏蔽中斷NMI。

關於程序計數器PC、程序狀態字PSW、中斷向量、向量地址等不多說。

n個中斷請求觸發器合起來叫IRR(中斷字),n個中斷屏蔽觸發器合起來叫IMR(屏蔽字)。大概是這種感覺:

圖1

優先排隊泛泛地說:硬故障&>DMA(對應程序中斷,可以認為DMA是一種簡單中斷)&>I/O程序中斷

將中斷源分級,即中斷級,有級間優先權,級內優先權。

1.單級中斷

優先次序事先定好,不能嵌套。同時請求才看優先順序。各中斷源用一條請求線。大概是這種感覺:

圖2

識別中斷源

1.軟體查詢。查詢次序即優先順序次序。

2.硬體識別判優。硬體固定,則優先次序固定。缺點:故障敏感,一點斷全線癱;不支持嵌套。大概是這種感覺:

圖3

具體來說就是菊♂花♂鏈:

圖4

2.多級中斷

每級公用請求線和響應線,分級內優先次序和級間優先次序。大概是這種感覺:

圖5

對於二位多級中斷,其最左判優邏輯電路如下:

圖6

該電路具有響應時間對各請求均等的特點。這個試著算一下就知道了,假設有8個IR,且與非門和非門的時延均為T。1表示此位有請求,0表示沒有請求。我們以下面兩種情況為例求排隊器的時延(寫在括弧內):

egin{tabular}{ cccccccc }
hline
$IR_1$  $IR_2$  $IR_3$  $IR_4$  $IR_5$  $IR_6$  $IR_7$  $IR_8$ \
hline
0(0T) 0(2T) 1(3T) 0(2T) 1(4T) 0(2T) 0(2T) 0(2T)\
1(0T) 0(2T) 0(2T) 1(3T) 0(2T) 0(2T) 0(2T) 0(2T)\
hline
end{tabular}

多試幾種情況可以找到如下規律:

egin{tabular}{ccc}
hline
left-most requestfollowing requests\
hline
$IR_1=1$ $0T$ $3T$\
$IR_1=0$ $3T$ $4T$\
hline
end{tabular}

我們把上面的東西放到大的環境下考慮:

圖7

其中①對應圖6的排隊器,②對應圖6的IRR、IMR,③對應圖4 IRR、IMR以上的部分。

需要說的是:識別和判優同時完成。先請求,先響應。先響應的未必先處理,優先次序由當前IMR決定。排隊電路決定響應優先權,它是不可變的,IMR決定處理優先權,它是動態分配的。每個中斷級均有自己的屏蔽字。CPU是否相應取決於優先順序關係和屏蔽字。

所以完整一點看,中斷前後大概要發生下面的事情:

  1. 當前指令周期結束

  2. 查詢是否有DMA請求

  3. 查詢是否有NMI

  4. 查詢是否有INTR

  5. 查詢CPU是否允許中斷

  6. 發INTA,接收INVEC

  7. 關中斷

  8. PC、PSW壓棧

  9. 中斷服務程序入口地址-&>PC

  10. 保護現場

  11. 交換屏蔽字

  12. 開中斷

  13. 中斷服務

  14. 關中斷

  15. 換回原屏蔽字
  16. 恢復現場

  17. 開中斷

  18. 中斷返回,PSW、PC彈棧

  19. 下條指令取指周期

這樣我們舉個例子解釋一下題主的問題,事情應該就很清楚了。

比如說我的機器有L_1,L_2,L_3,L_4,L_5,中斷響應優先次序為L_1>L_2>L_3>L_4>L_5,今欲將其改為L_2>L_4>L_1>L_5>L_3,那麼各級的中斷屏蔽字可設為:

egin{tabular}{ cccccc }
hline
  $L_1$ $L_2$ $L_3$ $L_4$ $L_5$\
hline
$L_1$ 1 0 1 0 1\
$L_2$ 1 1 1 1 1\
$L_3$ 0 0 1 0 0\
$L_4$ 1 0 1 1 1\
$L_5$ 0 0 1 0 1\
hline
end{tabular}

這時,若5級請求同時發出,我們表示一下CPU執行程序的軌跡:

這張圖是什麼意思?為什麼是這樣?

聰明的你一定已經明白咯:)


題主還有很多其他人都有這個疑問,主要是因為中斷子系統這幾年發展得非常快,概念被變更得很厲害。我們用包袱比較少的ARMv8構架來理解,就可以很快釐清這裡面的關係了。

ARMv8的中斷構架稱為GIC,全局中斷控制。示意如下(我省略了ITS,這個和我們要掌握的概念無關,有興趣的讀者自己去找GIC的Specification來看):

其中,GICD負責收集設備的中斷,GICR建立給CPUIF的橋樑(從軟體角度理解暫時可以忽略),CPUIF負責給CPU的中斷線(比如IRQ,FIR等)輸出中斷信號等工作。

所以,我們說關中斷,可以有兩種理解,一種是從GICD就把某個設備給屏蔽掉,讓中斷報不上來,一種是在CPU裡面關中斷,讓CPUIF的中斷報不上來。當然,軟體通常指後面一種,但你看硬體資料,它有時指前面一種,這就是我們很多人看軟體實現看不懂的一個原因。

ARMv8的中斷狀態切換一般有這麼幾種,我們暫時認為這個狀態機在GICD上,它的簡化理解如下:

簡單說,一開始GICD的狀態是Idle,中斷來了,就變成Pending,中斷信號就發給CPU了,CPU如果處理這個中斷,就讀IAR寄存器(可以得到中斷號),一旦你來讀這個寄存器,GICD的狀態就切換到Active,處理完成後,CPU再訪問EOI寄存器(End of Interrupt),狀態就切換回Idle。

這個過程,和軟體一般理解的進入中斷向量,然後eret,是相互獨立的過程,GIC是按這個流程來管理中斷上報的,軟體定義自己的概念,和硬體如何報中斷上來,兩者不是直接相關的。我們必須獨立理解這兩個流程。

現在我們來理解優先順序嵌套,ARMv8是這樣管理這個關係的:

1. 每個中斷都被指定一個優先順序(這個是硬體設計的時候決定的)

2. 當一個中斷報到GIC上,GIC進入Pending狀態,同時把GIC的優先順序提升到和這個中斷的優先順序一致,這時如果有新的中斷進入,就要比較兩者的優先順序,優先順序低的中斷會被排隊(排隊過長會被丟棄)

3. 等GIC切換到Active,會產生一次Priority Drop,GIC的優先順序會掉回來,然後嵌套的中斷就可以進入GIC,這個時候GIC會處於一個Active Pending的狀態,但這些不影響CPUIF上的行為,CPUIF繼續按有中斷來就產生一次中斷的方式運作。所以這個時候看你在CPU上是否屏蔽中斷,不屏蔽,同樣會產生中斷嵌套(從中斷上下文中產生第二次中斷);屏蔽就會排隊,等一個中斷處理完了,打開CPU上的中斷掩碼才會讓下一個中斷進來。

這樣理解,可能這類誤解就沒有了。如果還不明白,就在討論區接著問吧。


上面幾位都寫的很好, 補充一點, "當一個中斷正在被處理時,進入的中斷會被如何處理?"這個問題和arm本身沒有多大關係, arm只是提供了相關的機制, 具體的策略需要讓在arm上運行的軟體實現, 比如說linux操作系統.linux的做法是在把中斷分為上半部和下半部, 在中斷的上半部, 只處理之前被響應的一個中斷, 不會響應其他任何中斷.在這段時間內, 其他所有中斷都會被屏蔽, 但是你要注意, 這裡只是屏蔽, 沒有忽略.在處理完中斷上半部的時候, 會打開中斷響應, 繼續響應其他中斷.另外, 有一種情況下中斷是會被忽略的, 就是在處理某一個中斷上半部的時候, 來了一個來自於中斷源A的中斷1, 那麼在處理中斷上半部, 屏蔽中斷期間, 來自於中斷源A的其他中斷會被屏蔽. 但是來自於其他中斷源的中斷2不受影響.


在STM32里,中斷標誌要靠軟體清除。已響應的中斷標誌肯定被清除了,然後中斷控制器根據未清除的中斷標誌再生成一次中斷不就好了。Cortex-M3,M4是支持中斷嵌套的。


看優先順序,優先順序別高的可以中端優先順序別低的


中斷有優先順序,寶寶。。


中斷是有優先順序的呀。好多課本都會講。


我覺得你應該理解中斷是歸中斷管理器管理的,這是個硬體管理的過程。所有中斷經過它仲裁後交給軟體處理。


推薦閱讀:

自己寫四軸飛控難度有多大?是個可完成的任務嗎?
國內做化學分析儀(色譜,光譜等等……)比較好的有哪些公司?
Linux下開發,stm32和arduino,我該何去何從?
樹莓派比起低功耗x86 CPU有什麼獨特優勢?

TAG:嵌入式系統 | 電子 | 單片機 |