ARM基礎學習-異常中斷處理

中斷類型

當異常中斷髮生的時候,系統執行完當前指令後,將跳轉到相應的異常中斷處理程序,當處理程序執行完畢後,程序返回到發生中斷的指令的下一條指令處執行;在進入異常中斷處理程序時,要保存被中斷的執行現場,在異常中斷處理程序退出時,要恢復被中斷的程序的執行現場;

異常中斷類型:
這裏寫圖片描述

1.復位異常發生後,進入到管理模式(svc) 下。
2.軟中斷髮生後, 進入到 管理模式(svc) 下。
3.未定義指令異常發生後, 進入到 未定義指令中止模式(und)下。
4.指令預取中止異常發生後, 進入到 數據訪問中止模式(abt)下;
5.數據訪問中止異常發生後, 進入到 數據訪問中止模式(abt) 下:
6.外部中斷髮生後, 進入到 外部中斷模式(irq)下;
7.快速中斷髮生後, 進入到 快速中斷模式(fiq)下;

中斷向量表和中斷優先級

中斷向量表指定了各異常中斷及其處理程序的對應關係;通常存放在存儲地址的低端;每個中斷對應的中斷向量表中的4個字節存放了一個跳轉指令或者一個向PC寄存器賦值的數據訪問指令,通過跳轉指令,程序跳轉到相應的異常處理處理程序處執行;

幾個異常同時發生的時候需要設置優先級來處理這些異常:

這裏寫圖片描述

ARM對異常中斷的響應過程

(1)ARM處理器對異常中斷的響應過程

  1. 保存處理器當前狀態、中斷屏蔽位以及各條件標誌位。這是通過將當前程序狀態寄存器CPSR的內容保存到將要執行的異常中斷對應的SPSR寄存器中實現的。各異常中斷有自己的物理SPSR寄存器。
  2. 設置當前程序狀態寄存器CPSR中相應的位。包括設置CPSR中的位,使處理器進入相應的執行模式;設置CPSR中的位,禁IRQ中斷,當進入FIQ模式時,禁止FIQ中斷。
  3. 將寄存器Ir_mode(R14)設置成返回地址。
  4. 將程序計數器值(PC),設置成該異常中斷的中斷向量地址,從而跳轉到相應異常中斷處理程序處執行。

(2)從異常中斷處理程序中返回

  1. 恢復被中斷程序的處理器狀態,即將SPSR_mode寄存器內容複製到CPSR中。
  2. 返回到發生異常中斷的指令下一條指令處執行,即將Ir_mode寄存器的內容複製到程序計數器PC中。

(3)響應復位異常中斷

如下情況會導致復位:

  1. 上電覆位:在上電後,復位使內部達到預定的狀態,特別是程序跳到初始入口;
  2. 復位引腳上的復位脈衝:這是由外部其他控制信號引起的;
  3. 對系統電源檢測發現過壓或欠壓;
  4. 時鐘異常復位。

當發生復位 時,處理器硬件響應中斷,自動執行如下操作:

  1. 強制進入管理模式;
  2. 強制進入ARM狀態;
  3. 禁止IRQ中斷和FIQ中斷;
  4. 跳轉到絕對地址PC=0x00000000處執行;

(4)未定義指令異常

如下情況會導致:

  1. 遇到一條無法執行的指令,此指令沒有定義;
  2. 執行一條對協處理器的操作指令,在正常情況下,協處理器應該應答,但協處理器沒有應答。

處理器響應中斷後,硬件自動執行下列操作 :

  1. 把程序狀態寄存器CPSR拷貝給SPSR_und;
  2. 強制進入未定義模式;
  3. 強制進入到ARM模式;
  4. 禁止IRQ中斷
  5. 把下一條指令的地址拷貝給LR;
  6. 跳轉到絕對地址PC=0x00000004處執行;

關於從異常中斷處理程序的返回:

未定義指令異常中斷是由當前執行的指令自身產生的,當產生中斷時,程序計數器PC的值還未更新,它指向當前指令後面的第二條指令(對於ARM指令,它指向當前指令地址加8字節的位置;對於Thumb指令,它指向當前指令地址加4字節的位置)。當未定義指令異常中斷髮生時,處理器自動將值(pc-4)保存到lr_und中,此時(pc-4)指向當前指令的下一條指令,所以從未定義指令異常中斷返回可以通過如下指令來實現:

MOV  PC,LR

當異常中斷處理程序中使用了數據棧時,可以使用下面的指令在進入異常中斷處理程序時保存被中斷程序的執行現場,在退出異常中斷處理程序時恢復被中斷程序的執行現場。異常中斷程序中使用的數據棧由用戶提供。

