精品国产人成在线_亚洲高清无码在线观看_国产在线视频国产永久2021_国产AV综合第一页一个的一区免费影院黑人_最近中文字幕MV高清在线视频

0
  • 聊天消息
  • 系統(tǒng)消息
  • 評論與回復(fù)
登錄后你可以
  • 下載海量資料
  • 學(xué)習(xí)在線課程
  • 觀看技術(shù)視頻
  • 寫文章/發(fā)帖/加入社區(qū)
會員中心
創(chuàng)作中心

完善資料讓更多小伙伴認(rèn)識你,還能領(lǐng)取20積分哦,立即完善>

3天內(nèi)不再提示

ARM體系結(jié)構(gòu)中出現(xiàn)異常時(shí)該如何處理

電子設(shè)計(jì) ? 來源:電子設(shè)計(jì) ? 作者:電子設(shè)計(jì) ? 2020-12-24 18:43 ? 次閱讀

一、異常(Exception)

異常是理解CPU運(yùn)轉(zhuǎn)最重要的一個(gè)知識點(diǎn),幾乎每種處理器都支持特定異常處理,中斷是異常中的一種。有時(shí)候我們衡量一個(gè)操作系統(tǒng)的時(shí)候?qū)崟r(shí)性就是看os最短響應(yīng)中斷時(shí)間以及單位時(shí)間內(nèi)響應(yīng)中斷次數(shù)。

二、異常源

ARM體系結(jié)構(gòu)中,存在7種異常處理。當(dāng)異常發(fā)生時(shí),處理器會把PC設(shè)置為一個(gè)特定的存儲器地址。這一地址放在被稱為向量表(vector table)的特定地址范圍內(nèi),向量表的入口是一些跳轉(zhuǎn)指令,跳轉(zhuǎn)到專門處理某個(gè)異常或中斷的子程序。

1. 異常源分類

要進(jìn)入異常模式,一定要有異常源,ARM規(guī)定有7種異常源:

異常源描述Reset上電時(shí)執(zhí)行Undef當(dāng)流水線中的某個(gè)非法指令到達(dá)執(zhí)行狀態(tài)時(shí)執(zhí)行SWI當(dāng)一個(gè)軟中斷指令被執(zhí)行完的時(shí)候執(zhí)行Prefetch當(dāng)一個(gè)指令被從內(nèi)存中預(yù)取時(shí),由于某種原因而失敗,如果它能到達(dá)執(zhí)行狀態(tài)這個(gè)異常才會產(chǎn)生Data如果一個(gè)預(yù)取指令試圖存取一個(gè)非法的內(nèi)存單元,這時(shí)異常產(chǎn)生IRQ通常的中斷FIQ快速中斷reset復(fù)位異常

當(dāng)CPU剛上電時(shí)或按下reset重啟鍵之后進(jìn)入該異常,該異常在管理模式下處理。

irq/fiq一般/快速中斷請求

CPU和外部設(shè)備是分別獨(dú)立的硬件執(zhí)行單元,CPU對全部設(shè)備進(jìn)行管理和資源調(diào)度處理,CPU要想知道外部設(shè)備的運(yùn)行狀態(tài),要么CPU定時(shí)的去查看外部設(shè)備特定寄存器,要么讓外部設(shè)備在出現(xiàn)需要CPU干涉處理時(shí)“打斷”CPU,讓它來處理外部設(shè)備的請求,毫無疑問第二種方式更合理,可以讓CPU“專心”去工作,這里的“打斷”操作就叫做中斷請求,根據(jù)請求的緊急情況,中斷請求分一般中斷和快速中斷,快速中斷具有最高中斷優(yōu)先級和最小的中斷延遲,通常用于處理高速數(shù)據(jù)傳輸及通道的中數(shù)據(jù)恢復(fù)處理,如DMA等,絕大部分外設(shè)使用一般中斷請求。

預(yù)取指令中止異常

該異常發(fā)生在CPU流水線取指階段,如果目標(biāo)指令地址是非法地址進(jìn)入該異常,該異常在中止異常模式下處理。

未定義指令異常

該異常發(fā)生在流水線技術(shù)里的譯碼階段,如果當(dāng)前指令不能被識別為有效指令,產(chǎn)生未定義指令異常,該異常在未定義異常模式下處理。

軟件中斷指令(swi)異常

該異常是應(yīng)用程序自己調(diào)用時(shí)產(chǎn)生的,用于用戶程序申請?jiān)L問硬件資源時(shí),例如:printf()打印函數(shù),要將用戶數(shù)據(jù)打印到顯示器上,用戶程序要想實(shí)現(xiàn)打印必須申請使用顯示器,而用戶程序又沒有外設(shè)硬件的使用權(quán),只能通過使用軟件中斷指令切換到內(nèi)核態(tài),通過操作系統(tǒng)內(nèi)核代碼來訪問外設(shè)硬件,內(nèi)核態(tài)是工作在特權(quán)模式下,操作系統(tǒng)在特權(quán)模式下完成將用戶數(shù)據(jù)打印到顯示器上。這樣做的目的無非是為了保護(hù)操作系統(tǒng)的安全和硬件資源的合理使用,該異常在管理模式下處理。

