初探WindowsCE異常和中斷服務(wù)程序
中斷和異常都是異步發(fā)生的事件,當該事件發(fā)生,系統將停止目前正在執行的代碼轉而執行事件響應的服務(wù)程序。而事件服務(wù)程序的入口點(diǎn)就是中斷/異常向量所在的位置。ARM的中斷向量可以是0x0開(kāi)始的低地址向量,也可以是在FFFF0000位置的高向量地址。winCE下使用高地址作為trap區,所以在CE下arm使用高地址向量。
VectorINStructiONs
ldr pc, [pc, #0x3E0-8] ; reset
ldr pc, [pc, #0x3E0-8] ; undefined inSTruction
ldr pc, [pc, #0x3E0-8] ; SVC
ldr pc, [pc, #0x3E0-8] ; Prefetch abort
ldr pc, [pc, #0x3E0-8] ; data abort
ldr pc, [pc, #0x3E0-8] ; unused vector location
ldr pc, [pc, #0x3E0-8] ; IRQ
ldr pc, [pc, #0x3E0-8] ; FIQ
而在ffff03e0的位置放上如下的數據,每一項(32bit)對應一個(gè)異常的跳轉地址也就是winCE的異常/中斷向量跳轉表。該表項的內容就是發(fā)生異常后將要執行的服務(wù)程序的入口地址。具體如下。
VectorTable
DCD -1 ; reset
DCD UndefException ; undefined instruction
DCD SWIHandler ; SVC
DCD PrefetchAbort ; Prefetch abort
IF :DEF:ARMV4T :LOR: :DEF:ARMV4I
DCD OEMDataAbortHandler ; data abort
ELSE
DCD DataAbortHandler ; data abort
ENDIF
DCD -1 ; unused vector
DCD IRQHandler ; IRQ
DCD FIQHandler ; FIQ
在上面的這些代碼/數據在內存空間上按照上述要求放置好以后,每次觸發(fā)一個(gè)異常就自動(dòng)運行到相應跳轉表項所對應的地址執行。
2.異常/中斷服務(wù)程序
在arm下,由于有7種異常狀態(tài)包括reset、Undef exception、software interrupt(swi)、Prefech Abort、DataAbort、IRQ、FIQ七種異常/中斷。reset僅在復位時(shí)發(fā)生,其他6種都是在系統運行時(shí)發(fā)生。當任何一個(gè)異常發(fā)生并得到響應時(shí),ARM 內核自動(dòng)完成以下動(dòng)作:
拷貝 CPSR 到 SPSR_
設置適當的 CPSR 位:
改變處理器狀態(tài)進(jìn)入 ARM 狀態(tài)
改變處理器模式進(jìn)入相應的異常模式
設置中斷禁止位禁止相應中斷
更新 LR_
設置 PC 到相應的異常向量
同時(shí)不管異常發(fā)生在A(yíng)RM 還是Thumb 狀態(tài)下,處理器都將自動(dòng)進(jìn)入ARM 狀態(tài)。并且中斷使能會(huì )自動(dòng)被關(guān)閉。在這個(gè)時(shí)候由于部分通用寄存器是不同模式公用的,所以還需要保存這些將會(huì )被破壞的寄存器,待到處理完成的時(shí)候恢復這些寄存器被中斷前的狀態(tài)。另外在進(jìn)入異常模式后,lr的值不一定就是我們所需恢復執行的位置,該位置受到異常類(lèi)型和流水線(xiàn)誤差的影響。在SWI模式下,LR就是返回值。在IRQ和FIQ中LR=LR-4,DataAbort下LR=LR-8;下面分別對這些服務(wù)程序進(jìn)行分析。
2-1.undef exception服務(wù)程序
undef exception在執行到過(guò)非法的指令時(shí)產(chǎn)生,通常來(lái)模擬一些處理器不支持的功能,如浮點(diǎn)運算。簡(jiǎn)單說(shuō)一下undef exception的過(guò)程:當當前指令為一條處理器不支持的指令時(shí),處理器會(huì )自動(dòng)動(dòng)將該指令送交各協(xié)處理器(如MMU、FPU)處理,如果這些協(xié)處理器都無(wú)法識別這條指令的時(shí)候,就產(chǎn)生該異常。下面開(kāi)始看相應的代碼。
NESTED_ENTRY UndefException
sub lr, lr, #4 ; (lr) = address of undefined instruction
stmdb sp, {r0-r3, lr}
mov r1, #ID_UNDEF_INSTR
b CommonHandler
ENTRY_END UndefException
上面就是undef Exception的服務(wù)程序的入口處(已經(jīng)將不參與編譯和Thumb模式下的代碼去掉),通過(guò)lr-=4計算出觸發(fā)異常前的指令地址,同時(shí)保存r0-r3和lr入undef_exception stack用于最后恢復現場(chǎng)和取得異常指令本身,隨后進(jìn)入分發(fā)程序CommonHandler.CommonHandler是一個(gè)公共的異常服務(wù)程序,它通過(guò)不同的傳入參數來(lái)進(jìn)行處理,在這里mov r1,#ID_UNDEF_INSTR就是指定異常模式為undef Exception.
2-2.swi服務(wù)程序
按在A(yíng)RM處理器的設計意圖,系統軟件的系統調用(systemCalls)都是通過(guò)SWI指令完成。SWI相當于一個(gè)中斷指令,不同的是SWI不是由外部中斷源產(chǎn)生的,同時(shí)對應于SWI的異常向量位于0xc的位置或0xffff 000c的位置。也就是說(shuō)當執行一個(gè)swi指令后,當前程序流中斷,并轉入0xc或0xffff000c執行,同時(shí)將CPSR_mode(當前程序狀態(tài)寄存器)復制入SPSR_svc,轉入SVC模式運行(使用特權模式的寄存器組)。也就是說(shuō)系統通過(guò)執行SWI引發(fā)系統swi異常后切換入特權模式,系統調用功能號由swi xx后的xx決定,在運行完指定功能的代碼后返回異常時(shí)的地址并恢復用戶(hù)模式。Wince中這部分代碼是如何實(shí)現的。
DCD SWIHandler ; SVC《--------------------------SWI入口點(diǎn)。
LEAF_ENTRY SWIHandler
IF {FALSE}
…
ENDIF
movs pc, lr
ENTRY_END SWIHandler
上面IF {FALSE}到ENDIF之間的代碼在編譯的時(shí)候是得不到編譯的(事實(shí)上這部分代碼是用于開(kāi)發(fā)中調試使用的,針對特殊的硬件平臺,一般與我們使用的硬件平臺無(wú)關(guān)。所以下面摘抄的代碼都不將不參與編譯的內容寫(xiě)入),因此SWI服務(wù)程序就是一句話(huà)。movs pc, lr也就是直接回到SWI的地方,同時(shí)將SPSR_svc恢復到CPSR_mode中。這個(gè)過(guò)程中并沒(méi)有進(jìn)行在系統態(tài)執行特定系統指令序的工作,而僅僅是簡(jiǎn)單的返回,所以這不是系統調用,系統調用還需要根據調用號的不同運行指定的核心態(tài)代碼。也就是說(shuō)Wince的系統調用不是通過(guò)SWI來(lái)完成的,而是通過(guò)其他的異常處理手段達成的。
2-3 中斷服務(wù)程序
IRQ(大概是最熟悉的異常方式了)在外部中斷源在需要向處理器請求服務(wù)時(shí)發(fā)生,比如:時(shí)鐘、外圍器件FIFO上/下溢出、按鍵等等。IRQHandler就是中斷的處理句柄,具體如下。
----------------------------------------------------------------------------------
NESTED_ENTRY IRQHandler
sub lr, lr, #4 ; fix return address
stmfd sp!, {r0-r3, r12, lr} ;保存將要用到的寄存器和lr壓入stack_irq
評論