keil分散加载文件浅释

keil分散加载文件浅释
keil分散加载文件浅释

分散加载

ARM处理器的分散加载及特殊应用研究 摘要从ARM ELF目标文件主要构成出发,详细介绍了分散加载的基本原理、分散加载文件的语法、分散加载时连接器生成的预定义符号及要重新实现的函数等;以定位目标外设和定义超大型结构体数组两项应用来加以说明,并给出完整的工程实例和Bootloader代码。这些都已经在实际工程中多次应用和验证,是笔者实际工程项目的萃取。 关键词分散加载嵌入式系统 Scatter Loading Bootloader ARM ELF 引言 在当今的嵌入式系统设计中,ARM处理器以价格便宜、功耗低、集成度高、外设资源丰富和易于使用的特点而得到广泛的应用;在速度和性能方面已达到或超过部分PC104嵌入式计算机的性能,而成本却比相应的PC104计算机低很多,广泛应用于手机、GPS接收机、地图导航、路由器、以太网交换机及其他民用和工业电子设备。 在一个采用ARM处理器的实时嵌入式系统中,目标硬件常常由Flash、SRAM、SDRAM和NVRAM(非易失性RAM)等存储器组成,并定位于不同的物理地址范围,那么,怎样通过软件更好地访问和利用这些不同的存储器并让系统高效地运行?分散加载(scatter loading)就提供了这样一种机制。它可以将内存变量定位于不同的物理地址上的存储器或端口,通过访问内存变量即可达到访问外部存储器或外设的目的;同时通过分散加载,让大多数程序代码在高速的内部RAM中运行,从而使得系统的实时性大大增强。 1 ARM ELF目标文件的主要构成 ARM ELF(Executable and Linking Format)目标文件主要由.Text段、.Data 段、.BSS段构成,其他段如.debug段、.comment段等与本文关系不大,不作介绍。 .Text段由可执行代码组成,段类型为Code,属性为RO; .Data段由已初始化数据组成,段类型为Data,属性为RO; .BSS段由未初始化数据组成,段类型为Zero,属性为RW,在应用程序启动时对该段的数据初始化为零。如果在分散加载文件中指定了UNINIT属性,则在应用程序启动时不初始化该段。 2 分散加载的基本原理 假设一个采用ARM处理器的实时嵌入式系统目标硬件的存储器由ROM存储器和RAM存储器组成。当一个嵌入式系统在仿真环境下调试完毕,需要脱机运行的时候,就需要将源程序编译连接成可执行目标代码并烧写到ROM存储器中。由于ROM存储器存取数据的速率比RAM存储器慢,因此,让程序在ROM存储器中运行。CPU每次取指令和取数据操作都要访问ROM存储器,这样需要在CPU的总线周期中插入等待周期,通过降低总线的速率来满足访问慢速的ROM存储器,这样势必会降低CPU的运行速率和效率,因此,分散加载就显得非常必要。

在RealView MDK中使用J-Link对STM32F130ZET6外部Nor Flash烧写的方法

在RealView MDK中使用J-Link对STM32F130ZET6外部Nor Flash烧写的方法by 314forever 文章中以STM32F103ZET6外接SST39VF6401B为例,在红牛实验板上操作成功。图例中用到的地址需要根据你自己的情况作相应调整。 新建一个工作目录。将x:\Keil\ARM\Flash\STM32F10x\下的所有文件拷进来,将x:\Keil\ARM\Flash\SST39x640x\下的FlashPrg.c文件拷进来并覆盖同名文件,将x:\Keil\ARM\Flash\下的FlashOS.h文件拷进来。如果你使用的Nor Flash 不在MDK自带驱动的范围内,那么需要根据FlashPrg.c文件自行编写相关函数 打开工程STM32Fx,在FlashDev.c中添加如下代码,有关这段代码请参考x:\Keil\ARM\Flash\SST39x640x\FlashDev.c 修改FlashDev.c和FlashPrg.c中的头文件引用 在目标属性中修改宏定义和输出文件

编译此工程,将得到的STM32F10x_NOR.FLM文件拷入x:\Keil\ARM\Flash\文件夹中。然后在MDK的Flash下载设置中就出现了NOR Flash的选项 这样我们就得到了MDK对Nor Flash的接口文件,接下来是如何在工程中将数据弄到Nor Flash上。 新建工程,将要烧入Nor Flash中的数据单独存放在一个文件中

然后自定义分散加载文件 在这里把数据定义到Nor Flash中,注意地址要根据你自己的情况来设置 在程序中要对数据进行使用,否则编译后未用到的数据可能会被优化掉 编译结果 添加Flash烧写算法,MDK会根据不同的地址采用不同的算法