數(shù)據(jù)中止訪問異常該異常發(fā)生在要訪問數(shù)據(jù)地址不存在或者為非法地址時(shí),該異常在中止異常模式下處理。2. ARM的異常優(yōu)先級Reset→
Data abort→
FIQ→
IRQ→
Prefetch abort→
Undefined instruction/SWI。

3. FIQ 比 IRQ快的原因fiq 比 irq 的優(yōu)先級高FIQ 向量位于向量表的最末端,異常處理不需要跳轉(zhuǎn)FIQ 比 IRQ 多5個(gè)私有的寄存器(r8-r12),在中斷操作時(shí),壓棧出棧操作的少。

三、異常發(fā)生的硬件操作

異常發(fā)生后,ARM核的操作步驟可以總結(jié)為4大步3小步。

1. 4大步3小步保存執(zhí)行狀態(tài):將CPSR復(fù)制到發(fā)生的異常模式下SPSR中;模式切換:CPSR模式位強(qiáng)制設(shè)置為與異常類型相對應(yīng)的值,處理器進(jìn)入到ARM執(zhí)行模式,禁止所有IRQ中斷,當(dāng)進(jìn)入FIQ快速中斷模式時(shí)禁止FIQ中斷;保存返回地址:將下一條指令的地址(被打斷程序)保存在LR(異常模式下LR_excep)中。跳入異常向量表:強(qiáng)制設(shè)置PC的值為相應(yīng)異常向量地址,跳轉(zhuǎn)到異常處理程序中。2. 步驟詳解保存執(zhí)行狀態(tài)

當(dāng)前程序的執(zhí)行狀態(tài)是保存在CPSR里面的,異常發(fā)生時(shí),要保存當(dāng)前的CPSR里的執(zhí)行狀態(tài)到異常模式里的SPSR里,將來異常返回時(shí),恢復(fù)回CPSR,恢復(fù)執(zhí)行狀態(tài)。

模式切換

硬件自動(dòng)根據(jù)當(dāng)前的異常類型,將異常碼寫入CPSR里的M[4:0]模式位,這樣CPU就進(jìn)入了對應(yīng)異常模式下。不管是在ARM狀態(tài)下還是在THUMB狀態(tài)下發(fā)生異常,都會自動(dòng)切換到ARM狀態(tài)下進(jìn)行異常的處理,這是由硬件自動(dòng)完成的,將CPSR[5] 設(shè)置為 0。同時(shí),CPU會關(guān)閉中斷IRQ(設(shè)置CPSR 寄存器I位),防止中斷進(jìn)入,如果當(dāng)前是快速中斷FIQ異常,關(guān)閉快速中斷(設(shè)置CPSR寄存器F位)。

保存返回地址

當(dāng)前程序被異常打斷,切換到異常處理程序里,異常處理完之后,返回當(dāng)前被打斷模式繼續(xù)執(zhí)行,因此必須要保存當(dāng)前執(zhí)行指令的下一條指令的地址到LR_excep(異常模式下LR,并不存在LR_excep寄存器,為方便讀者理解加上_excep,以下道理相同),由于異常模式不同以及ARM內(nèi)核采用流水線技術(shù),異常處理程序里要根據(jù)異常模式計(jì)算返回地址。

跳入異常向量表

該操作是CPU硬件自動(dòng)完成的,當(dāng)異常發(fā)生時(shí),CPU強(qiáng)制將PC的值修改為一個(gè)固定內(nèi)存地址,這個(gè)固定地址叫做異常向量。

四、異常向量表

異常向量表是一段特定內(nèi)存地址空間,每種ARM異常對應(yīng)一個(gè)字長空間(4Bytes),正好是一條32位指令長度,當(dāng)異常發(fā)生時(shí),CPU強(qiáng)制將PC的值設(shè)置為當(dāng)前異常對應(yīng)的固定內(nèi)存地址。

1. 異常向量表:

異常向量表

跳入異常向量表操作是異常發(fā)生時(shí),硬件自動(dòng)完成的,剩下的異常處理任務(wù)完全交給了程序員。由上表可知,異常向量是一個(gè)固定的內(nèi)存地址,我們可以通過向該地址處寫一條跳轉(zhuǎn)指令,讓它跳向我們自己定義的異常處理程序的入口,就可以完成異常處理了。

異常向量表

