底层中断调试--开中断,程序就飞--这是为什么??--(与wince无关)
程序运行在Supervisor Mode下,当程序做完初始化、中断向量表初始化以后。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
这是一段宏指令,用于下面的程序调用。
MACRO
$HandlerLabel HANDLER $HandleLabel
$HandlerLabel
subsp,sp,#4 ;decrement sp(to store jump address)
stmfdsp!,{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)的地址
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
bResetHandler 程序的第一条指令,地址为0
省略
bHandlerIRQ程序的irq指令,地址为0x18,为了让程序跳入AddrIRQ(0x33ffff18)的地址里面存放的中断向量影射函数地址IsrIRQ(0x30000190),
程序应该跳转到IsrIRQ 处执行。
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
获得中断类型,依据中断类型查找向量表(见最后),pc跳转到向量表对应的中断服务首地址
IsrIRQ
subsp,sp,#4 ;reserved for PC
stmfdsp!,{r8-r9}
ldrr9,=INTOFFSET
ldrr9,[r9]依据中断类型
ldrr8,=HandleEINT0
addr8,r8,r9,lsl #2
ldrr8,[r8]查找向量表
strr8,[sp,#8]
ldmfdsp!,{r8-r9,pc}pc跳转到向量表对应的中断服务首地址
。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。。
ResetHandler(程序真正开始执行的地方)
。。。。。。。初始化一些东西
blInitStacks //各个模式下的堆栈初始化,最后初始化管理模式下的堆栈,[color=#FF0000]并且令管理模式下允许接收irq中断
; Setup IRQ handler设置中断向量表查询入口地址
ldrr0,=HandleIRQ HandleIRQ =0x33ffff18
ldrr1,=IsrIRQ IsrIRQ=0x30000190
strr1,[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]依据中断类型
ldr r8,=HandleEINT0
add r8,r8,r9,lsl #2
ldr r8,[r8]查找向量表
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}pc跳转到向量表对应的中断服务首地址
原來的返回位址呢?? ISR 結束後要去哪??
Paul, Chao @ Techware
[解决办法]
学习来了
[解决办法]
uping
[解决办法]
你这是ADS 下的代码吧?
看了一下,和我的没有差别啊。是不是你写的中断函数有问题。
其余的和我一摸一样。
[解决办法]
哦,我准备买RVDS
现在很多人还停留在ADS上的
楼主一味求新,就注定孤独单干了。那玩意没有使用过。
[解决办法]
开了MMU吗,一般调试器不支持中断跳转的,可以通过MMU处理后支持调试器。
[解决办法]
这个肯定不是,ARM中断产生后,会自动跳转到对应的中断地址,比如复位时跳到0,ISR 跳到 ISR 异常入口,当中断产生时,代码不是直接跳到中断程序中,而是进行了一次类似复位的操作,然后根据对应的中断异常再执行处理。
所以一般仿真器是不会自动找到中断程序的,一般的做法是在启动代码初始化完成,并且使能中断前,用MMU把你代码的ResetHandle地址映射到0地址,这样仿真器就能找到中断函数入口而不会跑飞。
还有一种可能就是你对中断的堆栈没有进行正确的初始化。
[解决办法]