ARM伪指令详述

1、AREA 语法格式: AREA 段名属性1,属性2,…… AREA伪指令用于定义一个代码段或数据段。其中,段名若以数字开头,则该段名需用―|‖括起来,如|1_test|。 属性字段表示该代码段(或数据段)的相关属性,多个属性用逗号分隔。常用的属性如下:— CODE属性:用于定义代码段,默认为READONL Y。 — DATA属性:用于定义数据段,默认为READWRITE。 — READONL Y属性:指定本段为只读,代码段默认为READONL Y。 — READWRITE属性:指定本段为可读可写,数据段的默认属性为READWRITE。—ALIGN属性:使用方式为ALIGN 表达式。在默认时,ELF(可执行连接文件)的代码段和数据段是按字对齐的,表达式的取值范围为0~31,相应的对齐方式为2表达式次方。—COMMON属性:该属性定义一个通用的段,不包含任何的用户代码和数据。各源文件中同名的COMMON段共享同一段存储单元。 一个汇编语言程序至少要包含一个段,当程序太长时,也可以将程序分为多个代码段和数据段。 使用示例: AREA Init,CODE,READONL Y 指令序列 ;该伪指令定义了一个代码段,段名为Init,属性为只读 2、ALIGN 语法格式: ALIGN {表达式{,偏移量}} ALIGN伪指令可通过添加填充字节的方式,使当前位置满足一定的对其方式|。其中,表达式的值用于指定对齐方式,可能的取值为2的幂,如1、2、4、8、16等。若未指定表达式,则将当前位置对齐到下一个字的位置。偏移量也为一个数字表达式,若使用该字段,则当前位置的对齐方式为:2的表达式次幂+偏移量。 使用示例: AREA Init,CODE,READONL Y,ALIEN=3 ;指定后面的指令为8字节对齐。 指令序列 END 3、CODE16、CODE32 语法格式: CODE16(或CODE32) CODE16伪指令通知编译器,其后的指令序列为16位的Thumb指令。 CODE32伪指令通知编译器,其后的指令序列为32位的ARM指令。 若在汇编源程序中同时包含ARM指令和Thumb指令时,可用CODE16伪指令通知编译器其后的指令序列为16位的Thumb指令,CODE32 伪指令通知编译器其后的指令序列为32位的ARM指令。因此,在使用ARM指令和Thumb指令混合编程的代码里,可用这两条伪指令进行切换,但注意他们只通知编译器其后指令的类型,并不能对处理器进行状态的切换。使用示例: AREA Init,CODE,READONL Y …… CODE32 ;通知编译器其后的指令为32位的ARM指令

M0系列ARM芯片的启动程序分解

周立功NXP LPC21xx/22xx 系列ARM 芯片的启动程序分解 作者:钟常慰 关于LPC2200 启动程序分散加载描述文件的叙述 在ADS LPC2200 的启动模板中有一个scf 文件夹,其中有mem_a.scf、mem_b.scf、mem_c.scf 这3 个文件,这3 个文件是ADS 的 分散加载机制,其目的是将代码段和数据段分别定位到指定地址上。可以在Arm Linker 中选择加载路径。分散装载技术概述: 分散装载技术可以把用户的应用程序分割成多个RO(只读)运行域和RW(可读写)运行域(一个存储区域块),并且给它们制定不同的 地址。一个嵌入式系统中,Flash、16 位RAM、32 位RAM 都可以存在于系统中,所以,将不同功能的代码定位在特定的位置会大大地提 高系统的运行效率。下面是最为常用的2 种情况: 1、32 位的RAM 运行速度很快,因此就把中断服务程序作为一个单独的运行域,放在32 位的RAM,使它的响应时间达到最快。 2、程序在RAM 中运行,其效率要远远高于在ROM 中运行,所以将启动代码(Boot loader)以外的所有代码都复制在RAM 中运行, 可以提高运行效率。 分散装载技术主要完成了2 个基本的功能: 如何分散。就是如何将输入段组成输出段和域。 如何装载。就是确定装载域和运行域在存储空间里的地址是多少。 域可以分为装载域和运行域 装载域描述运行前输出段和域在ROM/RAM 里的分布状态,运行域描述了运行时输出段和域在ROM/RAM 里的分布状态。大多数情况下, 映像文件在执行前把它装载到ROM 里,而当运行时,域里的有些输出段(比如RW 类型的输出段)必须复制到RAM 里,程序才能正常运行, 所以,在装载和运行时,RW 类的输出段处在不同的位置(地址空间)。 Scatterfile 分散加载文件: 在scatterfile 中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,Scatlertoading 的存储区块可以分成二种类 型: 装载区:当系统启动或加载时应用程序的存放区。 执行区:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。 映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。scatter 文件语法 scatter 文件是一个简单的文本文件,包含一些简单的语法。 My Region 0x0000 0x1000 ;我的名字My Region 起始地址0x0000 属性0x1000 { ;the context of region 这个域的范围 } 标题