STMFD   sp! , {reglist,lr}
....
LDMFD   sp! , {reglist,pc}^

reglist時異常中斷處理程序中使用的寄存器列表。標識符^指示將SPSR_mode寄存器的內容複製到CPSR中,該指令只能在特權模式下使用。

(5)軟件中斷異常

是由指令SWI引起的,程序在執行這一指令後,進入異常中斷。處理器響應中斷後,硬件自動執行下列操作 :

  1. 把程序狀態寄存器CPSR拷貝給SPSR_svc;
  2. 強制進入管理模式;
  3. 強制進入到ARM狀態;
  4. 禁止IRQ中斷。
  5. 把下一條指令的地址拷貝給LR;
  6. 跳轉到絕對地址PC=0x00000008處執行;

關於從異常中斷處理程序的返回:

軟件中斷異常是由當前執行的指令自身產生的,當產生中斷時,程序計數器PC的值還未更新,它指向當前指令後面的第二條指令(對於ARM指令,它指向當前指令地址加8字節的位置;對於Thumb指令,它指向當前指令地址加4字節的位置)。當軟件中斷髮生時,處理器自動將值(pc-4)保存到lr_siw中,此時(pc-4)指向當前指令的下一條指令,所以從軟件中斷返回可以通過如下指令來實現:

MOV PC,LR

當異常中斷處理程序中使用了數據棧時,可以使用下面的指令在進入異常中斷處理程序時保存被中斷程序的執行現場,在退出異常中斷處理程序時恢復被中斷程序的執行現場。異常中斷程序中使用的數據棧由用戶提供。

STMFD   sp! , {reglist,lr}
....
LDMFD   sp! , {reglist,pc}^

reglist時異常中斷處理程序中使用的寄存器列表。標識符^指示將SPSR_mode寄存器的內容複製到CPSR中,該指令只能在特權模式下使用。

(5)預取指中止異常

由程序存儲器引起的中止異常叫做預取指中止異常;
由數據存儲器引起的中止異常叫做數據中止異常。

由於ARM的指令是3級流水線結構,讀取指令週期是提前進行的,因此把讀取指令的過程一般稱預取指。在指令預取時,如果目標地址是非法的,該指令被標記成有問題的指令,這時,流水線上該指令之前的指令繼續執行。有兩種可能如下:

  1. 當執行這條指令前程序發生跳轉,則這條無效指令不引起異常中斷;
  2. 當執行到這條指令時,處理器會發生預取指中止異常,引起中斷。

處理器響應中斷後,硬件自動執行下列操作 :

  1. 把程序狀態寄存器CPSR拷貝給SPSR_abt;
  2. 強制進入中止異常模式;
  3. 強制進入到ARM狀態;
  4. 禁止IRQ中斷。
  5. 把中斷時PC的地址拷貝給LR;
  6. 跳轉到絕對地址PC=0x0000000C處執行;

關於從異常中斷處理程序的返回:

在指令預取時,如果目標地址是非法的,該指令被標記成有問題的指令,這時,流水線上該指令之前的指令繼續執行,當執行到該被標記成有問題的指令時,處理器產生指令預取中止異常中斷。發生指令預取異常中斷時,程序要返回到該有問題的指令處,重新讀取並執行該指令,因此指令預取中止異常中斷應該返回到產生該指令預取中止異常中斷的指令處,而不是當前指令的下一條指令。

指令預取異常是由當前執行的指令自身產生的,當產生中斷時,程序計數器PC的值還未更新,它指向當前指令後面的第二條指令(對於ARM指令,它指向當前指令地址加8字節的位置;對於Thumb指令,它指向當前指令地址加4字節的位置)。當指令預取中止異常中斷髮生時,處理器自動將值(pc-4)保存到lr_abt中,此時(pc-4)指向當前指令的下一條指令,所以從軟件中斷返回可以通過如下指令來實現:

SUBS PC,LR,#4

當異常中斷處理程序中使用了數據棧時,可以使用下面的指令在進入異常中斷處理程序時保存被中斷程序的執行現場,在退出異常中斷處理程序時恢復被中斷程序的執行現場。異常中斷程序中使用的數據棧由用戶提供。

SUBS LR,LR,#4
STMFD sp! , {reglist,lr}
….
LDMFD sp! , {reglist,pc}^

reglist時異常中斷處理程序中使用的寄存器列表。標識符^指示將SPSR_mode寄存器的內容複製到CPSR中,該指令只能在特權模式下使用。

