Main函数之IsrInit分析.docx
《Main函数之IsrInit分析.docx》由会员分享,可在线阅读,更多相关《Main函数之IsrInit分析.docx(13页珍藏版)》请在冰豆网上搜索。
Main函数之IsrInit分析
飞凌2440Bootloader学习中的若干问题
1.2440init.s分析
1)关于HANDLER宏定义
MACRO
$HandlerLabelHANDLER$HandleLabel;宏定义
$HandlerLabel
;由于ADS仅支持FD(满递减)型堆栈
subsp,sp,#4;将堆栈退一个字用于保存下面用到的R0
stmfdsp!
{r0};将R0压入堆栈
ldrr0,=$HandleLabel;将HandleLabel的地址赋给R0
ldrr0,[r0];将HandleLabel的地址指向的内容
;(实际的中断函数的执行地址)赋给R0
strr0,[sp,#4];将对应的中断函数首地址入栈保护
ldmfdsp!
{r0,pc};将中断函数的首地址出栈,放入PC中,系统将跳转到
;对应中断处理函数
MEND
HANDLER是宏名。
$HandlerLabel是宏展开后要被别的字符替换掉的标号,不过不叫参数。
例如:
HandlerFIQHANDLERHandleFIQ
展开后为:
HandlerFIQ
subsp,sp,#4
stmfdsp!
{r0}
ldrr0,=HandleFIQ
ldrr0,[r0]
strr0,[sp,#4]
ldmfdsp!
{r0,pc}
启动代码中有很多的类似下面的语句:
HandlerFIQHANDLERHandleFIQ
HandlerIRQHANDLERHandleIRQ
HandlerUndefHANDLERHandleUndef
HandlerSWIHANDLERHandleSWI
HandlerDabortHANDLERHandleDabort
HandlerPabortHANDLERHandlePabort
等等
该宏定义的代码用于将对应中断服务程序ISR的入口地址装载到PC中,可称之为“加载程序”。
本初始化程序定义了一个34个字空间的数据区(文件最后),用于存放相应中断服务程序的首地址。
每个字空间都有一个标号,以HandleXXX命名。
在向量中断模式下使用“加载程序”来执行中断服务程序。
在_ISR_STARTADDRESS=0x33FF_FF00里定义的第一级中断向量表是采用型如Handle***的方式的.而在程序的ENTRY处(程序开始处)采用的是bHandler***的方式.
在这里Handler***就是通过HANDLER这个宏和Handle***进立联系的.这种方式的优点就是正真定义的向量数据在内存空间里,而不是在ENTRY处的ROM(FLASH)空间里,这样,我们就可以在程序里灵活的改动向量的数据了.其中HANDLER是一个宏,用于查找中断处理程序的入口地址。
这些地址存放在由HandleXXX指向的表项中,该表定位在RAM高端,基地址为_ISR_STARTADDRESS。
假如_ISR_STARTADDRESS为0x800000000,当IRQ中断时,根据bHandlerFIQ,先跳转再根据^_ISR_STARTADDRESS基地址+HandleIRQ的偏移地址(4*6)得到的中断地址
0x80000000+0x00000024=0x80000024
2)
ALIGN
AREARamData,DATA,READWRITE
^_ISR_STARTADDRESS;_ISR_STARTADDRESS=0x33FF_FF00
HandleReset#4
HandleUndef#4
HandleSWI#4
HandlePabort#4
HandleDabort#4
Ø这个^起什么作用的呢?
^,是ARM汇编中的一个伪操作,和MAP是同义词,用来定义一个结构化的内存表的首地址。
#,也是一个伪操作,和FIELD是同义词,用来定义结构化的内存表中的一个数据域。
Øbootloader设定的中断向量表在启动Wince系统之后是不是就没用了?
没有用了,进入CE后会重新初始化中断向量的。
Ø那么是Wince在启动之后,自己又重新设定了中断向量表?
在哪个文件中设定的呢?
又把向量表保存在哪了?
OAL的startup.s中会调用KernelStart,里面会设置向量表。
可以参考%_WINCEROOT%\PRIVATE\WINCEOS\COREOS\NK\KERNEL\ARM\armtrap.s。
2.
初始化中断服务程序。
当中断产生时,处理相应的程序
voidIsr_Init(void)
{
pISR_UNDEF=(unsigned)HaltUndef;
pISR_SWI=(unsigned)HaltSwi;
pISR_PABORT=(unsigned)HaltPabort;
pISR_DABORT=(unsigned)HaltDabort;
rINTMOD=0x0; //All=IRQmode
rINTMSK=BIT_ALLMSK; //Allinterruptismasked.
}
pISR_UNDEF=(unsigned)HaltUndef; 就是将函数HaltUndef的地址强制转换为unsigned类型,赋给指针pISR_UNDEF。
由pISR_UNDEF定义知,
#definepISR_UNDEF (*(unsigned*)(_ISR_STARTADDRESS+0x4))
pISR_UNDEF为相应的异常中断地址。
函数名称代表函数的地址,即将HaltUndef函数的地址赋值到_ISR_STARTADDRESS+0x4中。
当发生中断时,系统会去pISR_UNDEF定义的地址里取出中断函数的地址也就是HaltUndef的地址,然后执行.就相当于当发生中断时,执行HaltUndef函数.
voidHaltUndef(void)
{
Uart_Printf("Undefinedinstructionexception!
!
!
\n");
while
(1);
}
注意:
unsignedlong*p
p=((unsignedlong*)0x80001000);
上面2句可以写成
unsignedlong*p=((unsignedlong*)0x80001000);
*p=0x55555555,就是给地址0x80001000写0x55555555
#defineAT91C_SDRAM((unsignedint*)0x20000000)//根据sdram的地址进行修改
unsingedint*pTemp=AT91C_SDRAM,指针pTemp的地址为0x20000000
/*PinConnectBlock*/
#definePINSEL0(*((volatileunsignedlong*)0xE002C000))
#definePINSEL1(*((volatileunsignedlong*)0xE002C004))
#definePINSEL2(*((volatileunsignedlong*)0xE002C014))
PINSEL0=0x00050000;地址0xE002C000的值为0x00050000
首先(volatileunsignedlong*)0x48000000的意思是把0x48000000强制转换成volatileunsignedlong类型的指针,即对指针的操作的范围是从0x48000000开始的4个字节(long型).暂记为p,那么就是
#defineA*p,即A为P指针指向位置的内容了。
这里就是通过内存寻址访问到寄存器A,可以读/写操作!
表示处理相应中断。
1./********************************************************************
2.*名称:
Timer1_ISR()
3.*功能:
定时器1中断服务程序
4.*入口参数:
5.********************************************************************/
6.void__irqTimer1_ISR(void)
7.{
8.
9. staticintcount;
10. count++;
11. rSRCPND=rSRCPND|(0x1<<11);
12. rINTPND=rINTPND|(0x1<<11);
13.
14. //每隔为1秒蜂鸣器响一次,持续时间为0.5秒
15. if(count%1000==0)
16. rGPADAT|=(1<<16); //蜂鸣器响
17. elseif(count%1000==500)
18. rGPADAT&=~(1<<16); //蜂鸣器不响
19.}
复制代码
1./********************************************************************
2.*名称:
Timer1_init()
3.*功能:
定时器1初始化
4.*入口参数:
5.********************************************************************/
6.void Timer1_init(void)
7.{
8. U32 time_val;
9.
10. rTCFG0=3; //配置定时器0,1的预分频值
11. rTCFG1=0<<4; //配置定时器1分频值
12.
13. time_val=PCLK/(3+1)/2/1000-1; //1ms=PCLK/prescaler/divider/1000
14.
15. rSRCPND=rSRCPND|(0x1<<11); //清除中断源未决寄存器相应位
16. rINTPND=rINTPND|(0x1<<11); //
17. rINTMSK=~(0x1<<11); //打开定时器1中断
18.
19. rTCNTB1=time_val; //计数缓存寄存器
20. rTCMPB1=time_val>>1; //50%