正是由于異常向量表的存在,才讓硬件異常處理和程序員自定義處理程序有機(jī)聯(lián)系起來。異常向量表里0x00000000地址處是reset復(fù)位異常,之所以它為0地址,是因?yàn)镃PU在上電時(shí)自動(dòng)從0地址處加載指令,由此可見將復(fù)位異常安裝在此地址處也是前后接合起來設(shè)計(jì)的,不得不感嘆CPU設(shè)計(jì)師的偉大,其后面分別是其余7種異常向量,每種異常向量都占有四個(gè)字節(jié),正好是一條指令的大小,最后一個(gè)異常是快速中斷異常,將其安裝在此也有它的意義,在0x0000001C地址處可以直接存放快速中斷的處理程序,不用設(shè)置跳轉(zhuǎn)指令,這樣可以節(jié)省一個(gè)時(shí)鐘周期,加快快速中斷處理時(shí)間。

存儲器映射地址0x00000000是為向量表保留的。在有些處理器中,向量表可以選擇定位在高地址0xFFFF0000處【可以通過協(xié)處理器指令配置】,當(dāng)今操作系統(tǒng)為了控制內(nèi)存訪問權(quán)限,通常會開啟虛擬內(nèi)存,開啟了虛擬內(nèi)存之后,內(nèi)存的開始空間通常為內(nèi)核進(jìn)程空間,和頁表空間,異常向量表不能再安裝在0地址處了。

比如Cortex-A8系統(tǒng)中支持通過設(shè)置CP15的C12寄存器將異常向量表的首地址放置在任意地址。

2. 安裝異常向量表

我們可以通過簡單的使用下面的指令來安裝異常向量表:

b reset ;跳入reset處理程序
b HandleUndef ;跳入未定義處理程序
b HandSWI ;跳入軟中斷處理程序
b HandPrefetchAbt ;跳入預(yù)取指令處理程序
b HandDataAbt ;跳入數(shù)據(jù)訪問中止處理程序
b HandNoUsed ;跳入未使用程序
b HandleIRQ ;跳入中斷處理程序
b HandleFIQ ;跳入快速中斷處理程序

通常安裝完異常向量表,跳到我們自己定義的處理程序入口,這時(shí)我們還沒有保存被打斷程序的現(xiàn)場,因此在異常處理程序的入口里先要保存打斷程序現(xiàn)場。

3. 保存執(zhí)行現(xiàn)場

異常處理程序最開始,要保存被打斷程序的執(zhí)行現(xiàn)場,程序的執(zhí)行現(xiàn)場無非就是保存當(dāng)前操作寄存器里的數(shù)據(jù),可以通過下面的棧操作指令實(shí)現(xiàn)保存現(xiàn)場:

STMFD SP_excep!, {R0 – R12, LR_excep}

注:LR_abt,SP_excep分別為對應(yīng)異常模式下LR和SP,為方便讀者理解加上_abt

需要注意的是,在跳轉(zhuǎn)到異常處理程序入口時(shí),已經(jīng)切換到對應(yīng)異常模式下了,因此這里的SP是異常模式下的SP_excep了,所以被打斷程序現(xiàn)場(寄存器數(shù)據(jù))是保存在異常模式下的棧里,上述指令將R0~R12全部都保存到了異常模式棧,最后將修改完的被打斷程序返回地址入棧保存,之所以保存該返回地址就是將來可以通過類似:MOV PC, LR的指令,返回用戶程序繼續(xù)執(zhí)行。

異常發(fā)生后,要針對異常類型進(jìn)行處理,因此,每種異常都有自己的異常處理程序,中斷異常處理過程通過下節(jié)的系統(tǒng)中斷處理來進(jìn)行分析。

五、異常處理的返回

異常處理完成之后,返回被打斷程序繼續(xù)執(zhí)行,具體操作如下:

恢復(fù)被打斷程序運(yùn)行時(shí)寄存器數(shù)據(jù)恢復(fù)程序運(yùn)行時(shí)狀態(tài)CPSR通過進(jìn)入異常時(shí)保存的返回地址,返回到被打斷程序繼續(xù)執(zhí)行1. 異常返回地址

一條指令的執(zhí)行分為:取指,譯碼,執(zhí)行三個(gè)主要階段, CPU由于使用流水線技術(shù),造成當(dāng)前執(zhí)行指令的地址應(yīng)該是PC – 8(32位機(jī)一條指令四個(gè)字節(jié)),那么執(zhí)行指令的下條指令應(yīng)該是PC – 4。在異常發(fā)生時(shí),CPU自動(dòng)會將將PC – 4 的值保存到LR里,但是該值是否正確還要看異常類型才能決定。

各模式的返回地址說明如下:

一般/快速中斷請求:

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