(6) 數據中止異常

ARM處理器訪問數據存儲器時,在讀取數據的同時數據存儲器發出了中止信號,引起數據中止異常。如果數據訪問指令的目標地址不存在,或者該地址不允許當前指令訪問,處理器產生數據訪問中止異常中斷;
處理器響應中斷後,硬件自動執行下列操作 :

  1. 把程序狀態寄存器CPSR拷貝給SPSR_abt;
  2. 強制進入中止異常模式;
  3. 強制進入到ARM狀態;
  4. 禁止IRQ中斷;
  5. 把中斷時的PC的地址拷貝給LR;
  6. 跳轉到絕對地址PC=0x00000010處執行;

關於從異常中斷處理程序的返回:

發生數據訪問異常中斷時,程序要返回到該有問題的指令處,重新訪問該數據,因此數據訪問異常中斷應該返回到產生該數據訪問中止異常中斷的指令處,而不是當前指令的下一條指令。

數據訪問異常中斷由當前執行的指令在ALU裏執行時產生,當數據訪問異常中斷髮生時,程序計數器pc的值已經更新,它指向當前指令後面第3條指令(對於ARM指令,它指向當前指令地址加12字節的位置;對於Thumb指令,它指向當前指令地址加6字節的位置)。此時處理器將值(pc-4)保存到lr_abt中,它指向當前指令後面第2條指令,所以返回操作可以通過下面指令實現:

SUBS PC, LR, #8

當異常中斷處理程序中使用了數據棧時,可以使用下面的指令在進入異常中斷處理程序時保存被中斷程序的執行現場,在退出異常中斷處理程序時恢復被中斷程序的執行現場。異常中斷程序中使用的數據棧由用戶提供。

SUBS LR,LR,#8
STMFD   sp! , {reglist,lr}
....
LDMFD   sp! , {reglist,pc}^

reglist時異常中斷處理程序中使用的寄存器列表。標識符^指示將SPSR_mode寄存器的內容複製到CPSR中,該指令只能在特權模式下使用。

(7)中斷請求(IRQ)異常

例如:定時器中斷、串行口通訊中斷、外部信號中斷和A/D處理中斷等。IRQ中斷是可屏蔽的。在狀態寄存器中的I位就是IRQ的屏蔽位。當I=1時。則屏蔽IRQ中斷,當I=0時,則允許中斷。處理器復位後置I爲1,關閉中斷。處理器響應中斷後,硬件自動執行下列操作 :

  1. 把程序狀態寄存器CPSR拷貝給SPSR_irq;
  2. 強制進入IRQ異常模式;
  3. 強制進入到ARM狀態;
  4. 禁止IRQ中斷;
  5. 把中斷時的PC的地址值拷貝給LR;
  6. 跳轉到絕對地址PC=0x00000018處執行;

關於從異常中斷處理程序的返回:

通常處理器執行完當前指令後,查詢IRQ中斷引腳,並查看系統是否允許IRQ中斷,如果某個中斷引腳有效,並且系統允許該中斷產生,處理器將產生IRQ異常中斷,當IRQ異常中斷產生時,程序計數器pc的值已經更新,它指向當前指令後面第3條指令(對於ARM指令,它指向當前指令地址加12字節的位置;對於Thumb指令,它指向當前指令地址加6字節的位置),當IRQ異常中斷產生時,處理器將值(pc-4)保存到IRQ異常模式下的寄存器lr_irq中,它指向當前指令之後的第2條指令,因此正確返回地址可以通過下面指令算出:

SUBS   PC,LR,#4 

當異常中斷處理程序中使用了數據棧時,可以使用下面的指令在進入異常中斷處理程序時保存被中斷程序的執行現場,在退出異常中斷處理程序時恢復被中斷程序的執行現場。異常中斷程序中使用的數據棧由用戶提供。

SUBS LR, LR, #4
STMFD   sp! , {reglist,lr}
 ....
LDMFD   sp! , {reglist,pc}^

reglist時異常中斷處理程序中使用的寄存器列表。標識符^指示將SPSR_mode寄存器的內容複製到CPSR中,該指令只能在特權模式下使用。

注:爲什麼PC會指向當前執行指令的後12個字節?

當前指令執行時(此時PC指向當前指令後面的第2條指令),如果發生IRQ中斷,ARM檢測到IRQ中斷後,取指和執行單元都不會改變,只有譯碼單元會改變,譯碼單元改爲開始譯碼中斷指令。執行完當前指令後,PC值加4個字節(此時PC指向剛剛那條指令後面的第3條指令),譯碼單元將譯完的中斷指令送到執行單元,執行單元執行中斷指令,保存PC-4(此時PC指向當前指令後面的第2條指令)的值到LR_irq,同時跳轉到IRQ中斷向量處。(詳細可看ARM流水線機制)

