《ARM 启动代码详解.docx》由会员分享,可在线阅读,更多相关《ARM 启动代码详解.docx(9页珍藏版)》请在课桌文档上搜索。
1、ARM启动代码详解(Vectors.Ini1.s.Target.cTarget.h)2010-05-1516:03启动代码是芯片豆位后进入C语言的mainO函数前执行的一段代码,主要是为运行C语言程序提供根本运行环境,如初始化存储潺系统等。八RM公司只设计内核,不自C1.生产芯片,只是把内核授权给其它J.商,其它厂商购置了授权I1.参加自己的外设后生产出各具特色的芯片。这样就促进了基TARM处理器核的芯片多元化,但也使得每一种芯片的后动代码差异很大,不易编写出统一的启动代码,ADS(针对ARM处理器核的C语言编译器的策略是不提供完整的启动代码,启动代码缺乏局部或者由厂商提供,或者自己编写。启动
2、代码划分为4个文件:Vectors.C.Init.s.Target,c.Target.hoVeCtors.c包含异常向室表、堆栈初始化及中断效劳程序与C程序的接口。Init.s包含统初始化代码,并跳转到ADS提供的初始化代码.Targe1.C和Target.h包含目标板特殊的代码,包括异常处理程序和目标板初始化程序。这样做的目的是为了尽量减少正编代码,同时把不需要修改的代码独立出来以减少错误。4.2.1VeC1.Ors.c文件的编写4.2.1.1中断向量表nouscVectors1.DRPC.ResetAddr1.DRPC,UndefinedAddr1.DRPC,SW1.Addr1.DRPC,
3、PrefetchAddr1.DRPC,DataAbortAddrDCD0xb9205f801.DRPC,PC,K-OxffO1.DRPC,FQAddrResetAddrDCDResetUndefinedAddrDCDUndefinedSW1.AddrDCDSoftwareInterruptPrefetchAddrDCDPrefetchAbortDataAbortAddrDCDDatabortDCD0IRQ.AddrDCDIRQJIand1.erFIQ_AddrDCDFIQJIand1.er异常是由内部或外部源产生的以引起处理器处理的一个事件。八RM处理器核支持1种类型的异常。异常出现后,CPU
4、强制从异常类型对应的固定存储地址开始执行程序。这个固定的地址就是异常向员。向量从上到下依次为夏位、未定义指令异常、软件中断、预取指令中止、预取数据中止、保存的异常、IRQ和FIQ.IRQ向:ft“1.DRPC,PC,AOxffO*使用的指令与其它向下不同。在正常情况下这条指令所在地址为OXooOooO18。当CPU执行这条指令但还没有跳转时,PC的值为0X00000020,OXOoOoO020减去OXoOOOoFFo为OXFFFFFO30,这是向量中断控制器(VIC)的特殊存放器VICveCtAddr。这个存放器保存当前将要效劳的IRQ的中断效劳程序的入口,用这条指令就可以直接跳转到需要的中断
5、效劳程序中.至丁在保存的异常向垃“MD0xb9205f80位置填数据0xb9205f8是为了使向量表中所有的数据32位累加和为0。4.2.1.2初始化C1.t堆枝InitStackMOVR0,1.RMSRCPSR_c,S0xd2;设置中断模式堆栈1.DRSP1StackIrqMSRCPSRC,MXd1;设置快速中断模式堆栈1.DRSP,StackFiqMSRCPSRC,#0xd7;设置中止模式堆栈1.DKSP,StackAbtMSRCPSRc1.SOxdb:设置未定义模式堆栈1.DRSP1StackUndMSRCPSRc,#Oxdf;设置系统模式堆栈1.DRSP,StackSysMOVPC,R
6、OStackIrqDCD(IrqStackSpace+IRQ_STACK.EGTH*4-4)StackFiqDCD(FiqStackSpace+FQSTACIC1.EGTH*4-4)StackAbtDCD(AbtStackSpace+ABT_STACK1.EGTH*4-4)StackUndDCD(1.ndtStackSpace+UND_STACKIEGTH*4-4)StackSysDCD(SysStackSpace+SYS_STACK_1.EGTH*4-4);/*分配堆栈空间*/AREAMyStacks,DT,NO1.NITIrqStackSpaceSPACEIRQSTACK1.EGTH*4;
7、中断模式堆栈FiqStackSpaceSPACEF1.QSTACKJEGTH*4:快速中断模式推栈AbtStackSpaceSPACEAB1.STACKJEGTH*4;中止义模式堆枝UndtStackSpaceSPACEUV)STACK_1.EGTH*4;未定义模式堆栈SySSIaCkSpaCeSPACESYSSTACK1.EGTH*4;系统模式堆栈因为程序需要切换模式,而且程序退出时CP1.J的模式已经不再是管理模式而是系统模式1.R已经不再保存返回程序地址,所以程序首先把返回地址保存到Ro中,同时使用Ro返回。然后程序把处理器模式转化为IRQ模式,并设置IRQ模式的堆栈指针。其中变员Sta
8、CkIrq保存着IRQ模式的堆栈指针的初始值,Irqstackspace是分配给IRQ模式的堆栈空间的开始地址JRQSTACK1.EGTH是用户定义的常量,用于设置IRQ模式的堆枝空间的大小。程序使用同样的方法设置F1.Q模式堆栈指针、中止模式堆栈指针、未定义堆栈指针和系统模式堆栈指针。程序使用编译器分配的空间作为堆栈,而不是按照通常的做法把堆栈分配到RAM的顶端,之所以这样是因为这样做不必知道RAM顶端位置,移植更加方便:编译器给出的占用RAM空间的大小就是实际占用的大小,便于控制RAM的分配。对于1.PC2106来说,中止模式是不需要分配堆栈空间的,这是因为1.PC2106没有外部总线,也
9、没有虚拟内存机制,如果出现取数据中止或取指令中止肯定是程序有问题,而一般情况下也不需要模拟协处理器指令或扩充指令,未定义中止也就意味若程序有错误,也不需要分配堆栈空间。4.2.1.3异常处理代码与C语言的接口程序C0511中断效劳子程序流程图如图4T所示:51kaifkacom执行中断返回指令I手、-C返回)图4-1中断效劳子程序流程图异常处理代码与C语言的接口程序如卜丁MACRO$1RQ1.abe1.HAND1.ER$IRQExceptionEXPORT$IRQJabe1.的标号IMPoRTS1.RQException部标号$IRQ1.abe1.SUB1.R,1.R,#4;计算返回地址STM
10、I-DSP!,(R0-R3,R12,1.R):输出;引用的外:保存任务环R3,MRSSTMFDSP!,(R3)OSIntNesting+1.DRR2,=OSIntNesting*,1.DRBR1.,R2ADDR1.,R1.1#1STRBR1.,R2理程序B1.$IRQException:调用C语言的中断处MSRCPS1.1.c,#0x92:关中断B1.OSIntExit1.DRRO1=OSTCBHighRdy1.DRRO,R01.DRR1.,=OSTCBCur1.DRR1.,RUCMPRO1RI1.DMFDSP!,(R3)MSRSPSRcxsf,R31.DMEQFDSP!,R0-R3,R12,
11、PC):不进行任务切换I.DKPC,=OSIntCtxSw:进行SPSR:保存状态任务切换MENDUndefined;未定义指令bPrefetchAbort:取指令中止bDataAbort:取数据中止bIRQJand1.erFIQHand1.er:快速中断bUndefinedPrefetchAbortDataAbortHAND1.ERIRQJxceptionFIQHand1.er:中断TimerOHand1.erHAND1.ERTimerO:定时器。中断未定义指令异常、取指令中止异常、取数据中止异常均是死循环,其中原因在上一小节已经说明。而快速中断在本应用中并未使用,所以也设置为死循环。1.P
12、C2106使用向量中断控制器,各个IRQ中断的人口不一样,所以使用了一个宏来简化中断效劳程序与C语言的接口编写。由RM处理器核的文档可知,处理器进入IRQ中断效劳程序时(1.R-I)的值为中断返回地址,为了使任务无论在主动放弃CP1.时还是中断时堆栈结构都一样,在这里先把1.R减4。其它的局部与C0S-耍求的根本一致。ARM处理核在进入中断效劳程序时处理器模式变为IRQ模式,与任务的模式不同,它们的堆栈指针SP也不一样,而存放涔应当保存到用户的堆栈中,为了减少不必要的CPU时间和RAM空间的浪费,本移植仪在必要时将处理器的存放器保存到用户的堆栈中,其它时候还是保存到IRQ模式的堆栈中。同时,从
13、编译器的函数调用标准可知,C语言函数返回时,存放器R4-R11、SP不会改变,所以只需要保存CpSR、Ro-R3、R12和返回地址1.R,在后面保存CPSR是为了必要时将存放器保存到用户堆栈比较方便。在异常处理代码与C语言的接口程序中没有与中断效劳子程序流程图中的判断语句对应的语句。判断语句是为了防止在函数OS1.ntCtXSW()调整堆栈指针,这个调整量是与编译器、编译器选项、uC/OS-II配置选项都相关的变量。在这里进行这些处理相对其它处理器结构可能增加的处理器时间很少,但对于ARM来说,由中断(IRQ)有独立的堆栈.在这里这样做就需要把所有存放器从中断的堆栈拷贝到任务的堆栈,需要花费比
14、较多的额外时间。而变量OSIn1.NeS1.ing为。时,并不一定会进行任务切换,所以本移植没有与之对应的程序,而在函数OS1.ntCtXS*()中做这一项工作。这样,仅在需要时才处理这些事物,程序效率得以提高。在中断调用后,如果需要任务切换,则变量OSTCBHighRdy和变量OSTCBCUr的值不同;如果不需要任务切换这两个变员则相同。本移植通过判断这两个变量来决定是进行任务切换,还是不进行任务切换.,通过比较,如果需要任务切换则执行U)RPC,=OS1.ntCtXSW”跳转到OS1.ntCtXSW处进行任务切换;如果不需要任务切换则执行“1.DMEQFDSP!,R0R3,R12,PC丁中
15、断返回。这里需要对MSRCPSRc,#0x92”说明下,这条指令的作用是关IRQ中断。因为中断(IRQ)模式的1.R存放器在处理器响应中断时用于保存中断返回地址,所以在处理器响应中断时中断(IRQ)模式的1.R存放器不能保存有效数据.,而B1.指令要用1.R存放器保存B1.下一条指令的位置,所以在中在(IRQ)模式时,在B1.指令之前必须关中断,在保存1.R后才能开中断。4.2.2Target,c文件的编写为了使系统根本能够工作,必须在进人mainO函数前对系统进行一些根本的初始化工作,这些工作由函数TargetReSe1.Ini1.()完成。voidTargetResetInit(void)
16、uint32i:uint32*cp1.;uin1.32*cp2;externvoidVectors(void):*拷贝向量表,保证在f1.ash和ram中程序均可正确运行*/cp1.=(uint32*)Vectors;cp2=(uint32*)0x40000000:for(i=0:i2*8:i+)cp2+-*cp1.+s)MEMMAP=0x2:PINSE1.O=(PINSE1.O&OxFFFFOOOO)UARTOPCBPINSE1.CFG0x50;P1.1.CON=I5/设置系统各局部时钟*/VPBDIV-0:P1.1.CFG=0x23;P1.1.FEED=Oxaa;P1.1.FEED=0x5
17、5;whi1.e(P1.1.STT&(110)=0);P1.I.CON=3:P1.1.FEED=Oxaa;P1.1.FEED=0x55;MAMCR=2;*设置存储器加速模块/#ifEcc1.k20000000MAMTIM=I;Seise#ifFcc1.k40000000MAMT1.M=2;片e1.seMAMTIM=3;#endifJtendif首先向量表拷贝到RAM底部,加上这局部是为了代码无论从F1.ash基地址开始编译还是从RAM基地址开始编译程序均运行正确。而把RAM底部映射到向量表“IEMMAP-0x2也是为了同一个目的。至于豆制16个字而不是8个字,是因为后8个字存储跳转的地址是通过
18、PC指针间接寻址的,它们与对应指令(在向量表中)相对位置是不能变化的。因为在进入多任务环境前使用了一些外设,同部外设使用了芯片的引脚,而UJC2106的所有引脚都是多功能的,所以需要设置引脚功能。同时串口也进行了设置。时钟是芯片各局部正常工作的基础,虽然时钟可以在任何时候设置,但为了防止混乱,最好在进入mainO函数前设置。程序首先使能P1.1.但不连接P1.1.,然后设置外设时钟(YPB时钟PCIk)与系统时钟(CC1.k)的分频比.接着设置P1.1.的乘因子和除因子。设置完成后,使用aP1.1.FEED=Oxaa;P1.1.FEED=0x55/的访间序列把数据正确写入硬件,并等待P1.1.
19、噩踪完成。最后,使能P1.1.,并使P1.1.联上系统。本应用外接的晶振频率(FoSC)为11.0592MHz,倍增罂的值M=4,所以处理器时钟(FCC1.k)为44.2368MHz。为了使电流控制振荡器频率(Fcco)满足156-320VHZ,所以分频器的值P=2,使得Fee。=Fcc1.k2P=176.9472UHze取VPB分频器的分频值为4,所以外设时钟(Fpc1.k)=FCC1.k/4=11.0592MHZ,则记数周期为0.09042us,定时0.2ms,则记数值为2212个,这些时钟的定义都在COnfi&h文件中。用户程序最终是要在FIaSh中运行的,而系统第位时F1.aSh是以最
20、低速度运行,这对发挥芯片的性能极其不利。虽然存储器加速模块可以在任何时候设置,但为了防止混乱,最好在进入main()函数前设置。首先使存储器加速模块全速工作,然后根据系统主时钟利用条件编译将FIaSh的访问时钟设置到适宜的值.4.2.3In.s文件的编写由于1.PC2106微控制版的存储系统比较简单,所以系统初始化代码也比较简单,代码如下:ResetB1.InitStack:初始化堆栈B1.TargetRese1.Ini1.;目标板根本初始化B_main:跳转到C语言入口在芯片及位在芯片第位时程序会跳传到标号RCSet处,程序首先调用InitStaCk初始化各种模式的堆栈,然后调用TargetReSetInit对系统进行根本初始化,最后跳转到ADS提供的启动代码main。_main是ADS提供的启动代码起始位置,它初始化阵并最终引导CPU进入Inain函数。类别:AnnIEMEI1.添加到搜藏I分享:到i贴吧I浏览(428)|进段(0)EE上一篇:PiC单片机键盘程序下*篇:1.pC系列ARM7startup.s启动代.