SUBS PC,LR_irq,#4 ; 一般中斷
SUBS PC,LR_fiq,#4 ; 快速中斷

注:LR_irq/LR_fiq分別為一般中斷和快速中斷異常模式下LR,并不存在LR_xxx寄存器,為方便讀者理解加上_xxx,下同。

預(yù)取指中止異常:

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

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

SUBS PC,LR_abt,#4
未定義指令異常:

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

MOV PC, LR_und
軟中斷指令(SWI)異常:

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

MOV PC, LR_svc
數(shù)據(jù)中止異常:

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

SUBS PC, LR_abt, #8

上述每一種異常發(fā)生時(shí),其返回地址都要根據(jù)具體異常類型進(jìn)行重新修復(fù)返回地址,「再次強(qiáng)調(diào)下,被打斷程序的返回地址保存在對應(yīng)異常模式下的LR_excep里」。

2. 模式恢復(fù)

異常發(fā)生后,進(jìn)入異常處理程序時(shí),將用戶程序寄存器R0~R12里的數(shù)據(jù)保存在了異常模式下棧里面,異常處理完返回時(shí),要將棧里保存的的數(shù)據(jù)再恢復(fù)回原先R0~R12里。

毫無疑問在異常處理過程中必須要保證異常處理入口和出口時(shí)棧指針SP_excep要一樣,否則恢復(fù)到R0~R12里的數(shù)據(jù)不正確,返回被打斷程序時(shí)執(zhí)行現(xiàn)場不一致,出現(xiàn)問題,雖然將執(zhí)行現(xiàn)場恢復(fù)了,但是此時(shí)還是在異常模式下,CPSR里的狀態(tài)是異常模式下狀態(tài)。

因此要恢復(fù)SPSR_excep里的保存狀態(tài)到CPSR里,SPSR_excep是被打斷程序執(zhí)行時(shí)的狀態(tài),在恢復(fù)SPSR_excep到CPSR的同時(shí),CPU的模式和狀態(tài)從異常模式切換回了被打斷程序執(zhí)行時(shí)的模式和狀態(tài)。

此刻程序現(xiàn)場恢復(fù)了,狀態(tài)也恢復(fù)了,但PC里的值仍然指向異常模式下的地址空間,我們要讓CPU繼續(xù)執(zhí)行被打斷程序,因此要再手動(dòng)改變PC的值為進(jìn)入異常時(shí)的返回地址,該地址在異常處理入口時(shí)已經(jīng)計(jì)算好,直接將PC = LR_excep即可。

上述操作可以一步一步實(shí)現(xiàn),但是通常我們可以通過一條指令實(shí)現(xiàn)上述全部操作:

LDMFD SP_excp!, {r0-r12, pc}^

注:SP_excep為對應(yīng)異常模式下SP,^符號表示恢復(fù)SPSR_excep到CPSR。

六、異常與模式關(guān)系

reset異常進(jìn)入SVC模式

fiq快速中斷請求異常進(jìn)入快中斷模式,支持高速數(shù)傳輸及通道處理(FIQ異常響應(yīng)時(shí)進(jìn)入此模式)

irq中斷請求異常進(jìn)入中斷模式,用于通用中斷處理,(IRQ異常響應(yīng)時(shí)進(jìn)入此模式)

prefetch預(yù)取指中止,數(shù)據(jù)中止異常進(jìn)入中止模式,用于支持虛擬內(nèi)存和/或存儲器保護(hù)

undef未定義指令異常進(jìn)入未定義模式,支持硬件協(xié)處理器的軟件仿真(未定義指令異常響應(yīng)時(shí)進(jìn)入此模式)

swi軟件中斷,復(fù)位異常進(jìn)入管理模式,操作系統(tǒng)保護(hù)代碼(系統(tǒng)復(fù)位和軟件中斷響應(yīng)時(shí)進(jìn)入此模式)

七、irq中斷異常1.中斷的概念

什么是中斷,我們從一個(gè)生活的例子引入。我們正在家中看書,突然電話鈴響了,你放下書本,去接電話,和來電話的人交談,然后放下電話,回來繼續(xù)看你的書。這就是生活中的"中斷"的現(xiàn)象,也就是正常的工作過程被外部的事件打斷了。

在處理器中,所謂中斷,是一個(gè)過程,即CPU在正常執(zhí)行程序的過程中,遇到外部/內(nèi)部的緊急事件需要處理,暫時(shí)中斷(中止)當(dāng)前程序的執(zhí)行,而轉(zhuǎn)去為事件服務(wù),待服務(wù)完畢,再返回到暫停處(斷點(diǎn))繼續(xù)執(zhí)行原來的程序。為事件服務(wù)的程序稱為中斷服務(wù)程序或中斷處理程序。

