ARM 異常處理過程,指令[ swi ]


 

1.  發生異常:

  程序正常執行,突然被一個不正常的事件打斷正在執行的程序,執行相應的異常事件對應的程序

2.  5 種異常模式對應着 7 種異常源:

          異常工作模式           異常源
          FIR                      FIR

          IRQ                     IRQ

            Abort           data_abort / pref_abort

           Undef                     undefine

          SVC                                    reset復位 / swi軟中斷指令

 

3. 同種異常源不可以被打斷,reset 優先級最高,打斷任何程序執行

 

4. 異常處理過程:

  

    保護現場:由 CPU 自動完成,通過 4 步完成 ; 通用寄存器CPSR 中的狀態,改變CPU狀態

    (1)CPU 保存現場當前狀態 CPSR 到異常模式下的 SPSR 中 ,這步的目的是保護當前狀態的CPSR(每種異常模式都對應一個自己的SPSR,以便將來在異常返回時,從SPSR恢復至CPSR)

    (2)CPU 修改 CPSR 中 模式位,禁止相應中斷源,切換 CPU 狀態為ARM 狀態(Thumb態和ARM態由CPSR的T位來決定)

      (3)保存的返回地址到對應異常模式下的LR 寄存器中。(返回地址:異常發生前正在執行指令的下一條地址)

      (4)pc 指向異常向量表中對應的異常

      恢復現場: 需要自己手動完成(手動修改寄存器 CPSR 中對應的狀態位)

     (1) 把異常模式下的 SPSR_MODE 恢復到CPSR中

      (2)把 異常模式下的 LR_MODE 恢復到 PC中

 

 

5. 異常向量表
  1)異常向量表就是內存的一塊空間,這塊內存的空間的大小為32byte,平均分成了8份,每份4個byte,然后在里邊存放7中異常源,多余的一份保留不用
  2) 在異常量表中存放的一條跳轉指令
  3) 7種異常源在異常向量表中的位置固定,不可以隨意更改。

示例: 手動修改到user模式,然后使用 swi 軟中斷切換到 SVC 異常模式

 

.text
.global _start
_start:
    b reset_handler
    b undef_handler
    b swi_handler
    b pref_abort_handler
    b data_abort_handler
    b .
    b irq_handler
    b fiq_handler
    
reset_handler:           @ 復位開始為 SVC 模式
    ldr sp, =0x40000200  @ 初始化棧
    mrs r0, cpsr           @ 讀取程序狀態寄存器
    mov r1, #0x1F
    mvn r1, r1
    and r0, r0, r1
    mov r1, #0x10
    orr r0, r0, r1       @ 修改 讀取 的CPSR 中的數據, 然后再重新寫入CPSR 寄存器
    msr cpsr, r0         @ 保存狀態寄存器 此時改為 user 模式
    ldr sp, =0x40000100  @ 初始化此狀態下的 sp 指針
    swi #1                  @ 使用指令 swi 產生異常,異常號為 1
    mov r0, #1
    mov r1, #2
    swi #2                 @ 使用指令 swi 產生異常,異常號為 2
    mov r0, #1
    mov r1, #2
loop:
    b loop

undef_handler:
swi_handler:     @ 切換模式后, 先進行現場保護, cpsr和lr值保存,修改cpsr切換模式
.if 0
    stmfd sp!, {r0-r10, lr}  @ 入棧  拷貝過來的lr 值, lr內容沒有改變
    mov r0, #1
    mov r1, #2
    ldmfd sp!, {r0-r10, r12} @ 出棧
    mrs r11, spsr
    msr cpsr, r11
    mov pc, r12    @ 恢復現場
.else
    stmfd sp!, {r0-r12, lr}
    mov r0, #1
    mov r1, #2

    mov r0, lr   
    sub r0, r0, #4       @ 獲取 lr 上一條指令(也就是swi)的地址
    ldr r1, [r0]         @ 提取 swi 指令對應的機器碼
    ldr r2, =0xFFFFFF     @ 提取后24位 對應的 num號
    and r0, r1, r2          @根據r0判斷具體是哪個地方的swi
    
    ldmfd sp!, {r0-r12, pc}^  @ 恢復現場, ^ 表示同時操作兩個步驟
.endif

pref_abort_handler:
data_abort_handler:
irq_handler:
fiq_handler:
    
.end

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM