M0系列ARM芯片的启动程序分解
- 1、下载文档前请自行甄别文档内容的完整性,平台不提供额外的编辑、内容补充、找答案等附加服务。
- 2、"仅部分预览"的文档,不可在线预览部分如存在完整性等问题,可反馈申请退款(可完整预览的文档不适用该条件!)。
- 3、如文档侵犯您的权益,请联系客服反馈,我们会尽快为您处理(人工客服工作时间:9:00-18:30)。
周立功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 这个域的范围
}
标题
每个块由一个头标题开始定义,头中至少包含块的名字和起始地址,如(0x0000),另外还有最大长度等其他一些属性选项(注:这些属性
是可选的,如0x1000)。
内容
块定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。
1、一个加载块必须至少含有一个执行块;实践中通常有多个执行块。
2、一个执行块必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;
通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。
有以下几种属性:
RO:只读的代码段和常量
RW:可以读写的全局变量和静态变量
ZI:RW 段中要被初始化为零的变量。
Scatterfile 中的定义要按照系统冲定向后的存储器分布情况进行,在引导程序完成初始化任务后,应该把主程序转移到RAM 中运行以
加快系统的运行速度。
2008.11.25
zhongcw1002@
分(消)散
LPC2200 的分散加载文件分析:
ROM_LOAD 0x80000000 (1)
{
ROM_EXEC 0x80000000 (2)
{ Startup.o (vectors, +First) (3)
* (+RO) } (4)
IRAM 0x40000000 (5)
{ Startup.o (MyStacks) } (6)
STACKS_BOTTOM +0 UNINIT (7)
{ Startup.o (StackBottom) } (8)
STACKS 0x40004000 UNINIT (9)
{ Startup.o (Stacks) } (10)
ERAM 0x80040000 (11)
{ * (+RW,+ZI) } (12)
HEAP +0 UNINIT (13)
{ Startup.o (Heap) } (14)
HEAP_BOTTOM 0x80080000 UNINIT (15)
{ Startup.o (HeapTop) } (16)
}
FLASH_LOAD 0x81000000 0x1000 (17)
{ FLASH_EXEC 0x81000000 (18)
{ main.o (+RO) } (19)
}
(1) 加载时域描述,名称位ROM_LODA 它的地址为0x80000000;
0x80000000 为LPC 片外RAM 地址,即将以下的加载的段和域都在RAM 中。
(2) 第一个运行时域描述。
ROM_EXEC 描述了执行区的地址,放在第一块定义,其起始地址、空间大小域加载区起始地址、空间大小要一样。
(2)-(4)从起始地址开始放置向量表。Startup.o 是Startup.s 的目标文件。Vectors 为中断向量表。模块Startup 位于该加载域的开
头(+First),vectors 作为入口点,包含全部的RO 代码。ARM 在芯片复位之后,系统进入管理模式、ARM 状态,PC(R15)寄存器的值
为0x00000000,所以必须保证用户的向量表代码定位在0x00000000 处,或者映射到0x00000000 处(例如向量表代码在0x80000000
处,通过存储器映射,访问0x0000000 就是访问(0x80000000)。
(5)-(6)第二运行时域描述。将MyStacks 堆栈段装载到片内静态RAM 中。
(7)-(8)将栈底放入堆栈的后面(+0)不进行初始化(UNINIT), 栈底为Startup 中的StackBottom。
(9)-(10) 将栈放入地址为0x40004000 并且不进行初始化(UNINIT)。
(11)-(12 将所有的RW 和ZI 段放入外部存储器中以0x80040000 为开头的地址中。并且全部清零(+ZI)外部RAM 中指定的区域。
(13)-(14)在RW ZI 段后放入堆底(Startup.o(Heap))并且不进行初始化。
(15)-(16)将堆定放入外部RAM 中(0x80080000)。
(17)-(19)自己添加的加载代码,把main.c 的目标文件加载到片外Flash 中并且占用了0x1000 的大小。2008.11.25
加载时域描述
第一个运行时域描述
放置向量表
将MyStacks 堆栈段装载到片内静态RAM 中。
将栈底放入堆栈的后面(+0)不进行初始化(UNINIT),
栈底为Startup 中的StackBottom。
将栈放入地址为0x40004000 并且不进行初始化(UNINIT)。
将所有的RW 和ZI 段放入外部存储器中以0x80040000
为开头的地址中。并且全部清零(+ZI)外部RAM 中指定的区域。
在RW ZI 段后放入堆底(Startup.o(Heap))
并且不进行初始化。
自己添加的加载代码,把main.c 的目标文件加载到
片外Flash 中并且占用了0x1000 的大小。
将堆定放入外部RAM 中(0x80080000)。
;******************************************************************************************* *************/
;** File Name: men_a.scf
ROM_LOAD 0x80000000 // ROM加载
{
ROM_EXEC 0x80000000 // ROM执行(起始地址)程序0x80000000 外部存储区
{ Startup.o (vectors, +First) // Startup.o文件(向量,程序入口)
* (+RO)} // 只读
IRAM 0x40000000 // Indexed Random Access Method,索引随机存取方法0x40000000
{ Startup.o (MyStacks)} // Startup(堆栈)装载到片内SRAM中
STACKS_BOTTOM +0 UNINIT // 堆栈栈底,将栈底放入堆栈的后面(+0),不初始化