ARM 7 使用者模式下禁止/使能中斷的一種方法--使用軟中斷 for Keil MDK
最近寫一個程式,需要在使用者模式下關中斷,但ARM 7的體系結構決定了中斷必須在特權模式下才可以更改,所以想到使用ARM的軟中斷來實現關中斷和開中斷.
使用軟中斷,首先要有硬體指令的支援.ARM有條指令是SWI.
SWI 指令的格式為:
SWI {條件} 24 位的立即數
SWI 指令用於產生軟體中斷,以便使用者程式能呼叫作業系統的系統例程。作業系統在 SWI 的異常處理程式中提供相應的系統服務,指令中 24 位的立即數指定使用者程式呼叫系統例程的型別,相關引數通過通用暫存器傳遞,當指令中 24 位的立即數被忽略時,使用者程式呼叫系統例程的型別由通用暫存器 R0 的內容決定,同時,引數通過其他通用暫存器傳遞。
指令示例:
SWI0x02;該指令呼叫作業系統編號位02的系統例程。
在keil MDK中,關鍵字__svc可以產生硬體SWI指令,使得處理器能響應軟體中斷.關鍵字__svc,keil MDK幫助檔案中這樣描述:
__svc 關鍵字宣告超級使用者呼叫 (SVC) 函式,該函式最多使用四個類似於整數的引數,並通過 value_in_regs 結構最多返回四個結果。
__svc 是一個函式限定符。它影響函式的型別。
語法
__svc(int svc_num) return-type function-name([argument-list]);
其中:
svc_num 是在 SVC 指令中使用的立即值。
它是一個表示式,其計算結果為以下範圍內的整數:
• 在 ARM 指令中為 0 到 224–1 (24 位值)
• 在 16 位 Thumb 指令中為 0-255 (8 位值)。
要在keil MDK中使用軟體中斷,要做好兩件事:第一件,更改啟動檔案,編寫軟體中斷的彙編入口.在這個彙編入口中主要根據軟體中斷命令號進行相應的函式跳轉.第二件,編寫相應命令號的C語言服務函式.下面舉例怎麼樣用軟體中斷實現開中斷和關中斷.
第一步:更改啟動程式碼
keil MDK自帶的啟動程式碼有類似下面的語句:
Vectors LDR PC, Reset_Addr
LDR PC, Undef_Addr
LDR PC, SWI_Addr
LDR PC, PAbt_Addr
LDR PC, DAbt_Addr
藍色語句是程式復位後要執行的第一條指令,即復位異常入口;而紅色語句就是執行一個軟體中斷指令後,要跳轉到的軟體中斷異常入口.通過語句"SWI_Addr DCD SWI_Handler"進行中轉,軟體中斷會跳轉到標號為SWI_Handler的語句處,該處即處理軟體中斷的命令號.原始碼如下:
EXPORT SWI_Handler
extern EnableIrqFunc ;使能中斷函式名,用C語言實現
extern DisableIrqFunc ;禁止中斷函式名,用C語言實現
SWI_Handler
STMFD SP!, {R0,R12,LR} ;入棧
LDR R0, [LR,#-4] ;取指令
BIC R0,R0,#0xFF000000 ;取軟體中斷命令號
CMP R0,#0 ;和0比較,因為我的使能中斷用了軟體中斷命令0,禁止中斷使用了軟體中斷命令1
BLEQ EnableIrqFunc ;為零呼叫使能中斷函式
BLNE DisableIrqFunc ;不為零呼叫禁止中斷函式
LDMFD SP!,{R0,R12,PC}^ ;出棧
第二部:編寫相應命令號的C語言服務函式.
宣告軟體中斷:
__svc(0x00) void EnableIrq(void); //使能中斷
__svc(0x01) void DisableIrq(void); //禁止中斷
編寫服務函式:
到此,使能和禁止中斷的軟中斷就結束了,下面看一下執行過程.
在程式中,如果想關中斷,只需使用:DisableIrq();
MDK編譯器在執行這句函式時,自動用軟中斷指令代替,即: SWI 0x01
ARM執行這條軟體中斷指令後,發生軟體中斷異常,程式跳轉到軟體中斷異常服務函式處,即彙編程式碼標號為SWI_Handler處,在這裡判斷軟體中斷命令號是0x01,然後執行 BLNE DisableIrqFunc 語句,呼叫禁止中斷函式,實現關中斷.