scatter文件的写法.doc_第1页
scatter文件的写法.doc_第2页
scatter文件的写法.doc_第3页
scatter文件的写法.doc_第4页
scatter文件的写法.doc_第5页
已阅读5页,还剩75页未读 继续免费阅读

下载本文档

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

文档简介

scatter文件的写法程序总有两种状态:运行态和静止态。当系统掉电的时候程序需要被保存在非易失性的存储器中,且这个时候程序的排放是按照地址依次放的,换句话说:我才懒得管它怎么放,只要不掉就行。当系统上电后,CPU就要跑起来了,CPU属于高速器件,存储器总是不怎么能跟得上,既然跟不上那么我们就尽量缩短它们之间的差距,那留下一条路,那就是尽量提高存储器的读取速度,存储器类型决定其速度的水平,那么尽量放在速度高的存储器就成为首选解决方案。那么我们就把要执行的程序暂时拿到速度较快的RAM中。那么拿的过程就牵涉到程序的加载了。这就是要解决的问题。一个映像文件由域(region)、输出段(output sections)和输入段(input sections)组成。不要想得太复杂,其实他们之间就是包含与被包好的关系。具体关系是这样的:映像文件 域 输出段 输入段输入段:输入段就是我们写的代码+初始化的数据+应该被初始化为0的数据+没有初始化的数据,用英文表示一下就是:RO(ReadOnly),RW (ReadWrite),ZI(ZeroInitialized),NOINIT(Not Initialized)。ARM连接器根据各个输入段不同的属性把相同的拿再一起组合一下就成为了输出段。请看看平时写的东东:AREA RESET, CODE, READONLYAREA DSEG1, DATA, READWRITEAREA HEAP, NOINIT, READWRITE看出其属性没?输出段:为了简化编译过程和更容易取得各种段的地址,那么把多个同属性的输入段按照一定的规律组合在一起,当然这个输出段的属性就和它包含的输入段的属性一样咯。输入段的排放规律就是:最先排放RO属性的输入段,然后是RW属性段,最后是ZI或NOINIT段。域:为什么还要加一层域,我的理解是由于代码的功能不同,那么我们有必要把不同功能的代码分类放。我们可以把需要高速执行的代码放在一起、把对速度要求不高的放在一起、把执行频率高的放在一起,把执行频率低的放在一起.那么按照这种方式放的代码就可以根据其具体需要放在不同的存储器中了。这样可以提高程序执行速度。一个域中包含13个输出段。映像文件:我暂时把映像文件理解成烧到存储器中的文件,由N个域组成。这些域其实可以看做是独立的模块,只是他们按照一定的顺序(这个顺序还是:RO+RW+ZI)被捆绑在一起,这样才方便烧写到非易失存储器中去。好了,了解了映像文件的组成,那么来看看映像文件是怎么跑起来的。映像文件就是有N节车厢的火车,车厢(域)里装着要送到不同站(不同类型的存储器)的货物。到相应的站了,那么就把相应的车厢拿下来。指挥拿这个的就是scatter文件。拿下货物车厢后,我们就解开它,把里面的品牌为RO的货物提取出来,按照scatter的指示发给某个地址,然后再先后把品牌为RW和ZI的货物发到scatter指定的地址。看看这个加深理解:LOAD_ROM1 0X00000000 ; 从火车上取出来时的地址(如:成都站) EXEC_ROM1 0x40000000 PROGRAM.O(+RO) ;把品牌RO的货物发给0x40000000去 RAM1 0x80000000 PROGRAM.O(+RW,+ZI);把品牌RW,ZI的货物依次发给0x80000000 .其他的段也可以这样依葫芦画瓢。scatter的原理就介绍这样,其中的语法和规则要多写多把代码的地址拖出来看才能体会。不过都是很简单的,生活中的小常识就能解决这些问题。为什么?因为设计这些规则的工程师的灵感就是源自生活。嘿嘿.享受把代码随处放的乐趣吧,.enjoy.scatterloading 实际的嵌入式系统中,ADS提供的缺省存储器映射是不能满足要求的。用户的目标硬件通常有多个存储器设备位于不同的位置,并且这些存储器设备在程序装载和运行时可能还有不同的配置。 Scatterloading可以通过一个文本文件来指定一段代码或数据在加载和运行时在存储器中的不同位置。这个文本文件scatterfile在命令行中由-scatter开关指定,例如: armlink_scatterscat.scffilel.ofile2.0 在scatterfile中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,Scatlertoading的存储区块可以分成二种类型: 装载区:当系统启动或加载时应用程序的存放区。 执行区:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。 映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。在系统启动时,C函数库中的_main初始化代码会执行必要的复制及清零操作,使应用程序的相应代码和数据段从装载状态转入执行状态。 1.scatter文件语法 scatter文件是一个简单的文本文件,包含一些简单的语法。 My_Region 0x0000 0x1000 the context of region 每个块由一个头标题开始定义,头中至少包含块的名字和起始地址,另外还有最大长度和其他一些属性选项。块定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。 一个加载块必须至少含有一个执行块;实践中通常有多个执行块。 一个执行块必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。 2.简单分散加载样例 图8所示样例中,只有一个加载块,包含了所有的代码和数据,起始地址为0。这个加载块一共对应两个执行块。一个包含所有的RO代码和数据,执行地址与装载地址相同;同时另一个起始地址为0x10000的执行块,包含所有的RW和ZI数据。这样当系统开始启动时,从第一个执行块开始运行(执行地址等于装载地址),在执行过程中,有一段初始化代码会把装载块中的一部分代码转移到另外的执行块中。 下面是这个scatter描述文件,该文件描述了上述存储器映射方式。 LOAD_ROM 0x4000 EXE_ROM 0x0000 0x4000;Rootregion +RO;Allcodeandconstantdata RAM 0x10000 0x8000 *+RW,+ZI;Allnon-constantdata 3.在分散文件中放置对象 在大多数应用中,并不是像前例那样,简单地把所有属性都放在一起,用户需要控制特定代码和数据段的放置位置。这可以通过在scatter文件中对单个目标文件进行定义实现,而不是只简单地依靠通配符。 为了覆盖标准的连接器布局规则,我们可以使用+FIRST和+LAST分散加载指令。典型的例子是在执行块的开始处放置中断向量表格: LOAD_ROM 0x0000 0x4000 EXEC_ROM 0x0000 0x4000 vectors.oVect,+FIRST *+RO ;moreexecregions. 在这个scatter文件中,保证了vextors.o中的Vect域被放置于地址0x0000。 4.RootRegion(根区) 根区是一个执行块,它的加载地址与执行地址是一致的。每个scatter文件至少有一个根区。分散加载有一个限制:创建执行块的代码和数据(即完成复制和清零的代码和数据)无法自行复制到另一个位置。因此,在根区中必须含有下面的部分: _main.o,包含复制代码/数据的代码; 连接器输出变量$Table和ZISection$Table,包含被复制代码/数据的地址。 由于上面两个部分的属性是只读的,因此他们被*+RO通配符语法匹配。如果*+RO被用在了非根区中,则在根区中必须显式地指明另一个RO区域。 下面是一个例子: LOAD_ROM 0x0000 0x4000 EXE_ROM 0x0000 0x4000;rootregion _main.o+RO;copyingcode *Region$Table;RO/RWaddressestocopy *ZISection$Table;ZIaddressestozero RAM 0x10000 0x8000 *+RO;allotherROsections *+RW,+ZI;allRWandZIsections Scatter文件编写Scatter文件编写 一个映像文件中可以包含多个域(region),在加载和运行映像文件时,每个域可以有不同的地址。每个域可以包括多达3个输出段,每个输出段是由若干个具有相同属性的输入段组成。这样在生成映像文件时,ARM链接器就需要知道下述两个信息。 分组信息 决定各域中的输出段是由哪些输入段组织而成; 定位信息 决定各域在存储空间中的起始地址。 根据映像文件中地址映射的复杂程度,有两种方法来告诉ARM链接器这些相关的信息。对于映像文件中地址映射关系比较简单的情况,可以使用命令行选项;对于映像文件中地址映射关系比较复杂的情况,可以使用一个scatter配置文件。Scatter文件又称为分散加载文件,将重点讲解如何编写scatter文件。1、Scatter文件结构 Scatter文件是一个文本文件,使用BNF语法来描述ARM链接器生成映像文件时所需要的信息。具体来说,在scatter文件中可以指定下列信息: 各个加载时域的加载时起始地址、最大尺寸和属性; 每个加载时域包含的输出段; 各个输出段的运行时起始地址、最大尺寸、存储访问特性和属性; 各个输出段中包含的输入段。 一个Scatter文件包含若干个加载域,一个加载域包含若干个输出段,一个输出段由若干个具有相同属性的输入段组成,其结构如图1所示。 图1 Scatter文件结构示意图 加载时域的描述 加载时域包括名称、起始地址、属性、最大尺寸和一个运行时域的列表。使用BNF语法描述,加载时域的格式如下所示:Load_name base_designator attribute max_size Load_name 运行时域名称,它除了唯一地标识一个运行时域外,还用来构成链接器生成的链接符号; base_designator 用来表示本加载时域的起始地址,它可以有两种格式表示:起始地址或偏移量; attribute 本加载时域的属性,其可能的取值为下面之一,默认的取值为ABSOLUTE: o PI 位置无关属性; o RELOC 重定位; o ABSOLUTE 绝对地址; max_size 最大尺寸,如果本加载时域的实际尺寸超过了该值,链接器将报告错误。默认的取值为0xFFFFFFFF。 输出段的描述 输出段包括名称、起始地址、属性、最大尺寸和一个输入段的集合。使用BNF语法描述,输出段的格式如下所示:output_name base_designator attribute max_size output_name 输出段的名称,它用来唯一地标识一个输出段,还用来构成链接器生成的链接符号。 base_designator 用来表示本输出段的起始地址,它可以有两种格式:起始地址值或偏移量。 attribute 表示本输出段的属性,其可能的取值如下所示: o PI 位置无关属性 o RELOC 重定位 o ABSOLUTE 绝对地址 o FIXED 固定地址 o UNINIT 未初始化的数据 max_size 指定本输出段的最大尺寸。 输入段的描述 输入段里描述了一个文本字符串的模式,匹配该模式的输入段都将被包含在当前域中。模式中可以使用匹配符,符号*代表零个或者多个字符,符号?代表单个字符。进行匹配时,所有字符是大小写无关的。 下面介绍一些使用scatter文件配置映像文件地址映射模式的例子。在本例中,映像文件包括一个加载时域和3个连续的输出段,这种模式适合于那些将其他程序加载到RAM中的程序,如操作系统的引导程序和Angel等。 例子 一个简单的scatter文件 Load_1 0x4000 ;定义加载时域的名称为Load_1,起始地址为0x4000 ER_RO + 0 ;输出段名ER_RO,地址偏移量0,所以起始地址为0x4000 *( + RO) ;通配符*,包含了所有的RO属性的输入段,它们被连续放置 ER_RW + 0 ;输出段名称ER_RW,起始地址为前一个输出段的结束地址加偏移量0 *( + RW) ;本输出段包含所有的RW属性的输入段,它们被连续放置ER_ZI 0x5000 ;输出段名称ER_ZI,起始地址为0x5000 *( + ZI) ;本输出段包含了所有的ZI属性的输入段,它们被连续放置 按照例 scatter文件的描述,ARM链接器会生成相应的映像文件地址映射关系,如图2所示。图2 程序运行时地址映射关系2、固定时域 任何一个映像文件都需要指定一个初始入口点(initial entry point),它是影响文件运行时的入口点。初始入口点必须位于一个固定域中,所谓固定域是指该域的加载时地址和运行时地址是相同的。如果初始入口点不是位于一个固定域中,ARM链接器在链接时会产生下面的错误信息。 L6203E:Entry point (0x0000 0000) lies within non-root region 32 bit RAM 使用scatter文件时,可以有下面两种方法来设置固定域。 设置输出段地址 第1种方法是设定一个加载域中第1个输出段的运行地址,使其和该加载域的加载地址相同。这样该输出段就是一个固定域。 例1就使用这种方法确定固定域。其中,加载域LR_1的起始地址为0x8000,输出段ER_RO的起始地址指定为0x8000,与加载域LR_1的起始地址相同,因此,输出段ER_RO是一个固定域,并且是映像文件的初始入口点。 例1 指定固定域LR_1 0x08000 ;加载域LR_1的起始地址为0x8000 ER_RO 0x08000 ;输出段ER_RO的起始地址为0x8000 *( + RO);包含了所有的RO数据,包含初始入口点 ;其他部分内容 设置输出段属性 第2种方法通过将某个输出段的属性设置成FIXED。 例2指定固定域LR_1 0x8000 ;加载时域LR_1的起始地址为0x8000 ER_RO 0x8000 *( + RO) ;除了init.o之外的其他RO数据 ER_INIT 0x9000 FIXED ;设置输出段属性为FIXED,确定固定域 init.o( + RO);本输出段包含了init.o,包含映像文件的初始入口点 ;其他部分内容3、一个实际系统的例子 在一个嵌入式设备中,为了保持好的性价比,通常在系统中存在多种存储器。在一个实际的ARM开发板中,可能包括片内Flash、RAM和片外Flash、RAM。在本例中,我们假设用ARM芯片构造了一个嵌入式系统,包含了8KB片内Flash存储器、16KB片内RAM存储器、起始地址为0x80000000的片外Flash和起始地址为0x81000000的片外RAM,其地址空间分配关系如图3所示。 在这样的ARM系统中,我们编写了程序,并且按照例3中的分散加载文件对映象文件的地址进行分配。分配后的地址映像关系如图4所示。 图3 ARM系统中的地址空间 图4 地址映像关系 从图4中可以看出:可执行代码都放在片外Flash中,并且Vectors向量表放在片外Flash的起始地址上;Startup目标文件的数据放置在片内RAM中,堆栈放在片内RAM的顶端;其他数据放置在片外RAM中,堆空间紧跟其后。 例3 片外Flash启动程序的scatter文件ROM_LOAD 0x80000000 ;定义加载区名称ROM_LOAD,起始地址0x80000000 ROM_EXE 0x80000000 ;定义执行代码空间,起始地址与加载域地址相同 Startup.o (vectors, +First) ;首先放置Startup.o文件的向量表vectors * ( +RO) ;后面地址空间放置其他RO属性代码 IRAM 0x40000000 ;定义数据空间 Startup.o ( +RW, +ZI) STACKS 0x40004000 UNINIT ;定义堆栈空间 stack.o ( +ZI) ERAM 0x81000000 ;定义数据空间 * ( +RW, +ZI) ;剩下未指定空间的所有数据 HEAP + 0 UNINIT ;定义堆空间 heap.o ( +ZI) armlink中的scatter fileScatter file (分散加载描述文件)用于armlink的输入参数,他指定映像文件内部各区域的download与运行时位置。Armlink将会根据scatter file生成一些区域相关的符号,他们是全局的供用户建立运行时环境时使用。 (注意:当使用了scatter file 时将不会生成以下符号: Image$RW$Base, Image$RW$Limit, Image$RO$Base, Image$RO$Limit, Image$ZI$Base, Image$ZI$Limit) 二 什么时候使用scatter file 当然首要的条件是你在利用ADS进行项目开发,下面我们看看更具体的一些情况。 1 存在复杂的地址映射:例如代码和数据需要分开放在在多个区域。 2 存在多种存储器类型:例如包含 Flash,ROM,SDRAM,快速SRAM。我们根据代码与数据的特性把他们放在不同的存储器中,比如中断处理部分放在快速SRAM内部来提高响应速度,而把不常用到的代码放到速度比较慢的Flash内。 3 函数的地址固定定位:可以利用Scatter file实现把某个函数放在固定地址,而不管其应用程序是否已经改变或重新编译。 4 利用符号确定堆与堆栈: 5 内存映射的IO:采用scatter file可以实现把某个数据段放在精确的地指处。 因此对于嵌入式系统来说scatter file是必不可少的,因为嵌入式系统采用了ROM,RAM,和内存映射的IO。 三 scatter file 实例 1 简单的内存映射 LOAD_ROM 0x0000 0x8000 EXEC_ROM 0x0000 0x8000 *(+RO) RAM 0x10000 0x6000 *(+RW, +ZI) LOAD_ROM(下载区域名称) 0x0000(下载区域起始地址) 0x8000(下载区域最大字节数) EXEC_ROM(第一执行区域名称) 0x0000(第一执行区域起始地址) 0x8000(第一执行区域最大字节数) *(+RO(代码与只读数据) RAM(第二执行区域名称) 0x10000(第二执行区域起始地址) 0x6000(第二执行区域最大字节数) *(+RW(读写变量), +ZI(未初始化变量) 2 复杂内存映射 LOAD_ROM_1 0x0000 EXEC_ROM_1 0x0000 program1.o(+RO) DRAM 0x18000 0x8000 program1.o (+RW, +ZI) LOAD_ROM_2 0x4000 EXEC_ROM_2 0x4000 program2.o(+RO) SRAM 0x8000 0x8000 program2.o (+RW, +ZI) LOAD_ROM_1 0x0000(下载区域一起始地址) EXEC_ROM_1 0x0000(第一执行区域开始地址) program1.o(+RO) (program1.o内的Code与RO data 放在第一执行区域) DRAM 0x18000(第二执行区域开始地址) 0x8000(第二执行区域最大字节数) program1.o (+RW, +ZI) (program1.o内的RW data与 ZI data 放在第二执行区域) LOAD_ROM_2 0x4000(下载区域二起始地址) EXEC_ROM_2 0x4000 program2.o(+RO) (program2.o内的Code与RO data 放在第一执行区域) SRAM 0x8000 0x8000 program2.o (+RW, +ZI) (program2.o内的RW data与 ZI data 放在第二执行区域) 2.1 BNF 符号与语法 :由引号赖标示的符号保持其字面原意,如A”+”B标示A+B。 A := B :定义A为B。 A:标示可选部分,如ABC用来标示ABC或AC。 A+:用来标示A可以重复任意次,如A+可标示A,AA,AAA, A*:同A+。 A | B:用来标示选择其一,不能全选。如A|B用来标示A或者B。 (A B):标示一个整体,当和|符号或复杂符号的多次重复一起使用时尤其强大,如(AB)+(C|D)标示ABC,ABD,ABABC,ABABD, 2.2分散加载文件各部分描述 (2.1) 如图2.1所示为一个完整的分散加载脚本描述结构图。下面我们对图示中各个部分进行讲述。 2.2.1 加载区描述 每个加载区有: 名称:供连接器确定不同下载区域 基地址:相对或绝对地址 属性:可选 最大字节数:可选 执行区域列:确定执行时各执行区域的类型与位置 load_region_name (base_address | (+ offset) attribute_list max_size execution_region_description+ load_region_name:下载区域名称,最大有效字符数31。(并不像执行区域段名用于Load$region_name,而是仅仅用于标示下载区域)。 base_address:本区域内部目标被连接到的地址(按字对齐)。 +offset:相对前一个下载区域的偏移量(4的整数倍,如果为第一个区域)。 2.2.2 执行区描述 每个执行区有: 名称:供连接器确定不同下载区域 基地址:相对或绝对地址 属性:确定执行区域的属性 最大字节数:可选 输入段:确定放在该执行区域的模块 exec_region_name (base_address | + offset) attribute_list max_size input_section_description+ exec_region_name:执行区域名称,最大有效字符数31。 base_address:本执行区域目标要被联接到的位置,按字对齐。 +offset:相对于前一个执行区域结束地址的偏移量,4的整数倍;如果没有前继之能够行区域(本执行区域为该下载区域的第一个执行区域),则该偏移量是相对于该下载区域的基址偏移量。 attribute_list:PI,OVERLAY,ABSOLUTE,FIXED,UNINIT。 PI: 位置独立。 OVERLAY: 覆盖。 ABSOLUTE: 绝对地址。 FIXED: 固定地址,下载地址与执行地址具有该地址指示确定。 UNINIT: 未初始化数据。 RELOC:无法明确指定执行区域具有该属性,而只能通过继承前一个执行区或父区域获得。 对于PI,OVERLAY,ABSOLUTE,FIXED,我们只能选择一个,缺省属性为ABSOLUTE。一个执行区域要么直接继承其前面的执行区域的属性或者具有属性为ABSOLUTE。 具有PI,OVERLAY,RELOC属性的执行区域允许其地址空间重叠,对于BSOLUTE,FIXED 属性执行区域地址空间重叠Armlink会报错。 max_size:可选,他用于指使Armlink在实际分配空间大于指定值时报错。 input_section_description:指示输入段的内容。 基本语法2 2.2.3 输入段描述 输入段: 模块名:目标文件名,库成员名,库文件名。名称可以使用通配符。 输入段名,或输入段属性(READ-ONLY,CODE)。 module_select_pattern ( (+ input_section_attr | input_section_pattern) (, + input_section_attr | , input_section_pattern)* ) 2.2.3.1 module_select_pattern:选择的模块名称(目标文件,库文件成员,库文件),模块名可以使用通配符(*匹配任意多个字符,?匹配任意一个字符),名称不区分字母大小写,它是供选择的样本。 例1:*libtx.a (+RO) libtx.a为threadX库文件。 例2:tx_ill.o (INIT) tx_ill.o为threadX中断向量目标文件。 2.2.3.2 input_section_attr:输入段属性选择子,每个选择子以”+”开头,选择子不区分大小写字符。 选择子可选: RO-CODE, RO-DATA, RO( selects both RO-CODE and RO-DATA), RW-DATA, RW-CODE, RW( selects both RW-CODE and RW-DATA), ZI, ENTRY( that is a section containing an ENTRY point)。 以下同义词可以选择: CODE (for RO-CODE), CONST( for RO-DATA), TEXT (for RO), DATA (for RW), BSS (for ZI)。 还有两个伪属性:FIRST,LAST。如果各段的先后顺序比较重要时,可以使用FIRST,LAST标示一个执行区域的第一个和最后一个段。 例1:os_main_init.o (INIT ,+FIRST) FIRST表示放于本执行区域的开始处。 例2:*libtx.a (+RO) RO 表示*libtx.a的只读部分。 2.2.3.3 input_section_pattern:输入段名。 例1:os_main_init.o (INIT ,+FIRST) INIT 为os_main_init.o的一个段。 例2:os_stackheap.o (heap) heap 为os_stackheap.o的一个段。 例3:os_stackheap.o (stack) stack为os_stackheap.o的一个段。 提高篇 3.1 在scatter file中指定胶合段 胶合段用于实现ARM代码到Thumb代码的切换或者实现代码的长转移。使用scatter file可以指定怎样放置胶合输入段。通常,在scatter file中一个执行区域可以拥有胶合段选择*(Venner$Code)。 Armlink把胶合输入段放到拥有段选择符*(Veneer$Code)的执行区域中,这样做是安全的。 可能由于地址范围问题或者受执行区域大小限制无法完成把胶合段分配个某个执行区域。如果当发生胶合段无法加到指定区域时,他将会被加到那些包含了生成胶合段的可重载输入段的执行区域。 3.2 创建根执行区域 根执行区域就是指那些执行与加载时地址相同的区域。 当你为映像文件指定初始化入口点或者由于你只使用一个ENTRY导向符而使得连接器创建初始化入口位置时,你就必须确保该入口点位于根执行区域。如果入口点不在根执行区域,连接将会失败,连接器会报错。 如:ENTRY point (0x00000000) lies within non-root region ER_ROM 可以通过以下方式实现在scatter file中指定根执行区域。 显示或缺省的指定执行区的属性为ABSOLUTE,同时使得加载区域与第一个执行区域具有相同的地址。 使用FIXED属性使得执行区域的加载地址与其执行时地址保持不变。 3.3 创建根执行区域 可以通过在scatter file中为某个执行区域指定FIXED属性来实现该区域加载于运行时地址保持不变。 FIXED可以用来在一个加载区中创建多个根执行区域。因此我们可以通过它实现把某个函数或一段数据放到目标地址,从而可以通过指针方便地访问该地址。比如,我们可以实现把常量表和checksum放到ROM上的固定地址处。 注意: 为了使得代码更加易于维护和调试,请尽量少使用scatter file来指定放置位置,而是应该尽可能多地让连接器来确定函数和数据的位置。 3.3.1 怎样把函数或数据放到指定地址 通常,编译器处理来自单个源文件的RO,RW,和ZI段。这些区域包括源文件的代码与数据。如果打算把单个函数或数据项放到某个固定地址,我们就必须让编译器单独处理这些函数和数据。 我么可以通过以下方式处理单个目标: 把函数和数据放到其源文件。 使用编译选项 zo为每个函数单独生成一个目标文件。(参看ARM Compiler Guide) 在C,C+源文件内利用 #pragma arm section 来生成多命名段。 在汇编源文件内利用AREA 导向符来生成可重载段。 3.3.2 怎样放置单个目标文件的内容 3.3.3 怎样使用ARM的 section pragma 通常把函数和数据放到其源代码文件,然后放到其目标文件的相应段中。然而,我们也可以#pragma 和scatter file实现单独处理某个命名段。 / file adder.c int x1 = 5; / in.data int y1100; / in.bss int const z13 = 1,2,3; / in.constdata int sub1(int x) / in.text return x-1; #pragma arm section rwdata = foo, code =foo int x2 = 5; / in foo (data part of region) char *s3 = abc; / s3 in foo, abc in .constdata int add1(int x) return x+1; / in foo (.text part of region) #pragma arm section code, rwdata / return to default placement FLASH 0x24000000 0x4000000 FLASH 0x24000000 0x4000000 init.o (Init, +First) ;place code from init.o first * (+RO) ;sub1(), z1 32bitRAM 0x0000 vectors.o (Vect, +First) * (+RW,+ZI) ;x1, y1 ADDER 0x08000000 adder.o (foo) ;x2, string s3, and add1() Scatterfile讲解(转) 零零散散的看了不少关于分散加载文件的文章,感觉大家好像都不是很明白。今天总结一下,虽不算全面,但希望能为后来者带来帮助! 分散加载(Scatlerloading),即工程里的.scf文件。在scatterfile中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,Scatlertoading的存储区块可以分成二种类型: 装载区:当系统启动或加载时应用程序的存放区。 执行区:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。 映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。1.scatter文件语法: scatter文件是一个简单的文本文件,包含一些简单的语法。My Region 0x0000 0x1000 ;the context of region 标题: 每个块由一个头标题开始定义,头中至少包含块的名字(自己定义)和起始地址,如0x0000,另外还有最大长度等其他一些属性选项(注:这些属性是可选的,如0x1000)内容: 块定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。 一个加载块(加载时域)必须至少含有一个执行块(运行时域);实践中通常有多个执行块。 一个执行块必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。2.分散加载样例分析: 这里用周立功的开发板附带例程里的分散加载文件做例子进行讲解。 硬件配置: 内部 64K RAM: 0x4000 0000 - 0x4000 ffff 外部 2M FLASH:0x8000 0000 - 0x801f ffff 外部 8M RAM: 0x8100 0000 - 0x807f ffffROM_LOAD 0x80000000 ;加载时域描述 ROM_EXEC 0x80000000 ;第一个运行时域描述 Startup.o (vectors, +First) ;输入段描述:模块startup位于该 ;域的开头(+First),vector为入口点 * (+RO) ;本域包含全部RO代码(*(+RO)) IRAM 0x40000000 ;第二个运行时域:将堆栈空间放入 ;片内静态RAM中(0x40000000) Startup.o (MyStacks) ;本域包含模块STARTUP 的MYSTACKS段 STACKS_BOTTOM +0 UNINIT ;将栈底放在堆栈的后面(+0) ;不进行初始化(UNINIT) Startup.o (StackBottom) STACKS 0x40004000 UNINIT ;将STACKS放入40004000 此处地址不能访问 ;如访问将产生预取中止和数据中止异常 Startup.o (Stacks) ERAM 0x81000000 ;将所有RWZI(*(+RW,+ZI))段放入外部RAM中 * (+RW,+ZI) HEAP +0 UNINIT ;在RWZI段后放入堆底 Startup.o (Heap) HEAP_BOTTOM 0x81080000 UNINIT Startup.o (HeapTop) ;堆顶:放入了外部RAM中(0x81080000) (1)样例中,只有一个加载块ROM_LOAD,包含了所有的代码和数据(存放在ROM),起始地址为0x800000000。这个加载块一共对应七个执行块(ROM_EXEC, IRAM,STACKS_BOTTOM, STAKS,ERAM,HEAP,HEAP_BOTTOM)。(2)RO的代码和数据会从ROM_EXEC开始执行,执行地址与装载地址相同。(3)Startup.o是Startup.s的目标文件(Startup.s也在这个工程下),vectors是在Startup.s定义的段,整个句子的意思是把整个Startup.s编译生成的目标文件(向量表)放在0x8000 0000的第一个位置,即从vect

温馨提示

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

评论

0/150

提交评论