ARM——分散加载描述文件

ARM——分散加载描述文件 分散加载的实现(scatter) 很多朋友对分散加载不是很理解,其实它的原来很简单,这些加载的原理都源自生活。 由于现在的嵌入式技术发展比较快,各类存储器也层出不穷,但是它们在容量、成本和速度上有所差异,嵌入式系统又对成本比较敏感,那么合理的选择存储器和充分的利用存储器资源成为一个必要解决的问题。咋们工程师最喜欢的就是发掘问题,然后解决问题,基于嵌入式系统对存储器的敏感,那么要合理的利用存储器资源,就必须找到一种合理的方式。工程师们发现,可以把运行的程序放在不同成本的存储器中来寻找这个成本的支点,比如把没有运行的但是较为庞大的程序放在容量大、成本低、速度也较低的FLASH存储器中,要用的时候再去拿。但是,这里面又有一个问题,嵌入式本身就对信号的处理速度有较高的要求,这点在实时操作系统的定义上上有所体现。所以那些经常要用的程序段如果要保证其高速的运行那么就得放在一个在高速的存储器中,不过这是有代价的:较高成本,小容量。但是,相信由于技术的发展这个问题终将被解决,到时候寻找平衡点的问题也就不存在了。好了,说了多了点。切入正题。 程序总有两种状态:运行态和静止态。当系统掉电的时候程序需要被保存在非易失性的存储器中,且这个时候程序的排放是按照地址依次放的,换句话说:我才懒得管它怎么放,只要不掉就行。当系统上电后,CPU就要跑起来了,CPU 属于高速器件,存储器总是不怎么能跟得上,既然跟不上那么我们就尽量缩短它们之间的差距,那留下一条路,那就是尽量提高存储器的读取速度,存储器类型决定其速度的水平,那么尽量放在速度高的存储器就成为首选解决方案。那么我们就把要执行的程序暂时拿到速度较快的RAM中。那么拿的过程就牵涉到程序的加载了。这就是要解决的问题。 一个映像文件由域(region)、输出段(output sections)和输入段(input sections)组成。不要想得太复杂,其实他们之间就是包含与被包好的关系。具体关系是这样的: 映像文件>域>输出段>输入段 输入段: 输入段就是我们写的代码+初始化的数据+应该被初始化为0的数据+没有初始化的数据,用英文表示一下就是:RO(ReadOnly),RW (ReadWrite),ZI (ZeroInitialized),NOINIT(Not Initialized)。ARM连接器根据各个输入段不同的属性把相同的拿再一起组合一下就成为了输出段。 请看看平时写的东东: AREA RESET, CODE, READONLY AREA DSEG1, DATA, READWRITE AREA HEAP, NOINIT, READWRITE 看出其属性没? 输出段: 为了简化编译过程和更容易取得各种段的地址,那么把多个同属性的输入段按照一定的规律组合在一起,当然这个输出段的属性就和它包含的输入段的属性

ScatterFile分散加载文件及其应用

分散加载文件及其应用 分散加载能够将加载和运行时存储器中的代码和数据描述在被称为分散加载描述文件的一个文本描述文件中,以供连接时使用。 (1)分散加载区 分散加载区域分为两类: ? 加载区,包含应用程序复位和加载时的代码和数据。 ? 执行区,包含应用程序执行时的代码和数据。应用程序启动过程中,从每个加载区可创建一个或多个执行区。 映象中所有的代码和数据准确地分为一个加载区和一个执行区。 (2)分散加载文件示例 ROM_LOAD 0x0000 0x4000 { ROM_EXEC 0x0000 0x4000; Root region { * (+RO); All code and constant data } RAM 0x10000 0x8000 { * (+RW, +ZI); All non-constant data } }

