ARM映像文件及其地址映射.docx_第1页
ARM映像文件及其地址映射.docx_第2页
ARM映像文件及其地址映射.docx_第3页
ARM映像文件及其地址映射.docx_第4页
ARM映像文件及其地址映射.docx_第5页
已阅读5页,还剩5页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

ARM映像文件及其地址映射2010-06-24 14:161、什么是arm的映像文件,arm映像文件其实就是可执行文件,包括bin或hex两种格式,可以直接烧到ROM里执行。在axd调试过程中,我们调试的是axf文件,其实这也是一种映像文件,它只是在bin文件中加了一个文件头和一些调试信息。映像文件一般由域组成,域最多由三个输出段组成(RO,RW,ZI),输出段又由输入段组成。所谓域,指的就是整个bin映像文件所处在的区域,它又分为加载域和运行域。对于嵌入式系统而言,程序映象都是存储在Flash存储器等一些非易失性器件中的,而在运行时,程序中的RW段必须重新装载到可读写的RAM中。简单来说,程序的加载时域就是指程序烧入Flash中的状态,运行时域是指程序执行时的状态。一般来说flash里的 整个bin文件所在的地址空间就是加载域,当然在程序一般都不会放在 flash里执行,一般都会搬到sdram里运行工作,它们在被搬到sdram里工作所处的地址空间就是运行域。我们输入的代码,一般有代码部分和数据部分,这就是所谓的输入段,经过编译后就变成了bin文件中ro段和rw段,还有所谓的zi段,这就是输出段。在ARM的集成开发环境中,只读的代码段和常量被称作RO段(ReadOnly);可读写的全局变量和静态变量被称作RW段(ReadWrite);RW段中要被初始化为零的变量被称为ZI段(ZeroInit)。对于加载域中的输出段,一般来说RO段后面紧跟着RW段,RW段后面紧跟着ZI段。在运行域中这些输出段并不连续,但RW和ZI一定是连着的。ZI段和RW段中的数据其实可以是RW属性。 2、 简单地址映射对于比较简单的情况,可以在ADS集成开发环境的ARM LINKER选项output中指定RO Base和RW Base,即在simple模式下,告知连接器RO和RW的连接基地址。这种模式下,ARM Linker会输出以下符号,它们指示了在运行域中各个输出段所处的地址空间,在使用的时候可以用IMPORT引入:| Image$RO$Base|: 表示RO段在运行域中的起始地址|Image$RO$Limit|:表示RO区末地址后面的地址,即RW数据源的起始地址 |Image$RW$Base|:RW区在RAM里的执行区起始地址,也就是编译器选项RW_Base指定的地址 |Image$ZI$Base|:ZI区在RAM里面的起始地址 |Image$ZI$Limit|:ZI区在RAM里面的结束地址后面的一个地址 RO Base对应的就是| Image$RO$Base|,RW Base 对应的是|Image$RW$Base|,由于ZI段是包含在RW段里的,所以|Image$RW$Limit| 就等于|Image$ZI$limit| 。下面给出一个例子,假设RO Base设为0x00000000,后面的RW Base 地址是0x30000000,然后在Options选项中有Image entry point ,是一个初始程序的入口地址,设为0x00000000,。现在要做的就是将RW section移到以0x30000000开始的地方,并且创造一个ZI section。首先比较Image$RO$Limit和Image$RW$Base,如果相等,说明execution view下RW section的地址和load view 下RW section的地址相同,这样,不需要移动RW section;如果不等, 说明需要移动RW section 到它在execution view中的地方,把ROM里|Image$RO$Limt|开始的RW初始数据拷贝到RAM里面|Image$RW$Base|开始的地址,当RAM这边的目标地址到达|Image$ZI$Base|后就表示RW区的结束和ZI区的开始,接下去就对这片ZI区进行清零操作,直到遇到结束地址|Image$ZI$Limit|示例代码如下: IMPORT|Image$RO$Limit| IMPORT|Image$RW$Base| IMPORT|Image$ZI$Base| IMPORT|Image$ZI$Limit| IMPORTmain; 声明C程序中的Main()函数AREAStart,CODE,READONLY; 声明代码段StartENTRY; 标识程序入口CODE32; 声明32位ARM指令ResetLDRSP,=0x40003F00 ; 初始化C程序的运行环境 LDR R0,=|Image$RO$Limit| ;得到RW数据源的起始地址 LDR R1,=|Image$RW$Base|;RW区在RAM里的执行区起始地址 LDR R3,=|Image$ZI$Base|;ZI区在RAM里面的起始地址 CMP R0,R1 ;检查RW section的地址在load view和execution view下是否相等 BEQ LOOP1 ;如果相等就不移动RW section,直接建立ZI scetion LOOP0 ;否则就copy RW section到execution view下指定的地址 CMP R1,R3LDRCC R2,R0,#4 ;它把从R0中的地址开始的section copy到R1中的地址开始的section STRCC R2,R1,#4 BCC LOOP0 LOOP1 LDR R1,=|Image$ZI$Limit| ;ZI section末地址 MOV R2,#0 ;将ZI section 需要的初始化量装入R2 LOOP2 CMP R3,R1 ;建立并初始化ZI section STRCC R2,R3,#4 BCC LOOP2 Bmain; 跳转到C程序代码Main()函数 END注:LDRCC R2,R0,#4 ;将地址为R0的内存单元数据读取到R2中,然后R0=R0+4CC(小于)为条件码。ARM映像文件及其地址映射 二2010年07月26日 星期一 18:37转载自 kun知道最终编辑 kun知道当我们把程序编写好以后,就要进行编译和链接了,在ADS1.2中选择MAKE按钮,会出现一个Errors and Warnings 的对话框,在该栏中显示编译和链接的结果,如果没有错误,在文件的最后应该能看到Image component sizes,后面紧跟的依次是Code,RO Data ,RW Data ,ZI Data ,Debug 各个项目的字节数,最后会有他们的一个统计数据,后面的字节数是根据用户不同的程序而来的。Image component sizes Code RO Data RW Data ZI Data Debug17256 158096 8 184 112580 Object Totals1064 299 0 0 796 Library Totals= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =Code RO Data RW Data ZI Data Debug18320 158395 8 184 113376 Grand Totals= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =Total RO Size(Code+RO Data) 176715(172.57KB)Total RW Size(RW Data+ZI Data) 192 ( 0.19KB) Total ROM Size(Code+RO Data+RW Data) 176723(172.58KB)= = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = = =Code :显示代码占用了多少字节。RO Data 显示只读数据占用了多少字节。 RW Data 显示读写数据占用了多少字节。ZI Data 显示零初始化的数据占用了多少字节。Debug 显示调试数据占用了多少字节。Object Totals 显示链接到一起以后生成映像的对象占用了多少字节。Library Totals 显示已提取并作为单个对象添加到映像中的库成员占用了多少字节。Grand Totals 显示映像的真实大小。 Grand Totals=Library Totals+Object Totals下面就以上面的数据为例来介绍几个变量的计算:|Image$RO$Base|=Image entry point=0x00000000;表示程序代码存放的起始地址|Image$RO$Limit|=|Image$RO$Base|+Total RO Size(Code+Ro Data)=0x0+176715+1=0x0002B24C(因为要满足4的倍数,所以+1)|Image$RW$Base|=0x30000000;由RW Base指定|Image$RW$Limit|=|Image$RW$Base|+Total RW Size(RW Data+ZI Data)=0x30000000+192=0x300000C0|Image$ZI$Base|=|Image$RW$Base|+RW Data=0x30000000+8=0x30000008|Image$ZI$Limit|=|Image$RW$Limit|3、复杂地址映射对于复杂情况,如RO段被分成几部分并映射到存储空间的多个地方时,需要创建一个称为“分布装载描述文件”的文本文件,通知连接器把程序的某一部分连接在存储器的某个地址空间。需要指出的是,分布装载描述文件中的定义要按照系统重定向后的存储器分布情况进行。在引导程序完成初始化的任务后,应该把主程序转移到RAM中去运行,以加快系统的运行速度。如下图,为了解决复杂memory map的问题需要用到scatter load 机制。_main() 和 main()之不同当所有的系统初始化工作完成之后,就需要把程序流程转入主应用程序,即呼叫主应用程序。最简单的一种情况是:IMPORT mainB main直接从启动代码跳转到应用程序的主函数入口,当然主函数名字可以由用户随便定义。在ARM ADS环境中,还另外提供了一套系统级的呼叫机制。IMPORT _mainB _main_main()是编译系统提供的一个函数,负责完成库函数的初始化和初始化应用程序执行环境,最后自动跳转到main()。所以说,前者是库函数,后者就是我们自己编写的main()主函数;因此我们用的B _main其实是执行库函数,然后该库函数再调用我们的main() 函数,因此在单步调试时会看到先要跑一段程序(其实是库函数),然后再单步到我们自己的main函数(这个同时也说明如果有B _main 则就对应必须有main函数,否则编译出错),如果我们用 B main来进入我们的主函数的话,那在单步调试时就看到直接进入到我们自己的main函数了,中间不会看到其他程序;那么用B _main和用B main 这两这进入我们的main函数方式有什么不同呢?如果采用前者则会由编译器加入一段段拷贝程序,即我们说的从加载域到执行域转化程序;而采用后者就没有这个了,因此如果要进行 段拷贝只能自己动手编写程序来实现了,完成段拷贝后就可以进入我们的主函数了,当然这个主函数不一定是叫做main(),可以起个其他好听的名字,这个有别于使用B _main方式;不管采用哪种方式进入我们的程序,都要有一段段拷贝程序,跑完了段拷贝后才能可以进入我们主程序了!(顺便提一下:startup.s这个文件并没有所谓的段拷贝功能,再看也无益!)对含有启动程序来说,执行地址与加载地址相同不容易实现:如果执行地址与加载地址相同哪当然不需要做段拷贝,但是个人理解编译器还会加入段拷贝程序(如果用B _main的话),只是因为条件不满足而不执行而已;但是对含有启动程序来说,执行地址与加载地址相同就不容易了.因为启动程序是要烧到非易失存储器里,用来在上电执行的,而这个程序必定会有RW段,如果RW放在非易失存储器,如FLASH,那就不好实现RW功能了,因此要给RW移动到能够实现RW功能的存储器,如SRAM等.因此,对含有启动程序来说,执行地址与加载地址相同就不容易实现;程序的入口点在C 库中的_main 处,在该点,库代码执行以下操作:1. 将非零(只读和读写)运行区域从其载入地址复制到运行地址。2. 清零ZI 区域。3. 跳转到_rt_entry。 1.ARM映像文件 ARM中的各种源文件(包括汇编文件,C语言程序及C+程序等)经过ARM编译器编译后生成ELF格式的目标文件。这些目标文件和相应的C/C+运行时用到的库经过ARM连接器处理后,生成ELF格式的映像文件(image),这种ELF格式的映像文件是一种可执行文件,可被写入嵌入式设备的ROM中。 ARM映像文件的组成:ARM映像文件是一个层次性结构的文件,包括了域(region),输出段(output section)和输入段(input section)。 一个映像文件由一个或者多个域组成;每个域最多由三个输出段组成组成;每个输出段又包含一个或者输入段;各输入端包含了目标文件中的代码和数据。 所谓域,指的就是整个bin映像文件所处在的区域,它又分为加载域和运行域。加载域就是映像文件被静态存放的工作区域,一般来说flash里的整个bin文件所在的地址空间就是加载域,当然程序一般都不会放在flash里执行,一般都会搬到sdram里运行工作,它们在被搬到sdram里工作所处的地址空间就是运行域。 我们输入的代码,一般有代码部分和数据部分,这就是所谓的输入段,每个输入段都有相应的属性,可以为只读(ro),可读写的(rw)以及初始化成0的(zi)。ARM连接器根据各输入段的属性将这些输入段分组,再组成对应属性的输出段。对于加载域中的输出段,一般来说ro段后面紧跟着rw段,rw段后面紧跟着zi段。在运行域中这些输出段并不连续,但rw和zi一定是连着的。zi段和rw段中的数据其实可以是rw属性。 通常一个映像文件中包含若干个域,各个域又包含若干的输出段。ARM连接器就需要知道如下信息以决定生成相应的映像文件。 *分组信息:决定如何各将输入段组织成相应的输出段和域。 *定位信息:决定各个域在存储器空间中的起始地址。 根据映像文件中地址映射的复杂程度有两种方法告诉ARM连接器这些相关的信息。 (1)当映像文件中最多包含两个域,每个域最多有三个输出段时,可以使用连接器选项告诉连接器相关的地址映射关系。选项有-ropi,-rwpi,-ro_base,-rw_base,-split等。 (2)当映像文件地址映射关系更复杂时,可以使用一个配置文件(分散加载文件)告诉连接器相关的地址映射关系。2.简单的初始化用户程序的执行环境 ARM映像文件一开始总是存储在ROMFlash里面的,其RO部分既可以在ROMFlash里面执行,也可以转移到速度更快的RAM中执行;而RW和ZI这两部分是必须转移到可写的RAM里去,其实RW包括ZI区域,ZI区域放的是未赋值的全局变量,RW区域放的是已赋值(赋0除外)的全局变量。所谓应用程序执行环境的初始化,就是完成必要的从ROM到RAM的数据传输和内容清零。 先介绍几个必要的符号,编译器使用下列符号来记录各段的起始和结束地址: |Image$RO$Base| :RO段起始地址|Image$RO$Limit| :RO段结束地址加1 |Image$RW$Base| :RW段起始地址|Image$RW$Limit| :ZI段结束地址加1 |Image$ZI$Base| :ZI段起始地址|Image$ZI$Limit| :ZI段结束地址加1 这些符号的值是根据链接器中设置的中ro-base和rw-base的设置来计算的。由于rw和zi相连,|Image$ZI$Base|就等于|Image$RW$Limit| .其它的值都是编译器自动计算出来的。我们还可以通过scatter文件更详细得指定各个输出段的工作地址。初始化用户执行环境主要是把ro、rw、zi三段拷贝到指定的位置。 下面的程序是rw、zi段在运行域中的搬运过程:IMPORT |Image$RO$Limit| /*表示RO区末地址后面的地址,即RW数据源的起始地址*/IMPORT |Image$RW$Base| /*RW区在RAM里的执行区起始地址,也就是编译器选项RW_Base指定的地址*/IMPORT |Image$ZI$Base| /*ZI区在RAM里面的起始地址*/IMPORT |Image$ZI$Limit| /*ZI区在RAM里面的结束地址后面的一个地址*/IMPORT Main ; 声明C程序中的Main()函数AREA Start,CODE,READONLY ; 声明代码段StartENTRY ; 标识程序入口CODE32 ; 声明32位ARM指令 Reset LDR SP,=0x40003F00 ; 初始化C程序的运行环境 LDR R0,=|Image$RO$Limit| /* 取ROM区中数据段的首地址 */ LDR R1,=|Image$RW$Base| /* 取RAM区中RW段的目标首地址*/ LDR R3,=|Image$ZI$Base|/*取RAM区中ZI段的首地址 */ CMP R0,R1 /* 比较ROM区中数据段首地址和RAM区中RW段目标首地址*/ BEQ LOOP1 /*相等代表当前是在RAM中运行*/LOOP0 CMP R1,R3 /*不相等则和RAM区中ZI段的目标地址比较*/ LDRCC R2,R0,#4/*如果r1r3,则把r0地址上的数据读出到r2中,然后r0=r0+4*/ STRCC R2,R1,#4 /*如果r1r3,则把r1地址上的数据读出到r2中,然后r0=r0+4*/ BCC LOOP0 /*如果r1r3,则跳转到Loop0继续执行*/ LOOP1 LDR R1,=|Image$ZI$Limit| /* 取ZI段的结束地址 */ MOV R2,#0LOOP2 CMP R3,R1 STRCC R2,R3,#4 /*

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论