<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>

新聞中心

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

ARM1176JZF-S/S3C6410處理器的異常處理過(guò)程

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

進(jìn)入異常中斷處理

本文引用地址:http://dyxdggzs.com/article/201611/317944.htm

ARM處理器發(fā)生異常中斷,則ARM處理器進(jìn)入如下異常中斷自動(dòng)處理過(guò)程(假設發(fā)生的異常中斷對應的模式為mode):

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

退出異常中斷處理

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

  1. 將保存在SPSR_mode中的值恢復到當前程序狀態(tài)寄存器CPSR中;
  2. 返回到發(fā)生異常中斷的指令的下一條指令處執行,也就是將lr_mode寄存器的值適當地返回到程序計數器pc中。

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

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

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

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

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

mov pc, lr

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

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

stmfd sp!, {register_list, lr} ;保存被中斷程序的執行現場(chǎng)
; . . .
ldmfd sp!, {register_list, pc}^ ;恢復被中斷程序的執行現場(chǎng)

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

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

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

mov pc, lr

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

stmfd sp!, {register_list, lr} ;保存被中斷程序的執行現場(chǎng)
; . . .
ldmfd sp!, {register_list, pc}^ ;恢復被中斷程序的執行現場(chǎng)

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

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

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

subs pc, lr, #4

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

如果要在指令預取中止異常中斷處理中使用數據棧,可以用以下方法保護、恢復被中斷程序的執行現場(chǎng):

subs lr, lr, #4
stmfd sp!, {register_list, lr} ;保存被中斷程序的執行現場(chǎng)
; . . .
ldmfd sp!, {register_list, pc}^ ;恢復被中斷程序的執行現場(chǎng)

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

退出數據訪(fǎng)問(wèn)中止異常中斷處理(Data Abort)

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

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

subs pc, lr, #8

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

如果要在數據訪(fǎng)問(wèn)異常中斷處理中使用數據棧,可以用以下方法保護、恢復被中斷程序的執行現場(chǎng):

subs lr, lr, #8
stmfd sp!, {register_list, lr} ;保存被中斷程序的執行現場(chǎng);
; . . .
ldmfd sp!, {register_list, pc}^ ;恢復被中斷程序的執行現場(chǎng);

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

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

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

subs pc, lr, #4

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

如果要在IRQ異常中斷處理中使用數據棧,可以用以下方法保護、恢復被中斷程序的執行現場(chǎng):

subs lr, lr, #4
stmfd sp!, {register_list, lr} ;保存被中斷程序的執行現場(chǎng)
; . . .
ldmfd sp!, {register_list, pc}^ ;恢復被中斷程序的執行現場(chǎng)

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

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

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

subs pc, lr, #4

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

如果要在FIQ異常中斷處理中使用數據棧,可以用以下方法保護、恢復被中斷程序的執行現場(chǎng):

subs lr, lr, #4
stmfd sp!, {register_list, lr} ;保存被中斷程序的執行現場(chǎng)
; . . .
ldmfd sp!, {register_list, pc}^ ;恢復被中斷程序的執行現場(chǎng)

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

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

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

答案在于A(yíng)RM處理器在處理指令時(shí)所使用的三級流水線(xiàn)機制。

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

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

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

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

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

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



評論


技術(shù)專(zhuān)區

關(guān)閉
国产精品自在自线亚洲|国产精品无圣光一区二区|国产日产欧洲无码视频|久久久一本精品99久久K精品66|欧美人与动牲交片免费播放
<dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><small id="yhprb"></small><dfn id="yhprb"></dfn><small id="yhprb"><delect id="yhprb"></delect></small><small id="yhprb"></small><small id="yhprb"></small> <delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"></dfn><dfn id="yhprb"></dfn><s id="yhprb"><noframes id="yhprb"><small id="yhprb"><dfn id="yhprb"></dfn></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><small id="yhprb"></small><dfn id="yhprb"><delect id="yhprb"></delect></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn> <small id="yhprb"></small><delect id="yhprb"><strike id="yhprb"></strike></delect><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn><dfn id="yhprb"><s id="yhprb"><strike id="yhprb"></strike></s></dfn><dfn id="yhprb"><s id="yhprb"></s></dfn>