(3)分散加载文件语法 load_region_name start_address | "+"offset [attributes] [max_size] { execution_region_name start_address | "+"offset [attributes][max_size] { module_select_pattern ["(" ("+" input_section_attr | input_section_pattern) ([","] "+" input_section_attr | "," input_section_pattern)) * ")"] } } load_region:加载区,用来保存永久性数据(程序和只读变量)的区域;execution_region:执行区,程序执行时,从加载区域将数据复制到相应执行区后才能被正确执行; load_region_name:加载区域名,用于“Linker”区别不同的加载区域,最多31个字符;start_address:起始地址,指示区域的首地址; +offset:前一个加载区域尾地址+offset 做为当前的起始地址,且“offset”应为“0”或“4”的倍数; attributes:区域属性,可设置如下属性: PI 与地址无关方式存放; RELOC 重新部署,保留定位信息,以便重新定位该段到新的执行区; OVERLAY 覆盖,允许多个可执行区域在同一个地址,ADS不支持; ABSOLUTE 绝对地址(默认); max_size:该区域的大小; execution_region_name:执行区域名; start_address:该执行区的首地址,必须字对齐; +offset:同上; attributes:同上; PI 与地址无关,该区域的代码可任意移动后执行; OVERLAY 覆盖; ABSOLUTE 绝对地址(默认); FIXED 固定地址; UNINIT 不用初始化该区域的ZI段; module_select_pattern:目标文件滤波器,支持通配符“*”和“?”; *.o匹配所有目标,* (或“.ANY”)匹配所有目标文件和库。 input_section_attr:每个input_section_attr必须跟随在“+”后;且大小写不敏感; RO-CODE 或CODE RO-DATA 或CONST RO或TEXT, selects both RO-CODE and RO-DATA RW-DATA RW-CODE RW 或DATA, selects both RW-CODE and RW-DATA ZI 或BSS

分散加载描述文件

7.5 分散加载描述文件 在7.3节中已经简单介绍了映像的组成,也介绍了如何用命令选项来构建简单结构的映像。要构建映像的存储器映射,链接器必须有:描述节如何分组成区的分组信息、描述映像区在存储器映射中的放置地址的放置信息。 分散加载机制允许为链接器指定映像的存储器映射信息,可实现对映像组件分组和布局的全面控制。分散加载通常仅用于具有复杂存储器映射的映像(尽管也可用于简单映像),也就是适合加载和执行时内存映射中的多个区是分散的情况。本节将对armlink所使用的分散加载描述文件作详细介绍。 7.5.1 分散加载机制 7.5.1.1 何时使用分散加载机制 链接命令行选项提供了一些对数据和代码布局的控制,但如果要对布局进行全面控制则需要比命令行选项更详细的指令。对于以下一些情况,就需要或最好使用分散加载描述文件: 复杂存储器映射:代码和数据需要放在多个不同存储器区域,必须详细指明哪个节放在哪个存储器空间。 不同存储器类型:许多系统包含FLASH、ROM、SDRAM和快速SRAM。利用分散加载可将代码和数据放置在最适合的存储器类型中。例如,中断代码可能放在快 速SRAM中,以改进中断响应时间,而将不频繁使用的配置信息可能放在较慢的 FLASH中。 存储器映射I/O:分散加载机制可将数据节精确放在存储器的某个地址,便于访问外设映射内存。 固定位置的函数:可以将函数放在存储器中的一个固定位置,即使周围的应用程序已经被修改并重新编译。 使用符号识别堆和栈:链接程序时,分散加载机制可为堆和栈的位置定义符号。 在实现嵌入式系统时,通常会需要使用分散加载机制,因为这些系统一般都会使用ROM、RAM和存储器映射I/O。 注意,如果为Cortex-M3结构的处理器编译程序,此处理器结构有着一个固定的内存映射,可以使用分散加载文件来定义栈和堆。 链接时如要使用分散加载文件,则需使用链接命令选项--scatter description_file,详细内容参考7.2节。 7.5.1.2 为分散加载所定义的符号 当armlink使用分散加载描述文件创建映像时,它将创建一些区相关符号,在7.4节中已作详细介绍。仅当代码引用这些特殊符号时,链接器才创建它们。 当分散加载描述文件被使用时,7.4节中的符号Image$$RW$$Base、 Image$$RW$$Limit、Image$$RO$$Base、Image$$RO$$Limit、 Image$$ZI$$Base和Image$$ZI$$Limit不被定义。 若使用分散加载文件,但不指定任何区名并且不使用__user_initial_stackheap(),则库将生成一个错误信息。

M3启动文件.tmp

