ARM7TDMI-S在嵌入式系统中的Bootloader代码设计
MSR CPSR_c,#0xd3 ;设置管理模式堆栈
LDR SP,StackSvc
MSR CPSR_c,#0xd2 ;设置中断模式堆栈
LDR SP,StackIrq
MSR CPSR_c,#0xd1 ;设置快速中断模式堆栈
LDR SP,StackFiq
MSR PSR_c,#0xd7 ;设置中止模式堆栈
LDR SP,StackAbt
MSR CPSR_c,#0xdb ;设置未定义模式堆栈
LDR SP,StackUnd
MSR CPSR_c,#0xdf ;设置系统模式堆栈
LDR SP,StackUsr
MOV PC,R0
StackUsr DCD UsrStackSpace+(USR_STACK_LEGTH-1)*4
StackRvc DCD SvcStackSpace+(SVC_STACK_LEGTH-1)*4
StackIrq DCD IrqStackSpace+(IRQ_STACK_LEGTH-1)*4
StackFiq DCD FiqStackSpace+(FIQ_STACK_LEGTH-1)*4
StackAbt DCD AbtStackSpace+(ABT_STACK_LEGTH-1)*4
StackUnd DCD UndtStackSpace+(UND_STACK_LEGTH-1)*4
;系统初始化代码
Reset
BL InitStack ;调用InitStack函数初始化芯片各种模式的堆栈
BL TargetResetInit ;调用TargetResetInit函数对系统进行基本初始化
B _main ;跳转到ADS提供的启动代码_main函数处,它初始化函数库并最终引导CPU进入操作系统的main()函数
javascript:window.open(this.src);" style="cursor:pointer;"/>
上面的程序代码只包含了流程图中的几个主机步骤。这些步骤都是必不可少的,其余的步骤都在TargetResetInit函数中加以实现。本例中的TargerReset Init函数如下:
void TargetResetInit(void)
{/*设置系统各部分时钟*/
PLLCON=1;
#if((Fcclk /4)/Fpclk==1
VPBDIV=0;
#endif
#if((Fcclk/4)/Fpclk==2
VPBDIV=2;
#endif
#if((Fcclk/4)/Fpclk==4
VPBDIV=1;
#endif
#if(Fcco/Fcclk)==1
PLLCFG=((Fcclk/Fosc)-1)(1<<5);
#endif
#if(Fcco/Fcclk)==2
PLLCFG=((Fcclk/Fosc)-1(2<<5);
#endif
#if(Fcco/Fcclk)==4
PLLCFG=((Fcclk/Fosc)-1(3<<5);
#endif
#if(Fcco/Fcclk)==8
PLLCFG=((Fcclk/Fosc)-1)(4<<5);
#endif
PLLFEED=0xaa;
PLLFEED=0x55;
while(PLLSTAT &(1<<10)==0)
PLLCON=3;
PLLFEED=0xaa;
PLLFEED=0x55;
/*设置存储器加速模块*/
MAMCR=2;
#if Fcclk<20000000
MAMTIM=1;
#else
#if Fcclk<40000000
MAMTIM=2;
#else
MAMTM=3;
#endif
#endif
/*初始化VIC,使芯片在进入μC/OS-II多任务环境前关中断*/
VICIntEnClr=0xffffffff;
VICVectAddr=0;
VICIntSelect=0;
/*其它步骤的代码与实际的软件功能相关,不具有代表性,故在此不列出*/
}
3 结论
本文介绍的Bootloader代码已经在基于Philips公司的LPC2106芯片开发的系统上运行并测试通过。针对不同的CPU芯片编写Bootloader代码,首先要了解该CPU的内核结构、指令系统,其次是具体芯片的结构和各种片上资源,以及所采用的操作系统。以上所列的设计流程不是一成不变的,在具体应用中要权衡取舍。