嚴(yán)格地說,上面的描述是針對硬件事件引起的中斷而言的。用軟件方法也可以引起中斷,即事先在程序中安排特殊的指令,CPU執(zhí)行到該類指令時(shí),轉(zhuǎn)去執(zhí)行相應(yīng)的一段預(yù)先安排好的程序,然后再返回來執(zhí)行原來的程序,這可稱為軟中斷。把軟中斷考慮進(jìn)去,可給中斷再下一個(gè)定義:中斷是一個(gè)過程,是CPU在執(zhí)行當(dāng)前程序的過程中因硬件或軟件的原因插入了另一段程序運(yùn)行的過程。因硬件原因引起的中斷過程的出現(xiàn)是不可預(yù)測的,即隨機(jī)的,而軟中斷是事先安排的。

2. 中斷處理流程

中斷異常發(fā)生時(shí),整個(gè)處理流程:

如上圖所示:

執(zhí)行執(zhí)行到0x30000008時(shí)產(chǎn)生中斷cpu執(zhí)行4大步3小步1) 保存CPSR到SPSR_irq
2) 根據(jù)異常類型,設(shè)置模式標(biāo)識位CPSR[4:0],CPU執(zhí)行狀態(tài)CPSR[5]:T位=0和關(guān)閉中斷
3) 設(shè)置返回地址LR=0x30000010
4) 將PC指向?qū)?yīng)的異常向量表地址[中斷IRQ:0x00000018]
進(jìn)入到異常向量表后執(zhí)行 b 指令,跳轉(zhuǎn)到異常處理函數(shù)異常處理函數(shù)需要執(zhí)行以下操作1) 修正返回地址 SUBS PC,LR_irq,#4 ,即0x3000000C
2) 保存現(xiàn)場寄存器
3) 跳入中斷處理函數(shù)isr_proccess(),執(zhí)行中斷處理程序
4) 恢復(fù)現(xiàn)場寄存器
5) 返回現(xiàn)場PC=LR
程序又回到0x3000000C位置,繼續(xù)執(zhí)行

關(guān)于中斷更詳細(xì)的講解,會在后續(xù)文章中詳細(xì)講解,請關(guān)注 [一口Linux]。

八、swi異常SWI指令

SWI指令的格式為:

SWI{條件} 24位的立即數(shù)

SWI指令用于產(chǎn)生軟件中斷,以便用戶程序能調(diào)用操作系統(tǒng)的系統(tǒng)例程。操作系統(tǒng)在SWI的異常處理程序中提供相應(yīng)的系統(tǒng)服務(wù),指令中24位的立即數(shù)指定用戶程序調(diào)用系統(tǒng)例程的類型,相關(guān)參數(shù)通過通用寄存器傳遞,當(dāng)指令中24位的立即數(shù)被忽略時(shí),用戶程序調(diào)用系統(tǒng)例程的類型由通用寄存器R0的內(nèi)容決定,同時(shí),參數(shù)通過其他通用寄存器傳遞。

舉例:

SWI 0x02 ;該指令調(diào)用操作系統(tǒng)編號位02的系統(tǒng)例程。
BKPT指令

BKPT指令的格式為:BKPT 16位的立即數(shù)BKPT指令產(chǎn)生軟件斷點(diǎn)中斷,可用于程序的調(diào)試。

舉例

以下是一個(gè)包含異常向量表的代碼,程序值填寫了reset異常和swi異常的入口,其他入口地址可以用空指令nop填充在這個(gè)位置。

area first, code, readonly
code32
entry
; 定義的異常向量表
vector
b reset_h(yuǎn)andler ; 跳轉(zhuǎn)到 reset_h(yuǎn)andler
nop
b swi_h(yuǎn)andler ; SWI 指令異常跳轉(zhuǎn)的地址
nop
nop
nop
nop
nop
swi_h(yuǎn)andler
; swi handler code
; 異常處理首先要壓棧保存處理器現(xiàn)場
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x10
msr cpsr_c, r0

;ldr r0, [lr, #-4] ; 獲得SWI指令的機(jī)器碼,lr前面那個(gè)指令是swi指令,下標(biāo)在該指令中
;bic r0, r0, #0xff000000 ; 通過機(jī)器碼獲得SWI NUMBER
movs pc, lr ; lr > pc 且 spsr -> cpsr返回 SVC -> USER
reset_h(yuǎn)andler
; 初始化 SVC 模式堆棧
ldr sp, =0x40001000
; 修改當(dāng)前的模式從SVC模式改變?yōu)閁SER模式
mrs r0, cpsr
bic r0, r0, #0x1f
orr r0, r0, #0x10
msr cpsr_c, r0
; 初始化 USER 模式堆棧
ldr sp, =0x40000800
mov r0, #1
; USER SWI
swi 5 ; open APP USER 這條語句由用戶程序自己出發(fā)異常
; 觀察并記錄對比指令執(zhí)行前后的 PC LR CPSR SPSR SP的變化
;并思考異常產(chǎn)生后處理器硬件自動(dòng)發(fā)生了那些變化
add r1, r0, r0
stop
b stop
end

