1. 程式人生 > >ARM 7 使用者模式下禁止/使能中斷的一種方法--使用軟中斷 for Keil MDK

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   語句,呼叫禁止中斷函式,實現關中斷.