1. 程式人生 > >ARM中斷異常處理的返回的問題

ARM中斷異常處理的返回的問題

    http://blog.chinaunix.net/uid-26215986-id-3333236.html
 http://blog.csdn.net/qianlong4526888/article/details/8598524
因為ARM指令是三級流水線就是說取指,譯指,執行時同時執行的 ,這樣說吧,現在PC指向的是正在取指的地址,那麼cpu正在譯指的指令地址是PC-4(假設在ARM狀態下,一個指令佔4個位元組),cpu正在執行的指令地址是PC-8.也就是說PC所指向的地址和現在所執行的指令地址相差8,儘管以後版本的指令流水線擴充套件為5級和8級,但是這一特性一直被相容處理,也即pc(excute)=pc(fetch) - 8,其中:pc(excute)是當前正在執行的指令,就是之前取該指令時候的PC的值;pc(execute):當前指令執行的,計算中如果用到pc,是指此時pc的值

。當突然發生中斷的時候,儲存的是PC的地址。
(1)對於子程式的呼叫

如下面是一段S3C2440 ARM彙編程式碼:

地址

指令

0x30000008

BL zFun

0x3000000C

MOV r0,#04

0x30000010

MOV r1,#08

0x30000014

MOV r0,#02

AREA Reset,CODE,READONLY
    ENTRY
    Start
         MOV r0,#08
         MOV r1,#08
         BL zFun
         MOV r0,#04
         MOV r1,#08
    zFun
         MOV r0,#02


         END

當0x30000008處的BL指令執行時,會把PC(=0x30000010)儲存到LR暫存器裡面,也就是LR=0x30000010。接下來處理器會立即對LR進行一個自動的更新動作:LR=LR-0x4,這樣,LR裡面的地址為0x30000010 – 0x4 = 0x3000000C,它是指令”MOV r0,#04”的地址,所以當從子程式zFun返回時,LR裡面正好是正確的返回地址。既是下一條要執行的指令的地址。
(2)中斷異常處理函式呼叫

異常就是正在執行的指令,由於各種軟體或硬體故障被打斷,比如,在讀資料或指令時,訪問儲存器失敗、產生了一個外部硬體中斷等。當這些情況發生時,在ARM系統裡,由異常和中斷處理程式做出相應的處理,當處理完成後,要返回到被中止的指令,使被中止的指令能夠繼續正常執行下去。因此,確定異常和中斷處理程式的返回地址是一個非常重要的問題。

1、中斷處理

當外部中斷IRQ和FIQ(Fast Interrpt Request,快速中斷請求)發生時,ARM核完成一部分工作。當然,這些工作是任何異常發生時都必須要做的,所以ARM處理器就會自動帶我們完成。 其它重要的工作,必須由程式設計師來完成。ARM處理器處理的事包括從使用者模式切換到IRQ模式、狀態暫存器值的變化及跳轉。比如說,處理器自動跳轉到從0x0地址開始的異常中斷向量表的0x18處,在向量表的0x18處,最簡單的指令為”B HandlerIRQ”。

那程式設計師所要關心的就是實現具體的異常處理程式(HandlerIRQ)。當用ARM組合語言實現HandlerIRQ函式的時候,如何確定HandlerIRQ函式正確地返回地址,使被中止的指令能夠繼續正常執行下去。

比較常用的中斷處理程式結構如下:

HandlerIRQ ;中斷響應,從向量表直接跳來

SUB r14,r14,#4 ;計算返回地址

STMFD r13,{r0-r3,r14} ;保護現場,一般只需要保護{r0-r3,lr}

BL irqHandler ;跳到具體的異常處理函式

LDMFD r13,{r0-r3,pc}^ ;恢復現場

通過”SUB R14,R14,#4”計算中斷函式的返回地址。為什麼計算返回地址的時候要減去4呢?

地址

指令

0x30000000

BL zFun

0x30000004

MOV r0,#0

0x30000008

MOV r1,#1

0x3000000C

MOV r2,#2

我們看上個表,比如在執行地址為0x30000004的move指令時,突然來了一個IRQ中斷,這個中斷打斷了move指令的執行,這個時候就要去跳轉到異常處理函式,之後還要返回0x30000004地址重新執行move指令。當中斷髮生時,LR裡面儲存了使用者模式下PC的值,那麼當執行地址為0x30000004的move指令時,PC的值應該是0x3000000C,前面介紹過,當發生跳轉時,處理器會對LR進行一個自動的更新動作:LR=LR-0x4,這樣LR裡面的地址是0x3000000C-0x04=0x30000008。但是0x30000008並不是我們要的地址,因為中斷髮生在地址為0x30000004的move指令執行的時候,所以中斷處理完後應該返回這個地址。 這就是在計算返回地址的時候LR減去4的原因。對於FIQ中斷和預取指中止異常,計算返回地址方法和IRQ相同。