運(yùn)行過程如下所示:

swi指令執(zhí)行

主要是注意觀察swi執(zhí)行前和執(zhí)行后,模式的變化,大家可以按照4大步3小步來分析。

swi指令執(zhí)行前后對比變化

如何同時(shí)跳轉(zhuǎn)并切換模式?

從swi異常返回時(shí),我們需要執(zhí)行兩個(gè)動(dòng)作:

將spsr拷貝會cpsr,pc = lr 跳轉(zhuǎn)回原來的位置

這兩個(gè)動(dòng)作都必須要執(zhí)行,但是如果分步執(zhí)行的話,spsr拷貝回去后,當(dāng)前模式就變回了usr模式,那么對應(yīng)的lr的值就變成了lr_usr,此時(shí)的值0x0【之前沒有執(zhí)行過bl指令】,那怎么跳轉(zhuǎn)會去呢?我們可以用以下命令

movs pc, lr

此命令同時(shí)執(zhí)行兩個(gè)動(dòng)作:

pc = lr
cpsr = spsr 返回 SVC -> USER

從而實(shí)現(xiàn)了同時(shí)跳轉(zhuǎn)并切換模式。如果入口已經(jīng)使用ldm壓??梢杂靡幌轮噶罨貜?fù):

LDMFD SP_excp!, {r0-r12, pc}^

參見第五章。

如何獲取軟中斷號?要獲取swi指令的中斷號,我們只能從swi的機(jī)器碼中得到對應(yīng)的值,

2. 而要想得到swi這條指令的內(nèi)容,就要先找到這條指令的地址,而lr的值是swi這條指令的下一條指令的地址,所以我們可以通過以下代碼得到軟中斷號。

