<meter id="pryje"><nav id="pryje"><delect id="pryje"></delect></nav></meter>
          <label id="pryje"></label>

          新聞中心

          EEPW首頁 > 嵌入式系統(tǒng) > 設(shè)計應(yīng)用 > ARM1176JZF-S/S3C6410處理器的異常處理過程

          ARM1176JZF-S/S3C6410處理器的異常處理過程

          作者: 時間:2016-11-09 來源:網(wǎng)絡(luò) 收藏
          本來準備總結(jié)一下ARM1176JZF-S/S3C6410處理器異常處理過程,但是發(fā)現(xiàn)《嵌入式系統(tǒng)Linux內(nèi)核開發(fā)實戰(zhàn)指南》一書中的這一部分講解得非常簡明和清楚。所以就不再重復(fù)發(fā)明輪子,不過我會在以下的引用中做一些補充。

          進入異常中斷處理

          本文引用地址:http://www.ex-cimer.com/article/201611/317944.htm

          ARM處理器發(fā)生異常中斷,則ARM處理器進入如下異常中斷自動處理過程(假設(shè)發(fā)生的異常中斷對應(yīng)的模式為mode):

          1. 將當前程序狀態(tài)寄存器CPSR的值保存到SPSR_mode中;
          2. 將CPSR中的模式位設(shè)置成mode模式,將CPSR中的bit7(I)設(shè)置為1,禁止IRQ中斷,如果是FIQ中斷,則再將CPSR中的bit6(F)設(shè)置為1,禁止FIQ中斷;
          3. 將返回地址傳給lr_mode;
          4. 將該異常中斷的向量地址傳給程序計數(shù)器pc,從而進入異常中斷處理程序。

          退出異常中斷處理

          當要從異常中斷處理程序中返回時,要做以下兩步操作(假設(shè)發(fā)生的異常中斷對應(yīng)的模式為mode):

          1. 將保存在SPSR_mode中的值恢復(fù)到當前程序狀態(tài)寄存器CPSR中;
          2. 返回到發(fā)生異常中斷的指令的下一條指令處執(zhí)行,也就是將lr_mode寄存器的值適當?shù)胤祷氐匠绦蛴嫈?shù)器pc中。

          但程序員只需做好上述第二步即可,第一步在完成第二步的同時由處理器自動完成,所以我們下面講解從各種異常中斷處理返回的編程接口。

          退出復(fù)位異常中斷處理(Reset)

          復(fù)位異常中斷處理程序不需要返回,所以不需要這個接口。

          退出未定義指令異常中斷處理(Undefined Instruction)

          未定義指令異常中斷由當前執(zhí)行的指令自身產(chǎn)生,當未定義指令異常中斷產(chǎn)生時,程序計數(shù)器pc的值還未更新,它指向當前指令后面第2條指令(對于ARM指令,它指向當前指令地址加8字節(jié)的位置;對于Thumb指令,它指向當前指令地址加4字節(jié)的位置),當未定義指令異常中斷發(fā)生時,處理器將值(pc-4)保存到lr_und中,此時(pc-4)指向當前指令的下一條指令,所以從未定義指令異常中斷返回可以通過如下指令來實現(xiàn):

          mov pc, lr

          該指令將寄存器lr_mode中的值到程序計數(shù)器pc中,實現(xiàn)程序返回,同時將SPSR_mode寄存器中的值到當前程序狀態(tài)寄存器CPSR中。

          如果要在異常中斷處理中使用數(shù)據(jù)棧,那么可以在進入異常中斷處理程序時保存被中斷程序的執(zhí)行現(xiàn)場,在退出異常中斷處理程序時恢復(fù)被中斷程序的執(zhí)行現(xiàn)場,編程如下:

          stmfd sp!, {register_list, lr} ;保存被中斷程序的執(zhí)行現(xiàn)場
          ; . . .
          ldmfd sp!, {register_list, pc}^ ;恢復(fù)被中斷程序的執(zhí)行現(xiàn)場

          上面的register_list,是異常中斷處理程序中使用的寄存器列表,標識符^表示要將SPSR_mode寄存器中的值到當前程序狀態(tài)寄存器CPSR中。

          退出軟中斷指令(SWI)異常中斷處理(Undefined Instruction)

          SWI異常中斷和未定義異常中斷指令一樣,也是由當前執(zhí)行的指令自身產(chǎn)生,當SWI指令執(zhí)行時,pc的值還未更新,它指向當前指令后面第2條指令(對于ARM指令,它指向當前指令地址加8字節(jié)的位置;對于Thumb指令,它指向當前指令地址加4字節(jié)的位置),當未定義指令異常中斷發(fā)生時,處理器將值(pc-4)保存到lr_svc中,此時(pc-4)指向當前指令的下一條指令,所以從SWI異常中斷處理返回的實現(xiàn)方法與從未定義指令異常中斷處理返回一樣:

          mov pc, lr

          使用數(shù)據(jù)棧的方法與未定義指令異常中斷處理中的方法也一樣:

          stmfd sp!, {register_list, lr} ;保存被中斷程序的執(zhí)行現(xiàn)場
          ; . . .
          ldmfd sp!, {register_list, pc}^ ;恢復(fù)被中斷程序的執(zhí)行現(xiàn)場

          退出指令預(yù)取中止異常中斷處理(Prefetch Abort)

          在指令預(yù)取時,如果目標地址是非法的,該指令被標記成有問題的指令,這時,流水線上該指令之前的指令繼續(xù)執(zhí)行,當執(zhí)行到該被標記成有問題的指令時,處理器產(chǎn)生指令預(yù)取中止異常中斷。發(fā)生指令預(yù)取異常中斷時,程序要返回到該有問題的指令處,重新讀取并執(zhí)行該指令,因此指令預(yù)取中止異常中斷應(yīng)該返回到產(chǎn)生該指令預(yù)取中止異常中斷的指令處,而不是當前指令的下一條指令。

          指令預(yù)取中止異常中斷由當前執(zhí)行的指令自身產(chǎn)生,當指令預(yù)取中止異常中斷發(fā)生時,程序計數(shù)器pc的值還未更新,它指向當前指令后面第2條指令(對于ARM指令,它指向當前指令地址加8字節(jié)的位置;對于Thumb指令,它指向當前指令地址加4字節(jié)的位置)。此時處理器將值(pc-4)保存到lr_abt中,它指向當前指令的下一條指令,所以返回操作可以通過下面指令實現(xiàn):

          subs pc, lr, #4

          該指令將lr中的值減4后傳給程序計數(shù)器pc中,實現(xiàn)程序返回,同時將SPSR_abt寄存器的內(nèi)容到當前程序狀態(tài)寄存器CPSR中。

          如果要在指令預(yù)取中止異常中斷處理中使用數(shù)據(jù)棧,可以用以下方法保護、恢復(fù)被中斷程序的執(zhí)行現(xiàn)場:

          subs lr, lr, #4
          stmfd sp!, {register_list, lr} ;保存被中斷程序的執(zhí)行現(xiàn)場
          ; . . .
          ldmfd sp!, {register_list, pc}^ ;恢復(fù)被中斷程序的執(zhí)行現(xiàn)場

          上面的register_list是異常中斷處理程序中使用的寄存器列表,標識符^表示要將SPSR_abt寄存器中的值到當前程序狀態(tài)寄存器CPSR中。

          退出數(shù)據(jù)訪問中止異常中斷處理(Data Abort)

          發(fā)生數(shù)據(jù)訪問異常中斷時,程序要返回到該有問題的指令處,重新訪問該數(shù)據(jù),因此數(shù)據(jù)訪問異常中斷應(yīng)該返回到產(chǎn)生該數(shù)據(jù)訪問中止異常中斷的指令處,而不是當前指令的下一條指令。

          數(shù)據(jù)訪問異常中斷由當前執(zhí)行的指令自身產(chǎn)生,當數(shù)據(jù)訪問異常中斷發(fā)生時,程序計數(shù)器pc的值已經(jīng)更新,它指向當前指令后面第3條指令(對于ARM指令,它指向當前指令地址加12字節(jié)的位置;對于Thumb指令,它指向當前指令地址加6字節(jié)的位置)。此時處理器將值(pc-4)保存到lr_abt中,它指向當前指令后面第2條指令,所以返回操作可以通過下面指令實現(xiàn):

          subs pc, lr, #8

          該指令將lr中的值減8后傳給程序計數(shù)器pc中,實現(xiàn)程序返回,同時將SPSR_abt寄存器內(nèi)容到當前程序狀態(tài)寄存器CPSR中;

          如果要在數(shù)據(jù)訪問異常中斷處理中使用數(shù)據(jù)棧,可以用以下方法保護、恢復(fù)被中斷程序的執(zhí)行現(xiàn)場:

          subs lr, lr, #8
          stmfd sp!, {register_list, lr} ;保存被中斷程序的執(zhí)行現(xiàn)場;
          ; . . .
          ldmfd sp!, {register_list, pc}^ ;恢復(fù)被中斷程序的執(zhí)行現(xiàn)場;

          上面的register_list是異常中斷處理程序中使用的寄存器列表,標識符^表示要將SPSR_abt寄存器中的值到當前程序狀態(tài)寄存器CPSR中。

          退出IRQ異常中斷處理程序(IRQ)

          通常處理器執(zhí)行完當前指令后,查詢IRQ中斷引腳,并查看是否允許IRQ中斷,如果某個中斷引腳有效,并且系統(tǒng)允許該中斷產(chǎn)生,處理器將產(chǎn)生IRQ異常中斷,當IRQ異常中斷產(chǎn)生時,程序計數(shù)器pc的值已經(jīng)更新,它指向當前指令后面第3條指令(對于ARM指令,它指向當前指令地址加12字節(jié)的位置;對于Thumb指令,它指向當前指令地址加6字節(jié)的位置),當IRQ異常中斷產(chǎn)生時,處理器將值(pc-4)保存到IRQ異常模式下的寄存器lr_irq中,它指向當前指令之后的第2條指令,因此返回操作可以通過下面指令實現(xiàn):

          subs pc, lr, #4

          該指令將lr中的值減4后傳給程序計數(shù)器pc中,實現(xiàn)程序返回,同時將SPSR_irq寄存器的內(nèi)容到當前程序狀態(tài)寄存器CPSR中。

          如果要在IRQ異常中斷處理中使用數(shù)據(jù)棧,可以用以下方法保護、恢復(fù)被中斷程序的執(zhí)行現(xiàn)場:

          subs lr, lr, #4
          stmfd sp!, {register_list, lr} ;保存被中斷程序的執(zhí)行現(xiàn)場
          ; . . .
          ldmfd sp!, {register_list, pc}^ ;恢復(fù)被中斷程序的執(zhí)行現(xiàn)場

          上面的register_list是異常中斷處理程序中使用的寄存器列表,標識符^表示要將SPSR_irq寄存器中的值到當前程序狀態(tài)寄存器CPSR中。

          退出FIQ異常中斷處理程序(FIQ)

          與IRQ異常中斷一樣,處理器執(zhí)行完當前指令后,查詢FIQ中斷引腳,并查看是否允許FIQ中斷,如果中斷引腳有效,并且系統(tǒng)允許該中斷產(chǎn)生,處理器將產(chǎn)生FIQ異常中斷,當FIQ異常中斷產(chǎn)生時,程序計數(shù)器pc的值已經(jīng)更新,它指向當前指令后面第3條指令(對于ARM指令,它指向當前指令地址加12字節(jié)的位置;對于Thumb指令,它指向當前指令地址加6字節(jié)的位置),當FIQ異常中斷產(chǎn)生時,處理器將值(pc-4)保存到IRQ異常模式下的寄存器lr_fiq中,它指向當前指令之后的第2條指令,因此返回操作可以通過下面指令實現(xiàn):

          subs pc, lr, #4

          該指令將lr中的值減4后傳給程序計數(shù)器pc中,實現(xiàn)程序返回,同時將SPSR_fiq寄存器的內(nèi)容到當前程序狀態(tài)寄存器CPSR中。

          如果要在FIQ異常中斷處理中使用數(shù)據(jù)棧,可以用以下方法保護、恢復(fù)被中斷程序的執(zhí)行現(xiàn)場:

          subs lr, lr, #4
          stmfd sp!, {register_list, lr} ;保存被中斷程序的執(zhí)行現(xiàn)場
          ; . . .
          ldmfd sp!, {register_list, pc}^ ;恢復(fù)被中斷程序的執(zhí)行現(xiàn)場

          上面的register_list是異常中斷處理程序中使用的寄存器列表,標識符^表示要將SPSR_fiq寄存器中的值到當前程序狀態(tài)寄存器CPSR中。

          補充:關(guān)于程序返回地址(PC)的取值

          上文中提到,在進入異常處理之后,CPU會自動根據(jù)pc的值來設(shè)置lr的值(一般是減4),而對于不同各類的異常來說,這個值還不能直接用做異常的返回地址,可能還需要再減4或減8等等,這樣做的原因是什么呢?

          答案在于ARM處理器在處理指令時所使用的三級流水線機制。

          CPU執(zhí)行一條指令的過程可以分為三個步驟:取指令、翻譯和執(zhí)行。執(zhí)行每一個步驟都需要一個指令周期的時間,所以完整地執(zhí)行完一條指令實際上就需要3個周期。為了加快程序的運行,現(xiàn)代CPU都會采用多級流程線的技術(shù)。以三級流水線為例,一條專門負責(zé)取指,一條專門翻譯,還有一條負責(zé)執(zhí)行,三條流水線并行工作,每一條流水線在每一個周期內(nèi)都不會空閑,所以平均來看,執(zhí)行每條指令都只要一個周期的時間。

          從二進制指令的角度來看,當前指令在執(zhí)行的時候,下一條指令已經(jīng)在被翻譯,再下一條指令已經(jīng)正在被讀取。注意pc寄存器總是指向正在被讀取的那條指令,而不是正在被執(zhí)行的指令。如下圖所示:

          箭頭方向是指令運行的方向,左側(cè)是低地址,右側(cè)是高地址,當A指令是正在運行的指令,pc寄存器現(xiàn)在正指向C指令的位置。

          下面,分別以軟中斷異常和數(shù)據(jù)異常為例來解釋一下上文中所講的內(nèi)容:

          在軟中斷發(fā)生時,指令流水線的結(jié)構(gòu)與上圖完全一樣。軟中斷是由正在執(zhí)行的指令A(yù)觸發(fā)的,它的任務(wù)已經(jīng)完成,所以在中斷處理結(jié)束之后,A指令不需要再被執(zhí)行一次,應(yīng)該直接執(zhí)行B指令。而在進入中斷處理程序之前,CPU已經(jīng)自動將(pc-4)的值存入lr,這正是B指定的位置。所以在中斷返回時,直接把lr的值賦給pc就行了。

          在數(shù)據(jù)訪問異常發(fā)生時,指令流水線的結(jié)構(gòu)與上圖不太一樣,正在執(zhí)行的指令仍然是A,pc已經(jīng)更新,即指向了D指令。在中斷處理結(jié)束時,數(shù)據(jù)的問題已經(jīng)解決(可以訪問),A指令還需要再重新執(zhí)行一次,所以pc需要指向A指令處。而在進入中斷處理程序之前,CPU已經(jīng)自動將(pc-4)的值存入lr,這是C指令的位置,所以我們需要手動調(diào)整pc的位置,把它再減8,這才是A指令的位置。



          評論


          技術(shù)專區(qū)

          關(guān)閉
          看屁屁www成人影院,亚洲人妻成人图片,亚洲精品成人午夜在线,日韩在线 欧美成人 (function(){ var bp = document.createElement('script'); var curProtocol = window.location.protocol.split(':')[0]; if (curProtocol === 'https') { bp.src = 'https://zz.bdstatic.com/linksubmit/push.js'; } else { bp.src = 'http://push.zhanzhang.baidu.com/push.js'; } var s = document.getElementsByTagName("script")[0]; s.parentNode.insertBefore(bp, s); })();