以YLE2410A開發板為例,說說ARM的異常是如何處理滴。
;Pre-defined constants
USERMODE EQU 0x10
FIQMODE EQU 0x11
IRQMODE EQU 0x12
SVCMODE EQU 0x13
ABORTMODE EQU 0x17
UNDEFMODE EQU 0x1B
MODEMASK EQU 0x1F
NOINT EQU 0xC0
;The location of stacks
UserStack EQU (_STACK_BASEADDRESS-0x3800) ;0x33ff4800 ~
SVCStack EQU (_STACK_BASEADDRESS-0x2800) ;0x33ff5800 ~
UndefStack EQU (_STACK_BASEADDRESS-0x2400) ;0x33ff5c00 ~
AbortStack EQU (_STACK_BASEADDRESS-0x2000) ;0x33ff6000 ~
IRQStack EQU (_STACK_BASEADDRESS-0x1000) ;0x33ff7000 ~
FIQStack EQU (_STACK_BASEADDRESS-0x0) ;0x33ff8000 ~
首先當然是進行堆棧初始化啦。。。有7種不同的異常處理,因為它們的堆棧是獨立滴,所以需要單獨進行堆棧分配以及初始化。初始化代碼如下:
InitStacks
;Don't use DRAM,such as stmfd,ldmfd......
;SVCstack is initialized before
;Under toolkit ver 2.5, 'msr cpsr,r1' can be used instead of 'msr cpsr_cxsf,r1'
mrs r0,cpsr
bic r0,r0,#MODEMASK
orr r1,r0,#UNDEFMODE|NOINT
msr cpsr_cxsf,r1 ;UndefMode
ldr sp,=UndefStack
orr r1,r0,#ABORTMODE|NOINT
msr cpsr_cxsf,r1 ;AbortMode
ldr sp,=AbortStack
orr r1,r0,#IRQMODE|NOINT
msr cpsr_cxsf,r1 ;IRQMode
ldr sp,=IRQStack
orr r1,r0,#FIQMODE|NOINT
msr cpsr_cxsf,r1 ;FIQMode
ldr sp,=FIQStack
bic r0,r0,#MODEMASK|NOINT
orr r1,r0,#SVCMODE
msr cpsr_cxsf,r1 ;SVCMode
ldr sp,=SVCStack
;USER mode has not be initialized.
mov pc,lr
做好這個初始化之後呢,當然就是IRQ的分配了。就說說普通的IRQ吧,一般在WINCE下很難用到FIQ滴。嘿嘿。。。一家之言。
因為ARM有7種不同的異常處理,所以:
LTORG
HandlerFIQ HANDLER HandleFIQ
HandlerIRQ HANDLER HandleIRQ
HandlerUndef HANDLER HandleUndef
;HandlerUndef
; sub sp, sp, #4 ;decrement sp(to store jump address)
; stmfd sp!, {r14} ;PUSH the work register to stack(lr does't push because it return to original address)
; ldr r0, =HandleUndef ;load the address of HandleXXX to r0
; ldr r0, [r0] ;load the contents(service routine start address) of HandleXXX
; str r0, [sp, #4] ;store the contents(ISR) of HandleXXX to stack
; ldmfd sp!, {r0, pc}
HandlerSWI HANDLER HandleSWI
HandlerDabort HANDLER HandleDabort
HandlerPabort HANDLER HandlePabort
也是需要7種不同的中斷向量了哦。這個和單片機是差不多滴。。。一般都是放在前面撒。
異常服務程序
這裡不用中斷(interrupt)而用異常(exception),畢竟中斷只是異常的一種情況,