1、ARM 的分散加载对于刚学习ARM的人来说,如果分析它的启动代码,往往不明白下面几个变量的含义:|Image$RO$Limit|、|Image$RW$Base|、|Image$ZI$Base|。首先申明我使用的调试软件为ADS1.2,当我们把程序编写好以后,就要进行编译和链接了,在ADS1.2中选择MAKE按钮,会出现一个Errors and Warnings的对话框,在该栏中显示编译和链接的结果,如果没有错误,在文件的最后应该能看到Image component sizes,后面紧跟的依次是Code,RO Data,RW Data,ZI Data,Debug各个项目的字节数,最后会有他们的一
2、个统计数据:本文引用地址:Code 163632,RO Data 20939,RW Data 53,ZI Data 17028Tatal RO size (Code+ RO Data) 184571 (180.25kB)Tatal RW size(RW Data+ ZI Data) 17081(16.68 kB)Tatal ROM size(Code+ RO Data+ RW Data) 184624(180.30 kB)后面的字节数是根据用户不同的程序而来的,下面就以上面的数据为例来介绍那几个变量的计算。在ADS的Debug Settings中有一栏是Linker/ARM Linker,在o
3、utput选项中有一个RO base选项,下面应该有一个地址,我这里是0x0c100000,后面的RW base地址是0x0c200000,然后在Options选项中有Image entry point,是一个初始程序的入口地址,我这里是0x0c100000。有了上面这些信息我们就可以完全知道这几个变量是怎么来的了:|Image$RO$Base| = Image entry point = 0x0c100000;表示程序代码存放的起始地址|Image$RO$Limit|=程序代码起始地址+代码长度+1=0x0c100000+Tatal RO size+1= 0x0c100000 + 18457
4、1 + 1 = 0x0c100000 +0x2D0FB + 1= 0x0c12d0fc|Image$RW$Base| = 0x0c200000;由RW base地址指定|Image$RW$Limit| =|Image$RW$Base|+ RW Data 53 = 0x0c200000+0x37(4的倍数,0到55,共56个单元)=0x0c200037|Image$ZI$Base| = |Image$RW$Limit| + 1 =0x0c200038|Image$ZI$Limit| = |Image$ZI$Base| + ZI Data 17028=0x0c200038 + 0x4284=0x0
5、c2042bc也可以由此计算:|Image$ZI$Limit| = |Image$RW$Base| +TatalRWsize(RWData+ZIData) 17081=0x0c200000+0x42b9+3(要满足4的倍数)=0x0c2042bc原文地址简单应用时可以不写.scf文件。而在Output页中选择Simple.然后填写RO Base和RW Base的起始地址。在Lay Out页中,填写Object/Symble: Startup.o, Section: Start.编写启动文件:Startup.s.在Option页里的Image Entry Point填入起始地址。-Scatter
6、-Load Description File的结构:.scf文件中的+RW对应.s源文件中的READWRITE.scf文件中的+ZI对应.s源文件中的NOINIT.scf文件中的+RO对应.s源文件中的READONLY.在.s源文件中有:AREA area_name CODE/DATA,READONLY/NOINIT/READWRITEEND.scf的例子内容注解ROM_LOAD 0x80000000;Name of Load Region, Start Address for Load Region and Maximum size of Load Region(省略了)ROM_EXEC 0
7、x80000000 0x20000;片外存储区,从0x80000000开始,最多0x20000字节。Startup.o(Vector,+First);Startup模块的Vector段放在最前面。注1*(+RO);其他所有模块中的所有代码和只读的数据放在这里。IRAM 0x40000000 0x00004000;片内RAM区,从0x40000000开始,最多0x4000字节Startup.o(MyStacks,+first);指定Startup.o中MyStacks放在最前面。Startup.o(+RW,+ZI);Startup.o中的其他+RW/+ZI段。注1os_cpu_a.o(+RW,+
8、ZI)STACKS 0x40004000 UNINIT;片内16K RAM的顶端,存放不需要被C library初始化的段。Stack.o(+ZI)注2ERAM 0x80040000*(+RW,+ZI)HEAP +0 UNINIT;+0表示接着上一段ERAM的结尾,继续安排存储区。Heap.o(+ZI)注3下面是在scf文件中引用过的源文件示意:Startup.scode 32area Vectors,CODE,READONLYentry.end注1:在Startup.o里面会生成名为Vectors的段,段的属性为READONLYStack.sarea Stacks, DATA, NOINIT
9、export StackUsrStackUsr SPACE 1end注2:在Stack.o里面会生成名为Stacks的段,段的属性为NOINIT,该属性对应scf文件中的+ZI.该段不需要初始化或者可以被初始化为0.Heap.sarea Heap,DATA,NOINITexport bottom_of_heapbottom_of_heap SPACE 1end注3: Heap.o里面名为Heap的段。在Scatter文件中最好每一个Region都加一个Maximum参数,这样当编译时如果实际使用的空间大于Maximum Size,会有Error:16220E: Excution region
10、xxx size (xxx bytes) exceeds limit (xx bytes)。如果地址有重复,会有Error: 16221E: Excution region xxx overlaps with excution region xxx。前一个Region的首地址+ Maximum 后一个Region的首地址时不一定有Error。只有当一分配的内存出现覆盖时才会有Error。Region的UNINIT之类的参数要放在Maximum size参数之前。在一个Region中,RAM的分配不是按照罗列的顺序来的。要想让汇编中使用的变量有固定的位置,可以把所有汇编文件产生的.o放在同一个R
11、egion中。如:IRAM1 0x40000000startup.o(+RW,+ZI)ASMSourceCode1.o(+RW,+ZI)ASMSourceCode2.o(+RW,+ZI)IRAM2 +0CSourceCode1.o(+RW,+ZI)CSourceCode2.o(+RW,+ZI)这样,所有汇编中定义的变量地址就相对集中了。如果只有一个汇编文件如startup.s,也可以这样:IRAM 0x40002000 0x1000startup.o (Mystack,+first)*(+RW,+ZI)用一个+first强行将startup.s中的Mystack放在0x40002000位置。在
12、Edit - DebugRel Settings.-ARM Linker中选中Image map。编译后在Error & Warnings窗口会显示出详细的内存分配情况。如果在List file name中指定一个输出文件名,该祥单会直接存在制定文件中以供多次研究。-关于JTAG接口:P1.20/TRACESYNC应该加上拉电阻以禁止TRACE功能。PINSEL2一定要在程序开始时初始化一下。LPC2210JTAG注1,2/VDD3.3VP1.31/nTRST, input 3/nTRST, output EasyJTAG中有上拉电阻。P1.28/TDI, input 5/TDI, outpu
13、t EasyJTAG中有上拉电阻。P1.30/TMS, input 7/TMS,output EasyJTAG中有上拉电阻。P1.29/TCK, input/output 9/TCK, input/output EasyJTAG中有上拉电阻。P1.26/RTCK, input 11/RTCK, output P1.26外接下拉电阻。P1.26有内部上拉电阻,故测量时该引脚会呈现高电平。但是在复位时,它的上拉电阻不起作用,只有外部的下拉电阻起作用,P1.26 = 0V,所以上电后PINSEL2的D3D0会是0x04(B0100),JTAG有效。若将P1.26接到3.3V再复位,此时PINSEL2
14、的D3D0将会是0x00,JTAG无效。P1.27/TDO, output 13/TDO, input EasyJTAG中有上拉电阻。nRESET, input 15/nRST, output EasyJTAG中有上拉电阻。4,6,8,10,12,14,16,18,20/GND17,19/NCG18控制板采用LPC2114,每次运行Axd都不会正确调入程序。原因如下:有一次是因为已经有一个Axd在运行了,打开第二个Axd,当然不会正确调入程序。还有一次是重新编译了一下,就好了。以上两次都不奇怪,奇怪的是下面几次:在Config Target - Config - Easy JTag Setup随便点两下Halt Mode中的选项,然后一路点击OK,会出现Reload the last Image?,点击Yes。有时会有正确的程序被调入,但有时候不成功。要检验是不是已经成功
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1