目录 第1章CMSIS标准 (1) 1.1 CMSIS标准简介 (1) 1.2 CMSIS标准的软件架构 (1) 1.3 CMSIS标准的文件结构 (2) 第2章注解startup.s文件(以startup_LPC17xx.s为例) (3) 2.1 堆栈以及堆的初始化 (3) 2.1.1 堆栈的初始化 (3) 2.1.2 堆的初始化 (3) 2.2 中断向量表的初始化 (4) 2.3 调用Reset Handler (5) 2.4 其他的代码 (5) 第3章ARM芯片的启动过程详解 (7) 3.1 ARM芯片的启动过程概述 (7) 3.2 结合代码来看ARM芯片的启动过程 (8) 3.2.1 调试环境的搭建及测试代码 (8) 3.2.2 跟踪启动代码 (8) 3.2.3 详细的启动过程 (9) 3.2.4 __main (10) 3.2.5 __rt_entry (10) 3.2.6 __rt_lib_init (11) 3.3 关于microlib (11) 3.4 x.map (11) 3.4.1 关于链接器 (12) 3.4.2 RW段在RAM的存放 (12) 3.5 关于ARM程序的Memory管理 (12) 3.5.1 ARM镜像文件的组成(image) (12) 3.5.2 关于image文件(镜像文件) (13) 3.5.3 RO段 (13) 3.5.4 RW段 (14) 3.5.5 ZI段(初始化为0或未初始化的变量) (15) 3.6 缺省内存映射 (16) 3.7 内存模型 (17) 第4章关于分散加载文件 (18) 4.1 什么时候使用分散加载文件 (18) 4.2 适用范围 (18) 4.3 再谈ARM Image(镜像文件) (18) 4.4 节放置 (19) 4.5 一个简单的加载过程 (20) 4.6 分散加载文件语法 (21) 4.6.1 加载时域(区)描述 (21) 4.6.2 运行时域(区)描述 (22) 4.6.3 输入段描述 (23)

STM32 分散加载文件

STM32 分散加载文件 IAP —MDK (2011-07-25 14:42:30) ; ************************************************************* ; *** Scatter-Loading Description File generated by uVision *** ; ************************************************************* LR_IROM1 0x08000000 0x00004000 ; load region size_region 第一个加载域,起始地址0x08000000,{ 大小0x00004000 ER_IROM1 0x08000000 0x00004000 ; load address = execution address 第一个运行时域, { 起始0x08000000,大小0x00004000 *.o (RESET, +First) IAP第一阶段还是在FLASH中运行 *(InRoot$$Sections) startup_stm32f10x_md.o } ER_IROM2 0x20008000 0x00004000 ; load address = execution address第二个运行时域, { 起始0x20008000,大小0x00004000 .ANY (+RO) IAP第二阶段加载到SDRAM中运行 } RW_IRAM1 0x20000000 0x00008000 ; RW data 把可读写的数据和初始化为0的数据放在内存SDRAM的开头 { .ANY (+RW +ZI) } } 做个比喻:就像一列火车在起始地址0x08000000装上大小0x00004000的货物,然后把特定的货物送到指定的地方拿下来运行或者存放。上面这辆火车就停了3个地方。 编译时出现一下警告: warning: L6314W: No section matches pattern address(RO). 在Target中的Linker中有一栏Misc controls,键入 --diag_suppress=L6314 即可,如下

STM32库开发实战指南-M4:49-在SRAM中调试代码

第49章在SRAM中调试代码 本章参考资料:《STM32F4xx中文参考手册》、《STM32F4xx规格书》、《Cortex-M3权威指南》、《Cortex-M4Technical Reference Manual》(跟M3大部分是相同的,读英文不习惯可先参考《Cortex-M3权威指南》)。 学习本章时,配合《STM32F4xx中文参考手册》“存储器和总线结构”及“嵌入式FLASH接口”章节一起阅读,效果会更佳,特别是涉及到寄存器说明的部分。 49.1在RAM中调试代码 一般情况下,我们在MDK中编写工程应用后,调试时都是把程序下载到芯片的内部FLASH运行测试的,代码的CODE及RW-data的内容被写入到内部FLASH中存储。但在某些应用场合下却不希望或不能修改内部FLASH的内容,这时就可以使用RAM调试功能了,它的本质是把原来存储在内部FLASH的代码(CODE及RW-data的内容)改为存储到 SRAM中(内部SRAM或外部SDRAM均可),芯片复位后从SRAM中加载代码并运行。 把代码下载到RAM中调试有如下优点: ?下载程序非常快。RAM存储器的写入速度比在内部FLASH中要快得多,且没有擦除过程,因此在RAM上调试程序时程序几乎是秒下的,对于需要频繁改动代 码的调试过程,能节约很多时间,省去了烦人的擦除与写入FLASH过程。另外, STM32的内部FLASH可擦除次数为1万次,虽然一般的调试过程都不会擦除这 么多次导致FLASH失效,但这确实也是一个考虑使用RAM的因素。 ?不改写内部FLASH的原有程序。 ?对于内部FLASH被锁定的芯片,可以把解锁程序下载到RAM上,进行解锁。 相对地,把代码下载到RAM中调试有如下缺点: ?存储在RAM上的程序掉电后会丢失,不能像FLASH那样保存。 ?若使用STM32的内部SRAM存储程序,程序的执行速度与在FLASH上执行速度无异,但SRAM空间较小。 ?若使用外部扩展的SDRAM存储程序,程序空间非常大,但STM32读取SDRAM的速度比读取内部FLASH慢,这会导致程序总执行时间增加,因此在 SDRAM中调试的程序无法完美仿真在内部FLASH运行时的环境。另外,由于 STM32无法直接从SDRAM中启动且应用程序复制到SDRAM的过程比较复杂 (下载程序前需要使STM32能正常控制SDRAM),所以在很少会在STM32的 SDRAM中调试程序。 49.2STM32的启动方式 在前面讲解的STM32启动代码章节了解到CM-4内核在离开复位状态后的工作过程如下,见图49-1:

