新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM微處理器的編程模型之:異常中斷處理

        ARM微處理器的編程模型之:異常中斷處理

        作者: 時間:2013-09-13 來源:網絡 收藏

        本文引用地址:http://www.104case.com/article/257085.htm

        2.編譯器對中斷處理函數編寫的擴展

        考慮到中斷處理函數在現場保護和返回地址的處理上與普通函數的不同之處,不能直接把普通函數體連接到異常向量表上,需要在上面加上一層封裝,下面是一個例子。

        IRQ_Handler ;中斷相應函數

        STMFD SP!,{r0-r12,lr} ;保護現場,一般只需要保護{r0-r3,LR}

        BL IrqHandler ;進入普通處理函數,C或匯編均可

        ……

        LDMFD sp!,{r0-r12,LR} ;恢復現場

        SUBS pc,lr,#4 ;中斷返回,注意返回地址

        為了方便使用高級語言直接編寫異常處理函數,編譯器對此做了特定的擴展,可以使用函數聲明關鍵字_irq,這樣編譯出來的函數就可以滿足異常響應對現場保護和恢復的需要,并且自動加入LR減4的處理,符合IQR和FIQ中斷處理的要求。

        下面的例子顯示了使用_irq對中斷處理函數產生的影響。

        C語言源程序如下。

        __irq void IRQHandler (void)

        {

        volatile unsigned int *base = (unsigned int *) 0x80000000;

        if (*base == 1)

        {

        /*調用C語言中斷處理函數*/

        C_int_handler();

        }

        /*清楚中斷標志*/

        *(base+1) = 0;

        }

        使用armcc編譯出的匯編代碼如下。

        IRQHandler PROC

        STMFD sp!,{r0-r4,r12,lr}

        MOV r4,#0x80000000

        LDR r0,[r4,#0]

        SUB sp,sp,#4

        CMP r0,#1

        BLEQ C_int_handler

        MOV r0,#0

        STR r0,[r4,#4]

        ADD sp,sp,#4

        LDMFD sp!,{r0-r4,r12,lr}

        SUBS pc,lr,#4

        ENDP

        如果不使用_irq子程序聲明關鍵字,編譯出的匯編代碼如下。

        IRQHandler PROC

        STMFD sp!,{r4,lr}

        MOV r4,#0x80000000

        LDR r0,[r4,#0]

        CMP r0,#1

        BLEQ C_int_handler

        MOV r0,#0

        STR r0,[r4,#4]

        LDMFD sp!,{r4,pc}

        ENDP

        3.可重入中斷設計

        在缺省情況下,中斷是不可重入的。因為一旦進入異常響應狀態,ARM自動關閉中斷使能。如果在異常處理過程中,簡單地打開中斷使能而發生中斷嵌套時,顯然新的異常處理將破壞原來的中斷現場而導致出錯。但有時需要中斷必須是可重入的,因此要通過程序設計來解決這個問題。其中有兩個關鍵問題。

        ① 新中斷使能之前,必須要保護好前一個中斷的現場信息。比如LR_irq和SPSR_irq等,這一點比較容易做的。

        ② 中斷處理過程中對BL進行保護。

        在中斷處理函數中發生函數調用BL是很常見的,假設有下面一種情況。

        IRQ_Handler:

        ……

        BL Foo

        ADD

        其中,

        Foo:

        STMFD SP!,{r0-r3,LR}

        ……

        LDMFD SP!{r0-r3,PC}

        上述程序,在IRQ處理函數IRQ_Handler()中調用了函數Foo()。若是在IRQ_Handler()里面中斷可重入的話,可能發生問題,考察下面的情況:當新的中斷請求恰好在“BL Foo”指令執行完成后發生。這時候LR_irq寄存器(因在IRQ模式下,所以是LR_irq)的值將調整為BL指令的下一條指令(ADD)地址,使其能從Foo()正確返回;但是因為這時候發生了中斷請求,接下來要進行新中斷的響應,處理器在新中斷響應過程中也要進行LR_irq保存。這次對LR_irq的操作發生了沖突,當新中斷返回后,往下執行STMFD指令,這時候壓棧的LR已不是原來的ADD指令地址,從而使子程序Foo()無法正確返回。

        這個問題無法通過增加額外的現場保護指令來解決。一個辦法就是在重新使能中斷之前改變處理器模式,也就是使上面程序的“BL Foo”指令不要運行在IRQ模式下。這樣當新的中斷發生時,就不會造成LR寄存器的沖突。考慮ARM的所有運行模式,采用SYSTEM模式是比較合適的,因為它是特權模式,不是IRQ模式,與中斷響應無關。

        下面的例子顯示了標準的IRQ/FIQ程序。

        PRESERVE8

        AREA INTERRUPT, CODE, READONLY

        IMPORT C_irq_handler

        IRQ

        SUB lr, lr, #4 ;跳轉返回地址

        STMFD sp!, {lr} ;保存返回地址

        MRS r14, SPSR ;讀取SPSR

        STMFD sp!, {r12, r14} ;保存寄存器

        ; 清除中斷源

        MSR CPSR_c, #0x1F ;切換到SYSTEM模式,

        STMFD sp!, {r0-r3, lr} ;保存lr_USR 和其他使用到的寄存器

        BL C_irq_handler ;跳轉到C中斷處理函數

        LDMFD sp!, {r0-r3, lr} ;恢復用戶模式寄存器

        MSR CPSR_c, #0x92 ;切換回irq模式

        LDMFD sp!, {r12, r14}

        MSR SPSR_cf, r14

        LDMFD sp!, {pc}^

        END



        評論


        相關推薦

        技術專區

        關閉
        主站蜘蛛池模板: 万年县| 嵩明县| 河津市| 称多县| 张家川| 彰化县| 石林| 昌黎县| 凉城县| 临潭县| 和田市| 茂名市| 中牟县| 鄂州市| 汶上县| 阳高县| 随州市| 长兴县| 元阳县| 登封市| 财经| 西昌市| 苍南县| 琼结县| 兴化市| 高安市| 鹤庆县| 巍山| 丰镇市| 阜南县| 五华县| 秦安县| 墨江| 托克逊县| 绥化市| 邢台市| 萨嘎县| 嘉禾县| 淮南市| 察哈| 达州市|