如何在ADS调试中使用中断
大家都知道ARM9产生中断的时候PC会自动跳转到0x18地址处执行中断处理代码,但是当FLASH等启动介质中没有预烧录代码会怎么样呢?ARM复位时从启动介质获取的代码为全F或者全0,而如果ADS调试将代码下载到外部RAM里边就会导致0x18地址没有中断处理代码,发生中断当然也就没有办法执行了,其实有几种处理方法:
1、使用ADS的分散加载机制。在下载映像时将带中断处理的代码下载到0地址开始的地方,使0x18地址有中断处理代码,而其它代码加载到外部RAM。
2、预烧录中断处理代码。就是将有中断处理的代码预先烧录到启动介质,当ARM复位的时候自动将代码读取到0地址,这样在调试过程也能很好的处理中断。
3、加载的镜像代码去改变0x18地址的数据。
代码如下:
_ISR_STARTADDRESS EQU 0x33ffff00
AREA StartupCode, CODE
ResetCode
b . ;ResetHandler
b . ;handler for Undefined mode
b . ;HandlerSWI
b . ;HandlerPabort
b . ;HandlerDabort
b .
b IsrIRQ ;HandlerIRQ
b . ;HandlerFIQ
b .;IsrIRQ;EnterPWDN
IsrIRQ
sub sp,sp,#4 ;reserved for PC
stmfd sp!,{r8-r9}
ldr r9,=INTOFFSET1
cmp r9,#0
ldrne r8,=HandleEINT0
bne %f0 ;如果中断来自于INTOFFSET1跳转
ldr r9,=INTOFFSET2
ldr r8,=Handle2D
0 ldr r9,[r9]
add r8,r8,r9,lsl #2
ldr r8,[r8]
str r8,[sp,#8]
ldmfd sp!,{r8-r9,pc}
LTORG
CopyStartupCode
adr r0, ResetCode
mov r2, #0
adr r3, CopyStartupCode
0
ldmia r0!, {r4-r7}
stmia r2!, {r4-r7}
cmp r0, r3
bcc %B0
mov pc,lr
;===============================================================================
ALIGN
AREA HandleAddr, DATA, READWRITE
^ _ISR_STARTADDRESS ; _ISR_STARTADDRESS=0x33FF_FF00
HandleReset # 4
HandleUndef # 4
HandleSWI # 4
HandlePabort # 4
HandleDabort # 4
HandleReserved # 4
HandleIRQ # 4
HandleFIQ # 4
HandleEINT0 # 4
HandleEINT1 # 4
HandleEINT2 # 4
HandleEINT3 # 4
HandleEINT4_7 # 4
HandleEINT8_15 # 4
HandleReserved0 # 4
HandlenBATT_FLT # 4
HandleTICK # 4
HandleWDT_AC97 # 4
HandleTIMER0 # 4
HandleTIMER1 # 4
HandleTIMER2 # 4
HandleTIMER3 # 4
HandleTIMER4 # 4
HandleUART2 # 4
;@0x33FF_FF60
HandleLCD # 4
HandleDMA # 4
HandleUART3 # 4
HandleReserved2 # 4
HandleSDI1 # 4
HandleSDI0 # 4
HandleSPI0 # 4
HandleUART1 # 4
HandleNAND # 4
HandleUSBD # 4
HandleUSBH # 4
HandleIIC0 # 4
HandleUART0 # 4
HandleReserved3 # 4
HandleRTC # 4
HandleADC # 4
;@0x33FF_FFA0
Handle2D # 4
HandleReserve3 # 4
HandleReserve4 # 4
HandleReserve5 # 4
HandlePCM0 # 4
HandleReserve6 # 4
HandleI2S0 # 4
在C文件中调用CopyStartupCode改变0地址开始的一段数据使0x18处能够处理中断。
中断函数初始化代码使用:
#define pISR_USBD (*(unsigned *)(_ISR_STARTADDRESS+0x84))
pISR_USBD = (unsigned)ISR_USBD;
其实三种方法中第一种和第三种都很简单,当初我竟然只用了第二种,为此还专门先写了段烧录ADS烧录NAND的代码,谁那个SJF用不起来,不过因为反正也要通过ADS烧录block0img和eboot也就无所谓了;第三种方法是后来根据EBOOT中USB中断初始化代码想到的;当初没有分散加载文件的方法还有一个原因是有一个重要的C函数,只要一使用分散加载调用就出错,查看Dissamemble发现使用分散加载时ADS Make出来的这个函数最后竟然没有mov pc,lr,搞不清楚它们之间有什么联系,改优化等级都没有用,彻底无奈,只好放弃使用分散加载。
转自:http://www.armce.com/bbs/thread-996-1-1.html
作者:Veabol