ARM映像文件及其地址映射.

ARM映像文件及其地址映射 2010-06-24 14:16 1、什么是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 对应的是

为C++程序添加文件保存加载功能

为C++程序添加文件保存加载功能 一、引子 为什么要浪费时间去设计一个算法来实现数据的文件存储还要费劲地调试代码呢?Boost库可以为你做这些事情。借助于串行化模板,你可以容易地把数据存储到你自己定制格式的文件中。本文将教给你如何轻松地存储数据并回读数据。 二、概述 当你开发一个软件包时,你总是想集中精力于软件的功能。而最让你担心的是,花费大量的时间写代码,而该代码有可能会应用在另外大量的其他程序中。那正是重用的含义所在,你会希望另外某人已经为你编写出这样现成的代码。 这类问题的一个很好的例子是给予你的程序存档的能力。例如,你可能在写最伟大的天文学程序-在该程序中,你的用户可以轻易地输入时间和坐标,你的程序负责绘制当前天空的地图。但是,假定你赋予你的用户能够高亮某些星星,这样以来它们可以容易地突出在地图上。最后,你让用户能够保存他们的配置以备后用。 你的程序集中于天文学编程。你并不是在写一个通用库来保存文档,所以你不必把大量的时间花在存储功能上,因为你要专注于程序的天文学特性。如果你是用C++编程,你可以从Boost重用库得到帮助。为了保存文件,Boost库包括一个串行化类,正是你需要的。 如果你成功地创建了你的程序工程,很可能有一个类来包含用户信息或文档。例如,你可能有一个类,该类列举用户们最喜欢的星星的名字和位置。(请原谅这里的简化)。这就是你希望用户能够保存到磁盘上的数据。毕竟,几乎所有的程序都有文件保存功能。微软的Word保存文本和格式化数据,而Excel保存工作单数据。一个优秀的地图程序可以用户保存喜欢的位置,GPS路线,旅程,等等。 借助于Boost串行化库的帮助,实现保存很容易-所要做是仅仅是设置好你的类,而由库来负责其它一切-使你专注于真正的工作。 其思想是很简单的:你创建了一个包含用户数据的对象。当准备保存信息时,用户选择File|Save As,然后从文件对话框中选择一个文件名即可。借助于Boost,你的程序就把数据保存到选定的文件中。以后,当用户重新启动该程序时,选择File|Open,选定已保存的文件,你的程序再一次使用Boost-但是这一次重新装入数据,因此,重新产生了该对象。

stm32固件库函数使用keil时的常见错误分析

error: A1355U: A Label was found which was in no AREA 终级解决办法 分类:深入C语言2009-12-30 11:26208人阅读评论(0)收藏举报error: A1355U: A Label was found which was in no AREA 在KEIL工程中,我使用另一个工程中正确的分散加载文件到一个新工程中,竟然就出现这样的提示。 到网上搜索,有很多内容是关于这个问题的,但是却没有几个很好解决问题的。 其实出现这个问题有两种情况,一种是出现在.s的汇编文件中,另一种是出现在.scf (或者.scat)等的分散加载文件中。 原来很多人在汇编文件(多数为.s的启动代码)中出现这个问题的,基本上是因为使用汇编的格式不对, 关于这个错误,ARM官网有相关的说明: A1355U: A Label was found which was in no AREA Example: This can occur where no white-space precedes an assembler directive. Assembler directives must be indented with white-space, for example: use: IF :DEF: FOO ; code ENDIF not: IF :DEF: FOO ; code ENDIF Symbols in the left hand column 1 are assumed to be labels, hence the error message. 意思是在编写汇编文件时,标号要顶格写,而其他的代码都要用空格或者TAB键来使代码进行缩进,这样,就不会出现编译的问题了。 如果问题是出现在分散加载文件中,那么很可能你是把分散加载文件一起加入到了KEIL的工程中,类似这样: 这时候,就可能会出现 error: A1355U: A Label was found which was in no AREA这样的报错,不管你用多么正确的SCATTER文件格式,它始终都会报错。为什么呢? 原来我们通常加到KEIL工程中的.c ,.s, .h等文件是供ARMCC,ARMASM等编译器处理的,而分散加载文件 .scf ,.scat等文件是供ARMLINKER等连接器处理的,当我们把分散加载文件加入到工程中后,KEIL会调用ARMASM编译器将分散加载文件做为汇编文件去处理,因为分散加载文件本来就不是合法的汇编文件,所以在编译的时候就出现了编译错误的提示。 解决方法:在工程中删除分散加载文件,在option->linker->scatter file路径中指定即可,如图:

