新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > ARM的異常處理過程分析

        ARM的異常處理過程分析

        作者: 時間:2016-12-01 來源:網絡 收藏
        2.接下來就是異常處理函數對應的操作,可以在進入異常處理之前就進行返回地址的調整,這樣后面就不用進行處理啦,當然也可以在返回過程中再調整。一般都是在這個過程中進行調整。進行壓棧操作,保存對應的環境變量。調用實際的處理過程等。
        3.出棧,恢復CPU的狀態和寄存器的值。由于第一步中已經調整好返回地址,這一步不需要再次調整。當然如果之前沒有調整,這里則需要進行相應的調整。
        在uC/OS-II的官網移植中采用通用異常處理函數的方式實現異常的處理,下面我們來分析其中的部分代碼:
        首先是處理器部分的移植,包括異常向量、異常的ID號,存儲異常處理函數地址的地址等:
        /*ARM的異常ID號,支持7種類型的異常,每一種異常都存在一個ID號*/
        #defineOS_CPU_ARM_EXCEPT_RESET 0x00
        #defineOS_CPU_ARM_EXCEPT_UNDEF_INSTR 0x01
        #defineOS_CPU_ARM_EXCEPT_SWI 0x02
        #defineOS_CPU_ARM_EXCEPT_PREFETCH_ABORT 0x03
        #defineOS_CPU_ARM_EXCEPT_DATA_ABORT 0x04
        #defineOS_CPU_ARM_EXCEPT_ADDR_ABORT 0x05
        #defineOS_CPU_ARM_EXCEPT_IRQ 0x06
        #defineOS_CPU_ARM_EXCEPT_FIQ 0x07
        #defineOS_CPU_ARM_EXCEPT_NBR 0x08
        /*異常向量地址*/
        #defineOS_CPU_ARM_EXCEPT_RESET_VECT_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04 + 0x00) //0x00
        #defineOS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04 + 0x00) //0x04
        #defineOS_CPU_ARM_EXCEPT_SWI_VECT_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04 + 0x00) //0x08
        #defineOS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04 + 0x00) //0x0c
        #defineOS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04 + 0x00) //0x10
        /*這個異常是ARM中不支持的異常*/
        #defineOS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04 + 0x00) //0x14
        #defineOS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04 + 0x00) //0x18
        #defineOS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04 + 0x00) //0x1c
        /*存儲異常處理函數地址的地址*/
        /* ARM exception handlers addresses */
        #defineOS_CPU_ARM_EXCEPT_RESET_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_RESET * 0x04 + 0x20) //0x20
        #defineOS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_UNDEF_INSTR * 0x04 + 0x20) //0x24
        #defineOS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_SWI * 0x04 + 0x20) //0x28
        #defineOS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR(OS_CPU_ARM_EXCEPT_PREFETCH_ABORT * 0x04 + 0x20) //0x2c
        #defineOS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_DATA_ABORT * 0x04 + 0x20) //0x30
        #defineOS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_ADDR_ABORT * 0x04 + 0x20) //0x34
        #defineOS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_IRQ * 0x04 + 0x20) //0x38
        #defineOS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR (OS_CPU_ARM_EXCEPT_FIQ * 0x04 + 0x20) //0x3c
        /*存儲在異常向量中的內容,實質上是LDR PC,[PC,#0x18]的機器碼*/

        #define OS_CPU_ARM_INSTR_JUMP_TO_SELF 0xEAFFFFFE
        /* ARM "Jump To Exception Handler"asminstruction */
        #define OS_CPU_ARM_INSTR_JUMP_TO_HANDLER 0xE59FF018
        異常的初始化函數,首先,完成了在異常向量中存儲指令的操作,采用機器碼的形式就能避免直接訪問寄存器什么的,其次,完成在固定的地址處存放對應異常處理函數的地址。其中采用了賦值的形式也是需要注意的,采用的強制類型轉換和指針相結合的形式。保證了是修改地址處的內容。而不是修改地址。
        /*初始化異常中斷向量*/
        voidOS_CPU_InitExceptVect (void)
        {
        /*
        OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR是對應中斷向量表的地址
        OS_CPU_ARM_INSTR_JUMP_TO_HANDLER是保存了對應的OS_CPU_ARM_INSTR_JUMP_TO_HANDLER(實質上是一個指令)
        實質上就是在異常向量中存放了:LDR PC [PC, #0x18],也就是讓PC指向對應的異常處理地址中的內容,
        也就是實現到實際處理函數的跳轉。
        異常處理地址中存儲了實際的異常處理函數的地址
        其他的異常也有相同的操作,OS_CPU_ARM_INSTR_JUMP_TO_HANDLER是一個指令的機器碼形式
        */
        (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_UNDEF_INSTR_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptUndefInstrHndlr;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_SWI_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptSwiHndlr;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_PREFETCH_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptPrefetchAbortHndlr;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_DATA_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptDataAbortHndlr;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_ADDR_ABORT_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptAddrAbortHndlr;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_IRQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptIrqHndlr;
        /*在異常向量中存儲對應的操作,實質上就是將PC值調轉*/
        (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_VECT_ADDR) = OS_CPU_ARM_INSTR_JUMP_TO_HANDLER;
        (*(INT32U *)OS_CPU_ARM_EXCEPT_FIQ_HANDLER_ADDR) = (INT32U)OS_CPU_ARM_ExceptFiqHndlr;

        評論


        技術專區

        關閉
        主站蜘蛛池模板: 叶城县| 买车| 平乐县| 龙岩市| 新民市| 多伦县| 昭觉县| 南丰县| 景东| 阿拉尔市| 青阳县| 淮滨县| 聊城市| 上饶县| 鄂伦春自治旗| 大城县| 依兰县| 庐江县| 原平市| 兰州市| 泸溪县| 克什克腾旗| 天津市| 尼玛县| 云阳县| 来安县| 个旧市| 黄浦区| 盐边县| 福海县| 石狮市| 德钦县| 容城县| 周口市| 泸州市| 平塘县| 壤塘县| 泾阳县| 黑水县| 蓝山县| 武陟县|