(8)快速中斷(FIQ)請求異常。

FIQ快速中斷是可屏蔽的。在狀態寄存器中的F位就是FIQ的屏蔽位。當F=1時。則屏蔽FIQ中斷,當F=0時,則允許中斷。處理器復位後置F爲1,關閉中斷。處理器響應中斷後,硬件自動執行下列操作:
1. 把程序狀態寄存器CPSR拷貝給SPSR_fiq;
2. 強制進入FIQ異常模式;
3. 強制進入到ARM狀態;
4. 禁止FIQ中斷;
5. 把中斷時的PC的地址值拷貝給LR;
6. 跳轉到絕對地址PC=0x0000001C處執行;

關於從異常中斷處理程序的返回:

通常處理器執行完當前指令後,查詢FIQ中斷引腳,並查看系統是否允許FIQ中斷,如果某個中斷引腳有效,並且系統允許該中斷產生,處理器將產生FIQ異常中斷,當FIQ異常中斷產生時,程序計數器pc的值已經更新,它指向當前指令後面第3條指令(對於ARM指令,它指向當前指令地址加12字節的位置;對於Thumb指令,它指向當前指令地址加6字節的位置),當FIQ異常中斷產生時,處理器將值(pc-4)保存到IRQ異常模式下的寄存器lr_fiq中,它指向當前指令之後的第2條指令,因此正確返回地址可以通過下面指令算出:

SUBS   PC,LR,#4 

當異常中斷處理程序中使用了數據棧時,可以使用下面的指令在進入異常中斷處理程序時保存被中斷程序的執行現場,在退出異常中斷處理程序時恢復被中斷程序的執行現場。異常中斷程序中使用的數據棧由用戶提供。

SUBS LR, LR, #4
STMFD   sp! , {reglist,lr}
....
LDMFD   sp! , {reglist,pc}^

reglist時異常中斷處理程序中使用的寄存器列表。標識符^指示將SPSR_mode寄存器的內容複製到CPSR中,該指令只能在特權模式下使用。

FIQ和IRQ補充

FIQ和IRQ都是用於外部設備向CPU請求中斷服務,這兩個異常中斷的引腳都是低電平有效,都可以通過CPSR的I控制位來設置是否屏蔽;

FIQ比IRQ的異常中斷優先級高,所以FIQ通常用於對於相應時間要求比較苛刻的任務,FIQ異常中斷向量爲0X1C,位於中斷向量表的最後,這樣FIQ異常中斷程序可以字節放在地址0X1C後面,這樣節省了中斷向量表中的跳轉指令;

當系統存在cache時,可以把FIQ異常中斷向量和處理程序放在一起鎖定在cache中,從而大大提高相應時間,同時FIQ異常模式有額外的5個寄存器,可以有效的提高執行速度;

對於中斷處理程序重入和不可重入

不可以重入的中斷程序,在函數前用關鍵字__irq聲明;不可重入的中斷處理函數裏會做如下操作:
1. 保存APCS規定的被破壞的寄存器;
2. 保存其他中斷處理程序用到的寄存器;
3. 同時將(LR - 4)賦予程序計數器PC實現中斷處理程序的返回,並且恢復CPSR寄存器的內容;

缺省情況下ARM 中斷是不可重入的,因爲一旦進入異常響應狀態,ARM 自動關閉中斷使能。如果在異常處理過程中簡單地打開中斷使能而發生中斷嵌套,顯然新的異常處理將破壞原來的中斷現場而導致出錯。但有時候中斷的可重入又是需要的,對應可重入異常中斷處理程序需要做如下特別操作:

  1. 將返回地址保存到IRQ的數據棧中;
  2. 保存工作寄存器和SPSR_irq;
  3. 清除中斷標誌位;
  4. 將處理器切換到系統模式,重新使能中斷;
  5. 保存用戶模式的LR寄存器和被調用者不保存的寄存器;
  6. 調用C語言的IRQ/FIQ異常中斷處理程序;
  7. 當C語言的IRQ/FIQ異常中斷處理程序返回後,恢復用戶模式的寄存器,並禁止中斷;
  8. 切換到IRQ模式,禁止中斷;
  9. 恢復工作寄存器和寄存器LR_irq;
  10. 從IRQ異常中斷處理程序中返回;
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章