程序运行在Supervisor Mode下,当程序做完初始化、中断向量表初始化以后。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
这是一段宏指令,用于下面的程序调用。
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
sub sp,sp,#4 ;decrement sp(to store jump address)
stmfd sp!,{r0-r1} ;PUSH the work register to stack(lr does't push because it return to original address)
ldr r0,=$HandleLabel;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-r1,pc} ;POP the work register and pc(jump to ISR)
MEND
LTORG
HandlerIRQ HANDLER AddrIRQ 调用上面的宏,令HandlerIRQ 的内容存放AddrIRQ(0x33ffff18)的地址
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
b ResetHandler 程序的第一条指令,地址为0
省略
b HandlerIRQ 程序的irq指令,地址为0x18,为了让程序跳入AddrIRQ(0x33ffff18)的地址里面存放的中断向量影射函数地址IsrIRQ(0x30000190),
程序应该跳转到IsrIRQ 处执行。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
获得中断类型,依据中断类型查找向量表(见最后),pc跳转到向量表对应的中断服务首地址
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]依据中断类型
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]查找向量表
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}pc跳转到向量表对应的中断服务首地址
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
ResetHandler(程序真正开始执行的地方)
。。。。。。。初始化一些东西
bl InitStacks //各个模式下的堆栈初始化,最后初始化管理模式下的堆栈,[color=#FF0000]并且令管理模式下允许接收irq中断
; Setup IRQ handler设置中断向量表查询入口地址
ldr r0,=HandleIRQ HandleIRQ =0x33ffff18
ldr r1,=IsrIRQ IsrIRQ=0x30000190
str r1,[r0] 意图想在中断来临的时候,程序自动从0x33ffff18 读出0x30000190,并跳转到0x30000190处执行查询中断向量表[/color]
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
AREA RamData, DATA, READWRITE 中断向量表
^ _ISR_STARTADDRESS(ISR_STARTADDRESS==0x33ffff00)
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
AddrIRQ # 4
HandleFIQ # 4
;Don't use the label 'IntVectorTable',
;The value of IntVectorTable is different with the address you think it may be.
;IntVectorTable
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_23 # 4
HandleRSV6 # 4
HandleBATFLT # 4
HandleTICK # 4
HandleWDT # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
HandleLCD # 4
HandleDMA0 # 4
HandleDMA1 # 4
HandleDMA2 # 4
HandleDMA3 # 4
HandleMMC # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleRSV24 # 4
HandleUSBD # 4 HandleUSBD=0x33ffff84
HandleUSBH # 4
HandleIIC # 4
HandleUART0 # 4
HandleSPI1 # 4
HandleRTC # 4
HandleADC # 4
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
void Isr_Init(void)
pISR_USBD =(unsigned)IsrUsbd;//c代码中将中断服务程序首地址写入向量表。在0x33ffff84里写入函数IsrUsbd的地址0x30002294
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
void ConfigUsbd(void)配置usbd设备
{
ReconfigUsbd();
rINTMSK&=~(BIT_USBD); 配置完成后,程序只要一开中断(0x4a000008里面写入0xfdffffff),中断来临时,程序立即进入中断模式,但是程序却跑飞了。
}
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
------解决方案--------------------
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET
ldr r9,[r9]依据中断类型