试图搞懂MDK程序下载到Flash(四)--生成bin文件下载到Nor Flash

试图搞懂MDK程序下载到Flash(四)--生成bin文件下载到Nor Flash 喜讯啊!!下载到flash中的一种实现了啊!!!鸡冻了!终于可以脱机运行了,尽管是下载到了Nor Flash中运行,还没有下载到Nand Flash中运行,但是这也是一个进步了吧,下面详细介绍一下MDK编译的程序下载到Nor Flash运行的步骤。 1、编写程序 我的主程序功能是实现UART的输出功能,工程文档结构图如下: 需要自己编写的文件有三个main.c uart.c uart.h,下面贴出这三个文件的实验代码:main.c文件 #include #include"uart.h" int main() { unsigned int a=10; //系统时钟初始化, FCLK=400MHz,HCLK=100MHz,PCLK=50MHz Uart0_Init(115200); //初始化并设置波特率为115 200 while(1) { Uart0_Printf("Uart0_Printf test output is:%d\n",a); } } uart.c文件

#include #include #include"uart.h" #define PCLK 50000000 #define UART_BRD (int)((PCLK/(baudrate*16))-1) /*********************************************** *函数名称:void Uart0_Init(unsigned int baudrate) *参数说明:baudrate:波特率 *返回值:无 *全局变量: 无 *功能:对UART0进行初始化 ************************************************/ void Uart0_Init(unsigned int baudrate) { GPHCON&=~((3<<4)|(3<<6)); //GPH2--TXD0;GPH3--RXD0 GPHCON|=((2<<4)|(2<<6)); //设置GPH2、GPH3为TXD0、RXD0功能 GPHUP=0x00; //上拉电阻使能 ULCON0|=0x03; //设置数据发送格式:8个数据位,1个停止位,无校验位 UCON0=0x05; //发送模式和接收模式都使用查询模式 UBRDIV0=UART_BRD; //设置波特率,其中波特率作为一个参数传递到该初始化函数 URXH0=0; //将URXH0清零 } /*********************************************** *函数名称:void putc(unsigned char c) *参数说明:c:通过串口接收到的字符,注意这里是8位数据 *返回值:无 *全局变量: 无 *功能:将通过串口接收到的字符发送给PC机并显示在 * 串口调试工具。 ************************************************/ void putc(unsigned char c) { UTXH0=c;

ARM7的Bootloader和分散加载文件笔记

Boot Loader概述 简单地说,在操作系统内核运行之前,通过一小程序,可以初始化硬件设备、建立内存空间的映射图等,从而将系统的软硬件环境带到一个合适的状态,以便为最终调用操作系统内核配置好相应的环境,也可以下载文件到系统板上的SDRAM,对Flash进行擦除与编程,这个小程序一般称为Boot Loader。可以说,一个功能完善的Boot Loader已经相当于一个微型的操作系统了。 Boot Loader作为系统复位或上电后首先运行的代码,一般应写入Flash存储器并从起始物理地址0x0开始。Boot Loader是非常依赖于硬件而实现的,而且根据实现的功能不同,其复杂程度也各不相同。一个简单的Boot Loader可以只完成USB口的初始化,而功能完善的Boot Loader可以支持比较复杂的命令集,对系统的软硬件资源进行合理的配置与管理。因此,建立一个通用的Boot Loader 几乎是不可能的。 系统初始化代码直接对ARM微处理器内核及硬件控制器编程,多采用汇编语言编程,初始化代码一般应包括如下典型任务: 1.定义程序入口点; 2.设置异常和中断向量表; 3.初始化存储设备; 4.初始化堆栈指针寄存器; 5.初始化用户执行环境; 6.呼叫主应用程序。 1.1 定义程序入口 初始化代码必须定义整个程序的入口点。通过伪指令Entry指定编译器保留该段代码,同时配合链接器的设置,确定整个程序的入口点。 1.2 设置异常和中断向量表 1.3初始化存储设备 1. 存储器类型和时序的配置 2.存储器的地址分配与地址重映射 一种典型的存储器地址重映射过程描述如下:当系统上电或复位以后,PC指针指向0x0,程序从0x0地址开始执行,因此,为了能正确读取代码,要求此时Flash (或其它类型的ROM)的起始地址为0x0。但Flash(或其它类型的ROM)的访问速度大大低于RAM,每次产生异常后,都要从Flash(或其它类型的ROM)的异常向量表调转到相应的处理程序,会影响异常的响应速度,因此,系统便提供一种灵活的地址重映射方法,在系统完成必要地初始化以后,将RAM安排到0x0 地址处,而将原来位于0x0处的Flash(或其它类型的ROM)安排到其他的地方上去,加快异常的响应速度。