ldr r0, [lr, #-4] ; 獲得SWI指令的機(jī)器碼,lr前面那個(gè)指令是swi指令,下標(biāo)在該指令中
bic r0, r0, #0xff000000 ; 通過機(jī)器碼獲得SWI NUMBER
系統(tǒng)調(diào)用與swi系統(tǒng)調(diào)用

linux的應(yīng)用程序有很多的系統(tǒng)調(diào)用,比如open,read,socket等實(shí)際上會觸發(fā)swi異常,觸發(fā)系統(tǒng)調(diào)用sys_open,sys_read等,內(nèi)核根據(jù)swi的值來執(zhí)行具體的操作。

每個(gè)系統(tǒng)調(diào)用都有自己惟一的編號,系統(tǒng)調(diào)用函數(shù)的標(biāo)識符在以下文件定義:

linux/arch/arm/kernel/calls.S

內(nèi)容如下:

0 CALL(sys_restart_syscall)
CALL(sys_exit)
CALL(sys_fork)
CALL(sys_read)
CALL(sys_write)
…………
375 CALL(sys_setns)
CALL(sys_process_vm_readv)
CALL(sys_process_vm_writev)
CALL(sys_kcmp)
CALL(sys_finit_module)
#ifndef syscalls_counted
.equ syscalls_padding, ((NR_syscalls + 3) & ~3) - NR_syscalls
#define syscalls_counted
#endif
.rept syscalls_padding
CALL(sys_ni_syscall)
.endr
SWI代碼片段分析

搜索下vector_swi,找到入口函數(shù)

archrmkernelentry-common.S
.a(chǎn)lign 5
ENTRY(vector_swi)
@ 保存現(xiàn)場

sub sp, sp, #S_FRAME_SIZE
stmia sp, {r0 - r12} @ Calling r0 - r12
add r8, sp, #S_PC
stmdb r8, {sp, lr}^ @ Calling sp, lr
mrs r8, spsr @ called from non-FIQ mode, so ok.
str lr, [sp, #S_PC] @ Save calling PC
str r8, [sp, #S_PSR] @ Save CPSR
str r0, [sp, #S_OLD_R0] @ Save OLD_R0
zero_fp

@ 獲得swi的指令地址,確保是swi指令
ldr scno, [lr, #-4] @ get SWI instruction
A710( and ip, scno, #0x0f000000 @ check for SWI )
A710( teq ip, #0x0f000000 )
A710( bne .Larm710bug )

@ tbl等于數(shù)組表基地址
get_thread_info tsk
adr tbl, sys_call_table @ load syscall table pointer
ldr ip, [tsk, #TI_FLAGS] @ check for syscall tracing

@清除高8位
bic scno, scno, #0xff000000 @ mask off SWI op-code
@ #define __NR_SYSCALL_BASE 0x900000 這里swi的值實(shí)際上是0x900000 0x900001 ...所以要清除這個(gè)高位的9
eor scno, scno, #__NR_SYSCALL_BASE @ check OS number

@根據(jù)索引號,去tbl 這個(gè)數(shù)組中調(diào)用函數(shù)
@ tbl:數(shù)組表基地址, scno:要調(diào)用的sys_write()的索引值 lsl #2:左移2位,一個(gè)函數(shù)指針占據(jù)4個(gè)字節(jié)
cmp scno, #NR_syscalls @ check upper syscall limit
adr lr, ret_fast_syscall @ return address
ldrcc pc, [tbl, scno, lsl #2] @ call sys_* routine
這里首先獲得swi這條指令的內(nèi)容,swi指令位于lr-4,原因如下圖

2. 然后分析確保是swi指令,也就是

and ip, scno, #0x0f000000

3. 獲得全局的一個(gè)存有系統(tǒng)調(diào)用函數(shù)的數(shù)組的地址4. 通過swi的值去找到這個(gè)數(shù)組的索引,執(zhí)行函數(shù)


審核編輯:符乾江
聲明:本文內(nèi)容及配圖由入駐作者撰寫或者入駐合作網(wǎng)站授權(quán)轉(zhuǎn)載。文章觀點(diǎn)僅代表作者本人,不代表電子發(fā)燒友網(wǎng)立場。文章及其配圖僅供工程師學(xué)習(xí)之用,如有內(nèi)容侵權(quán)或者其他違規(guī)問題,請聯(lián)系本站處理。 舉報(bào)投訴
  • ARM
    ARM
    +關(guān)注

    關(guān)注

    134

    文章

    9057

    瀏覽量

    366874
  • 嵌入式
    +關(guān)注

    關(guān)注

    5072

    文章

    19026

    瀏覽量

    303516
  • 異常
    +關(guān)注

    關(guān)注

    0

    文章

    22

    瀏覽量

    9218
收藏 人收藏

    評論

    相關(guān)推薦

    GPGPU體系結(jié)構(gòu)優(yōu)化方向(1)

    繼續(xù)上文GPGPU體系結(jié)構(gòu)優(yōu)化方向 [上],介紹提高并行度和優(yōu)化流水線的方向。
    的頭像 發(fā)表于 10-09 10:03 ?229次閱讀
    GPGPU<b class='flag-5'>體系結(jié)構(gòu)</b>優(yōu)化方向(1)

    無刷DC門驅(qū)動(dòng)系統(tǒng)的體系結(jié)構(gòu)

    電子發(fā)燒友網(wǎng)站提供《無刷DC門驅(qū)動(dòng)系統(tǒng)的體系結(jié)構(gòu).pdf》資料免費(fèi)下載
    發(fā)表于 09-29 11:52 ?0次下載
    無刷DC門驅(qū)動(dòng)系統(tǒng)的<b class='flag-5'>體系結(jié)構(gòu)</b>

    名單公布!【書籍評測活動(dòng)NO.45】RISC-V體系結(jié)構(gòu)編程與實(shí)踐(第二版)

    。 接著討論了鏈接腳本編寫和內(nèi)存管理的基本概念,包括頁表映射和物理內(nèi)存屬性,為讀者進(jìn)一步探索 RISC-V 的內(nèi)存管理提供了實(shí)用指導(dǎo)。 還詳細(xì)介紹了 RISC-V 體系結(jié)構(gòu)中的異常處理、中斷
    發(fā)表于 09-25 10:08

    電動(dòng)機(jī)出現(xiàn)異常噪聲怎么處理

    當(dāng)電動(dòng)機(jī)發(fā)出異常噪聲時(shí),首先需要檢查的是機(jī)械部件是否出現(xiàn)了問題。其中,軸承是最容易出現(xiàn)問題的部件之一。 軸承磨損或者損壞會導(dǎo)致電動(dòng)機(jī)在運(yùn)行過程中發(fā)出嗡嗡或者嘎吱嘎吱的聲音。這種聲音通常比較明顯,容易
    的頭像 發(fā)表于 09-14 17:19 ?273次閱讀

    如何解決交流接觸器出現(xiàn)異常抖動(dòng)問題

    在工業(yè)控制系統(tǒng)中,交流接觸器穩(wěn)定性直接影響到整個(gè)系統(tǒng)的可靠性。針對交流接觸器出現(xiàn)異常抖動(dòng)問題,采取有效的措施是至關(guān)重要的。本文將詳細(xì)探討如何應(yīng)對交流接觸器異常抖動(dòng)的問題。 首先,從電源電壓的角度出發(fā)
    的頭像 發(fā)表于 09-11 10:52 ?536次閱讀

    嵌入式系統(tǒng)的體系結(jié)構(gòu)包括哪些

    嵌入式系統(tǒng)的體系結(jié)構(gòu)通常是一個(gè)復(fù)雜而精細(xì)的架構(gòu),旨在滿足特定應(yīng)用需求,同時(shí)兼顧系統(tǒng)的可靠性、效率、成本和體積等多方面因素。以下是對嵌入式系統(tǒng)體系結(jié)構(gòu)的詳細(xì)解析,包括其主要組成部分、層次結(jié)構(gòu)以及各部分的功能和特點(diǎn)。
    的頭像 發(fā)表于 09-02 15:25 ?767次閱讀

    工業(yè)控制計(jì)算機(jī)的體系結(jié)構(gòu)是什么

    工業(yè)控制計(jì)算機(jī)是一種專門為工業(yè)自動(dòng)化控制領(lǐng)域設(shè)計(jì)的計(jì)算機(jī)系統(tǒng),具有高性能、高可靠性、實(shí)時(shí)性、可擴(kuò)展性等特點(diǎn)。本文將詳細(xì)介紹工業(yè)控制計(jì)算機(jī)的體系結(jié)構(gòu),包括其硬件結(jié)構(gòu)、軟件結(jié)構(gòu)、通信協(xié)議、控制策略等方面
    的頭像 發(fā)表于 06-16 11:38 ?921次閱讀

    雙線磁環(huán)共模電感測試中出現(xiàn)異常的原因分析

    電子發(fā)燒友網(wǎng)站提供《雙線磁環(huán)共模電感測試中出現(xiàn)異常的原因分析.docx》資料免費(fèi)下載
    發(fā)表于 06-03 14:50 ?0次下載

    嵌入式微處理體系結(jié)構(gòu) 嵌入式微處理器原理與應(yīng)用

    嵌入式微處理器是一種集成于嵌入式系統(tǒng)中的微處理器,其體系結(jié)構(gòu)和應(yīng)用具有獨(dú)特特點(diǎn)。本文將詳細(xì)介紹嵌入式微處理器的體系結(jié)構(gòu)以及其原理與應(yīng)用。 一
    的頭像 發(fā)表于 05-04 16:53 ?2057次閱讀

    嵌入式微處理體系結(jié)構(gòu)有幾種

    嵌入式微處理體系結(jié)構(gòu)是指嵌入式系統(tǒng)中的微處理器采用的硬件結(jié)構(gòu)和設(shè)計(jì)技術(shù),以實(shí)現(xiàn)特定的功能和性能要求。在嵌入式系統(tǒng)中,微處理器被用于控制、通
    的頭像 發(fā)表于 04-21 16:29 ?1137次閱讀

    利用Motor Profiler測試電機(jī)參數(shù)時(shí),老是出現(xiàn)異常的原因?

    大家好,我在利用Motor Profiler測試電機(jī)參數(shù)時(shí),老是出現(xiàn)異常。
    發(fā)表于 04-03 06:08

    嵌入式微處理器的體系結(jié)構(gòu)

    嵌入式微處理器的體系結(jié)構(gòu)通常包括核心架構(gòu)、指令集架構(gòu)、存儲體系架構(gòu)和系統(tǒng)總線架構(gòu)等關(guān)鍵組成部分。
    的頭像 發(fā)表于 03-29 11:48 ?728次閱讀

    變壓器運(yùn)行中常見的異常現(xiàn)象應(yīng)如何處理呢?

    變壓器運(yùn)行中常見的異常現(xiàn)象應(yīng)如何處理?
    的頭像 發(fā)表于 03-08 09:19 ?585次閱讀
    變壓器運(yùn)行中常見的<b class='flag-5'>異常</b>現(xiàn)象應(yīng)如<b class='flag-5'>何處理</b>呢?

    《RVfpga:理解計(jì)算機(jī)體系結(jié)構(gòu)》3.0 版本更新上線

    計(jì)算機(jī)體系結(jié)構(gòu)課程,課程針對本科教學(xué)設(shè)計(jì),包含一整套豐富的教學(xué)資料和實(shí)踐練習(xí),可幫助學(xué)生了解處理器架構(gòu)中的關(guān)鍵要素,包括多個(gè)IP內(nèi)核,修改RISC-V內(nèi)核的方法,
    的頭像 發(fā)表于 01-18 08:27 ?731次閱讀
    《RVfpga:理解計(jì)算機(jī)<b class='flag-5'>體系結(jié)構(gòu)</b>》3.0 版本更新上線

    什么是串?dāng)_?何處理它?

    什么是串?dāng)_?何處理它?
    的頭像 發(fā)表于 12-05 16:39 ?800次閱讀
    什么是串?dāng)_?<b class='flag-5'>該</b>如<b class='flag-5'>何處理</b>它?