新聞中心

        EEPW首頁 > 嵌入式系統 > 設計應用 > arm處理器異常處理swi

        arm處理器異常處理swi

        作者: 時間:2016-11-09 來源:網絡 收藏
        ARM處理器共有7中運行模式:

        用戶模式(usr) -- 正常程序執行模式

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

        |-- |-- 快速中斷模式(fiq) -- 用于高速數據傳輸和通道處理

        特 | 異 | 外部中斷模式(irq) -- 用于通常的中斷處理
        權 --| 常 --| 管理員模式(svc) -- 供操作系統使用的一種保護模式
        模 | 模 | 數據訪問中止模式(abt) -- 用于虛擬存儲及存儲保護
        式 | 式 |-- 未定義指令中止模式(und) -- 用于支持通過軟件仿真硬件的協處理器
        |-- 系統模式(sys) -- 用于運行特權級的操作系統任務

        特權模式:fiq、irq、svc、abt、und、sys -- 程序可以訪問所有的系統資源,也可以任意切換處理器模式
        異常模式:fiq、irq、svc、abt、und

        ARM異常中斷種類及優先級:
        優先級 異常中斷名稱
        高 復位(reset)
        || 數據訪問中止(data abort)
        || 快速中斷請求(FIQ)
        || 外部中斷請求(IRQ)
        /||/ 指令預取中止(prefetch abort)
        // 軟中斷(SWI)
        低 未定義指令(undefined instruction)

        異常向量表:
        地址 異常中斷名稱 優先級
        . .
        . .
        . .
        0x1c FIQ 3
        0x18 IRQ 4
        0x14 Reserved X
        0x10 Data Abort 2
        0x0c Prefetch Abort 4
        0x08 SWI 5
        0x04 Undefined Instruction 6
        0x00 Reset 1
        Vector Table可以位于0x0或者0xFFFF0000處(ARM720T、ARM9、ARM10..)
        優先級為3的FIQ為什么放在地址0x1c處呢?當初這么設計應該是為了更加快速地響應FIQ中斷,也就是說不在0x1c地
        址放跳轉指令,而是直接存放最關鍵的FIQ處理代碼在0x1c開始一段地址區域內。

        異常進入及返回:
        當異常產生時:
        1. 拷貝當前模式的CPSR值到相應異常模式的SPSR_,如:CPSR(usr) --> SPSR_svc(svc)。
        2. 設置適當的CPSR位:
        改變處理器狀態進入ARM狀態
        改變處理器模式進入相應的異常模式
        如果需要可以設置中斷禁止位禁止相應中斷
        3. 保存返回地址(pc-4)到LR_
        4. 設置pc為相應的異常向量。
        異常返回時,需要:
        1. 從SPSR_恢復CPSR。
        2. 從LR_恢復pc
        (只能在ARM狀態下實現該返回操作)
        異常返回的指令分析:
        * 使用一數據處理指令實現,該指令帶“S”后綴,同時pc作為目的寄存器
        * 在特權模式下不僅僅要更新pc,而且還要拷貝SPSR到CPSR
        1. 從SWI和Undef異常返回:
        movs pc , lr
        這兩種異常都會在導致異常的指令執行周期中就進入異常,沒有等到下個時鐘周期才進入異常,另外這兩種異常都是返回到產生異常指令的下一條指令去繼續執行。我從前面可以知道lr中保存的就是pc-4(該pc值是產生異常指令的下下一條指令的地址),所以可以直接將lr的值送入pc。
        2. 從FIQ、IRQ和Prefect Abort返回:
        subs pc , lr , #4
        這三種異常都會等待產生異常的指令執行完才會進入異常,所以此刻的pc已經更新,比如:
        ...
        subs r3, r3, #1 << 26 @ 0x100
        bcs 2b @ 0x104
        subs r1, r1, #1 << 5 @ 0x108
        bcs 1b @ 0x10b
        ...
        如果在執行第1行地址為0x100指令時,發生了上面三種異常,此刻的pc值為0x108,等第1行執行完之后,pc更新為0x10b。同時進入異常處理,在異常進入時將lr值保存為pc-4,即0x108。那么在異常返回后,需要接著執行發生異常指令的下一條指令的話就必須將lr的值減去4才能得到正確的地址,lr-4 = 0x108 - 4 = 0x104。
        3. 從數據異常(Data Abort)異常返回:
        該異常也是會等待產生異常的那條指令執行完才會進入異常,情況類似于第2類的三種異常,但是有一點不同的是:數據異常返回地址不是產生異常的下一條指令,而是產生異常的那條指令,所以,它的返回指令應該是:
        subs pc , lr , #8
        按照上面的例子就應該返回到地址0x100處繼續執行。為什么會這樣,因為數據異常返回后會繼續去取數據,想想缺頁異常。
        4. 如果lr在進入異常后被壓棧的話,就需要使用下面的指令來彈出。
        LDMFD sp! , {pc}^
        (^同時拷貝SPSR到CPSR中,這里的lr在壓棧之前已經做了前面3中情況對應的處理了)

        SWI異常:
        執行SWI軟中斷指令即可產生軟中斷異常,進入SWI異常時會做如下動作:
        CSPR保存到SPSR_svc。
        改變處理器狀態進入ARM狀態
        改變處理器模式進入相應的管理員模式(svc)
        看需要禁止中斷
        保存返回地址(pc-4)到LR_svc
        設置pc為0x08或者0xFFFF0008
        需要注意一點的是:如果在執行SWI指令時系統正處于svc模式時,那么將會覆蓋掉原來LR_svc的值。所以
        在SWI指令之前應該對LR_svc壓棧保存。
        SWI異常返回時,做如下動作:
        從SPSR_svc恢復CPSR
        從LR_svc恢復pc,不需要修正

        在c語言中使用關鍵字“__swi”來定義一個軟中斷函數:
        __swi(0x30) void my_swi(void);
        void fun(void)
        {
        my_swi();
        }
        -----> 轉換成匯編
        fun
        STMFD sp! , {lr}
        swi 0x24
        LDMFD sp! , {pc}

        swi調用帶參和swi處理函數帶參:
        swi調用帶參:
        使用swi指令時,通常有兩種方法來傳遞參數:
        1. 使用swi號
        swi指令的低24bits(ARM指令集)組成或者低8bits(Thumb指令集)來指定軟中斷號,
        其余參數通過寄存器來傳遞。
        2. r0決定軟中斷號,其余參數使用同樣寄存器傳遞。
        c語言中,關鍵字“__swi”定義的軟中斷函數允許最多4個參數,使用r0~r4來傳遞。
        swi處理函數帶參:
        1. 匯編中,存取調用者設置的寄存器即可
        2. 傳參給c,通常才用壓棧的方法:
        將參數壓棧,給調用的函數傳遞一個指向這些參數的指針。

        獲取SWI號:
        ARM core不提供直接傳遞軟中斷號到處理程序的機制,SWI處理程序必須定位SWI指令并提取SWI指令中的常數域
        1. 檢查SPSR_svc的Tbit,可以確定陷入swi異常之前的指令時ARM指令集還是Thumb指令集。
        2. 然后通過LR_svc的值確定SWI指令的地址。ARM狀態下是LR-4,而Thumb狀態下是LR-2的位置。
        3. SWI指令格式:
        ARM態:
        31 30 29 28 27 26 25 24 23 22 21 20 19 18 17 16 15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
        | Cond |1 1 1 1 | SWI number |
        Thumb態
        15 14 13 12 11 10 9 8 7 6 5 4 3 2 1 0
        | 1 1 0 1 1 1 1 1| SWI number |



        評論


        技術專區

        關閉
        主站蜘蛛池模板: 双辽市| 茌平县| 镇原县| 连城县| 响水县| 西吉县| 调兵山市| 怀化市| 青河县| 廊坊市| 旌德县| 武鸣县| 云和县| 青冈县| 诏安县| 南乐县| 阿城市| 萍乡市| 陵川县| 东丽区| 武威市| 内乡县| 秦皇岛市| 宁蒗| 兖州市| 闽侯县| 余庆县| 海城市| 丰都县| 河曲县| 崇仁县| 凤翔县| 界首市| 汨罗市| 达尔| 精河县| 衡水市| 石家庄市| 安图县| 辽宁省| 呼和浩特市|