; (r2) = pending interrupt event mask mov r1, #1 orr r2, r2, r1, lsl r0 ; (r2) = new pending mask str r2, [lr, #pendevents] ; save it ;*pendevents = *pendevents|(1<<interruptno); ; ; mark reschedule needed ;情況1:r0=sysintr_resched=1 ;情況2: r0 =r0-sysintr_devices>=sysintr_max_devices 10 ldrb r0, [lr, #bresched] ; (r0) = reschedule flag orr r0, r0, #1 ; set "reschedule needed bit" strb r0, [lr, #bresched] ; up-date flag 20 mrs r1, spsr ; (r1) = saved status register value and r1, r1, #0x1f ; (r1) = interrupted mode cmp r1, #user_mode ; previously in user mode? cmpne r1, #system_mode ; if not, was it system mode? cmpeq r0, #1 ; user or system: is resched == 1 ;if(sytemmode(spsr)||usermode(spsr))&&r0!=1) return; ldmnefd sp!, {r0-r3, r12, pc}^ ; can"t reschedule right now so return ************************************************************************************* sub lr, lr, #4 ldmfd sp!, {r0-r3, r12} stmdb lr, ldmfd sp!, str r0, [lr] ; save resume address mov r1, #id_reschedule ; (r1) = exception id b commonhandler entry_end irqhandler 將spsr_irq壓入irq堆棧保存。為調(diào)用oeminterrupthandler作準備。(通常中斷處理程序切換入系統(tǒng)態(tài)執(zhí)行的目的在于避免使用終端模式下的寄存器,以方便是實現(xiàn)終端套嵌,這兒切入系統(tǒng)態(tài)時終端使能是關(guān)閉的,對于模態(tài)切換的原因我很迷惑。)oeminterrupt需要在特權(quán)模式下執(zhí)行,所以這里增加了切換入特權(quán)(svc)模式的內(nèi)容。緊接著將要用與傳遞參數(shù)的寄存器保存。設(shè)定傳入?yún)?shù),r0就可以開始調(diào)用oeminterrupthandler了,這里的調(diào)用規(guī)則遵循windowsce的規(guī)范而不是atpcs的規(guī)范。具體過程參考arm parameter passing@msdn。下面是函數(shù)原形。int oeminterrupthandler(unsigned int ra);這里傳入的參數(shù)就是上面的r0,事實上r0代表的參數(shù)ra并沒有實質(zhì)的作用在這里僅僅是形式上的實現(xiàn)一下而已,不過在這兒可以看到這個傳入的ra實際上就是被中斷的地址,如果需要知道被中斷的位置可以通過ra來查詢,而msdn里面說這個參數(shù)是保留的。返回的參數(shù)也是保存在r0中。其中返回值是系統(tǒng)中斷類型。其中sysintr_resched為系統(tǒng)時鐘中斷,每次時間片用完,該時鐘便產(chǎn)生中斷,并設(shè)置kdata結(jié)構(gòu)的bresched位,進入調(diào)度流程。如果中斷類型是系統(tǒng)設(shè)備中斷,那就設(shè)置pendevents,待再次調(diào)度的時候處理中斷。所以oeminterrupthandler必須提前就要對中斷進行響應對該中斷源設(shè)置mask,防止在這過程中同一中斷不停發(fā)生,導致中斷飽和影響程序流的執(zhí)行,直道中斷處理真正完成后再次開放該中斷的mask。在這里還可以看到的是系統(tǒng)設(shè)備中斷號的范圍是從sysintr_devices到sysintr_max_devices,也就是從9-40一共32個設(shè)備中斷號,其中sysintr_firmware為8+16號,這個在編寫oal的中斷服務程序時需要注意。如果當前的返回值既不是設(shè)備中斷號又不是調(diào)度中斷號,則讀出當前調(diào)度標示,根據(jù)該標示進行判斷是否調(diào)度/或返回.如果是進入調(diào)度流程則恢復初始的寄存器狀態(tài),再按commonhandler的要求保存寄存 |