Cortex-M3在MDK下汇编程序分散加载文件出错的解决方法

Cortex-M3在MDK下汇编程序分散加载文件出错的解决方法 1.对于汇编调试,不需要添加启动,仅设置堆栈即可 2.默认分散加载文件如下(LM3S615,其实其他也差不多,都是自动生成):LR_IROM1 0x00000000 0x00008000 { ; load region size_region ER_IROM1 0x00000000 0x00008000 { ; load address = execution address *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) } RW_IRAM1 0x20000000 0x00002000 { ; RW data .ANY (+RW +ZI) } } 需要注意的是,自己写的程序的入口必须是RESET,如下程序所示:STACK_TOP EQU 0x20002000 AREA RESET,CODE,READWRITE DCD STACK_TOP DCD START ENTRY START MOV R0, #10 MOV R1, #0 loop ADD R1, R0 SUBS R0, #1 BNE loop deadloop B deadloop END 然后在编译的时候linker选项下如下图所示:

编译之后输出结果如下所示: Build target 'Target 1' assembling test.s... linking... test.sct(8): warning: L6314W: No section matches pattern *(InRoot$$Sections). Program Size: Code=24 RO-data=0 RW-data=0 ZI-data=0 "test.axf" - 0 Error(s), 1 Warning(s). 此时,会出现这个警告。据网友们说是无关紧要的。虽然如此,但是看着不爽。后来查看了帮助文档,找到了消除这个警告的方法,在linker选项中加上如下一行: 虽然现在警告已经消除了,但是仍然不明白为什么。也就是没有搞懂这个分散加载文件中的 *.o (RESET, +First) *(InRoot$$Sections) .ANY (+RO) 这几行是什么意思,有待高人指点!

如何在Keil4下通过J-Link下载文件数据到STM32外部的Nor Flash

如何在Keil4下通过J-Link下载文件数据到STM32外部的Nor Flash 实验目的: 把一张320*240像素的图片文件,通过J-Link下载到STM32外部的Nor Flash里去,然后再读到LCD显示屏显示出来。用LCD转换图片工具把图片搞成一个C文件。 准备烧写算法: 声明:图例中用到的地址需要根据你自己的情况作相应调整。 Keil单片机开发平台是根据预先设定好的Flash烧写算法将用户程序烧到单片机的Flash内部的,那么由于这个算法是固定的,我们往往不关心,所以我们对其原理不是很了解,实际上,我们都知道,要将程序烧进去,需要在工程选项中选择对应的单片机型号,如下图所示。

这个过程就是准备Flash的烧写算法,选中了某个单片机型号,就确定了其使用的Flash特征,那么这些算法藏在什么地方呢。这些算法就藏在Keil安装的根目录下X:\Keil\ARM\Flash目下,该目录下有很多的文件夹,每个文件夹里有对应的工程,每个工程都是某种型号单片机的Flash烧写算法,他们具体的内容不同,但是具有统一的接口,以便被Keil调用。 现在我们要烧写STM32的外部Nor Flash,所以我们要新建一个算法: 新建一个文件夹,如Test。将X:\Keil\ARM\Flash\STM32F10x\下的所有文件拷进Test文件夹来,将X:\Keil\ARM\Flash\SST39x160x\下的FlashPrg.c文件也拷进Test文件夹来并覆盖同名文件,将X:\Keil\ARM\Flash\下的FlashOS.h 文件也拷进Test文件夹来。如果你使用的Nor Flash不在MDK自带驱动的范围内,那么需要根据FlashPrg.c文件自行编写相关函数。 打开工程文件STM32Fx.uvproj,此时会报一个错误,提示没有选择STM32的Device型号。 这时你根据你的STM32的型号选择相应的就OK了,如下图所示。

相关主题
相关文档
最新文档