周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx

上传人:b****1 文档编号:14672782 上传时间:2023-06-26 格式:DOCX 页数:62 大小:89.62KB
下载 相关 举报
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第1页
第1页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第2页
第2页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第3页
第3页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第4页
第4页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第5页
第5页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第6页
第6页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第7页
第7页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第8页
第8页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第9页
第9页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第10页
第10页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第11页
第11页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第12页
第12页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第13页
第13页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第14页
第14页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第15页
第15页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第16页
第16页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第17页
第17页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第18页
第18页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第19页
第19页 / 共62页
周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx_第20页
第20页 / 共62页
亲,该文档总共62页,到这儿已超出免费预览范围,如果喜欢就下载吧!
下载资源
资源描述

周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx

《周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx》由会员分享,可在线阅读,更多相关《周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx(62页珍藏版)》请在冰点文库上搜索。

周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解.docx

周立功NXPLPC21xx22xx系列ARM芯片的启动程序分解

周立功NXPLPC21xx/22xx系列ARM芯片的启动程序分解2008.11.25

zhongcw1002@作者:

钟常慰关于LPC2200启动程序分散加载描述文件的叙述在ADSLPC2200的启动模板中有一个scf文件夹,其中有mem_a.scf、mem_b.scf、mem_c.scf这3

个文件,这3个文件是ADS的分散加载机制,其目的是将代码段和数据段分别定位到指定地址上。

可以在ArmLinker中选择加载路径。

分散装载技术概述:

分散装载技术可以把用户的应用程序分割成多个RO(只读)运行域和RW(可读写)运行域(一个存储区域块),并且给它们制定不同的地址。

一个嵌入式系统中,Flash、16位RAM、32位RAM都可以存在于系统中,所以,将不同功能的代码定位在特定的位置会大大地提高系统的运行效率。

下面是最为常用的2种情况:

1、32位的RAM运行速度很快,因此就把中断服务程序作为一个单独的运行域,放在32位的RAM,使它的响应时间达到最快。

2、程序在RAM中运行,其效率要远远高于在ROM中运行,所以将启动代码(Bootloader)以外的所有代码都复制在RAM中运行,可以提高运行效率。

分散装载技术主要完成了2个基本的功能:

如何分散。

就是如何将输入段组成输出段和域。

如何装载。

就是确定装载域和运行域在存储空间里的地址是多少。

域可以分为装载域和运行域

装载域描述运行前输出段和域在ROM/RAM里的分布状态,运行域描述了运行时输出段和域在ROM/RAM里的分布状态。

大多数情况下,映像文件在执行前把它装载到ROM里,而当运行时,RWRAM里,程序才能正常运行,所以,在装载和运行时,RW类的输出段处在不同的位置(地址空间)。

Scatterfile分散加载文件:

RO:

只读的代码段和常量

RW:

可以读写的全局变量和静态变量

ZI:

RW段中要被初始化为零的变量。

Scatterfile中的定义要按照系统冲定向后的存储器分布情况进行,在引导程序完成初始化任务后,应该把主程序转移到RAM中运行以加快系统的运行速度。

分(消)散

2008.11.25

zhongcw1002@

LPC2200的分散加载文件分析:

ROM_LOAD0x80000000

{

ROM_EXEC0x80000000

(2)第一个运行时域描述

(3)

(4)

(5)

(6)

(7)将栈底放入堆栈的后面(+0)不进行初始化(UNINIT),

(1)加载时域描述{Startup.o(vectors,+First)*(+RO)}IRAM0x40000000放置向量表将MyStacks堆栈段装载到片内静态RAM中。

{Startup.o(MyStacks)}STACKS_BOTTOM+0UNINIT

{Startup.o(StackBottom)}

STACKS0x40004000UNINIT

栈底为Startup中的StackBottom。

(8)(9)将栈放入地址为0x40004000并且不进行初始化(UNINIT)。

(10)(11)将所有的RW和ZI段放入外部存储器中以0x80040000(13)在RWZI段后放入堆底(Startup.o(Heap))(14){Startup.o(Stacks)}ERAM0x80040000{*(+RW,+ZI)}HEAP+0UNINIT(12)为开头的地址中。

并且全部清零(+ZI)外部RAM中指定的区域。

{Startup.o(Heap)}并且不进行初始化。

HEAP_BOTTOM0x80080000UNINIT{Startup.o(HeapTop)}

}

FLASH_LOAD0x810000000x1000

{FLASH_EXEC0x81000000

{main.o(+RO)}

}(15)将堆定放入外部RAM中(0x80080000)。

(16)(17)自己添加的加载代码,把main.c的目标文件加载到(18)片外Flash中并且占用了0x1000的大小。

(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)在RWZI段后放入堆底(Startup.o(Heap))并且不进行初始化。

(15)-(16)将堆定放入外部RAM中(0x80080000)。

(17)-(19)自己添加的加载代码,把main.c的目标文件加载到片外Flash中并且占用了0x1000的大小。

;********************************************************************************************************/;**FileName:

men_a.scf

ROM_LOAD0x80000000//ROM加载{

ROM_EXEC0x80000000//ROM执行(起始地址)程序0x80000000外部存储区

{Startup.o(vectors,+First)//Startup.o文件(向量,程序入口)*(+RO)}//只读

IRAM0x40000000//IndexedRandomAccessMethod,索引随机存取方法0x40000000{Startup.o(MyStacks)}//Startup(堆栈)装载到片内SRAM中

STACKS_BOTTOM+0UNINIT//堆栈栈底,将栈底放入堆栈的后面(+0),不初始化

{Startup.o(StackBottom)}//将栈放入地址为0x40004000并且不进行初始化(UNINIT)

STACKS0x40004000UNINIT//堆栈0x4000400016kb的SRAM片内存储区{Startup.o(Stacks)}//Startup.o文件(堆栈)

ERAM0x81000000//将所有的RW和ZI段放入外部存储器中0x81000000为开头的地址中{*(+RW,+ZI)}//并且全部清零(+ZI)外部RAM中指定的区域读写(无输入ZI)HEAP+0UNINIT//在RWZI段后放入堆底(Startup.o(Heap))并且不进行初始化{Startup.o(Heap)}//Startup.o文件(堆栈)

HEAP_BOTTOM0x81080000UNINIT//将堆定放入外部RAM中0x81080000

{Startup.o(HeapTop)}//Startup.o文件(堆栈栈顶)

}

;********************************************************************************************************/;**FileName:

men_b.scf

ROM_LOAD0x80000000

{

ROM_EXEC0x80000000

{Startup.o(vectors,+First)

*(+RO)}

IRAM0x40000000

{Startup.o(MyStacks)}

STACKS_BOTTOM+0UNINIT

{Startup.o(StackBottom)}

STACKS0x40004000UNINIT

{Startup.o(Stacks)}

ERAM0x80040000

{*(+RW,+ZI)}

HEAP+0UNINIT

{Startup.o(Heap)}

HEAP_BOTTOM0x80080000UNINIT

{Startup.o(HeapTop)}

}

;********************************************************************************************************/;**FileName:

men_c.scf

ROM_LOAD0x0

{

ROM_EXEC0x00000000

{Startup.o(vectors,+First)

*(+RO)}

IRAM0x40000000

{Startup.o(MyStacks)}

STACKS_BOTTOM+0UNINIT

{Startup.o(StackBottom)}

STACKS0x40004000UNINIT

{Startup.o(Stacks)}

ERAM0x80000000

{*(+RW,+ZI)}

HEAP+0UNINIT

{Startup.o(Heap)}

HEAP_BOTTOM0x80080000UNINIT

{Startup.o(HeapTop)}

}

;/********************************************************************************************************

加载文件的更多分解说明,网上了解资料。

只作参考

有如下分散加载文件:

ROM_LOAD0x00000000//程序起始点(程序在Flash中)OriginationPointofCode(CodeinFlash){

ROM_EXEC0x00000000//起始程序执行OriginationPointofExecuting

{Startup.o(vectors,+First)

*(+RO)}

IRAM0x40000040//内部SRAM起始点OriginationPointofInternalSRAM

{Startup.o(MyStacks)}//0x40000000~0x4000003FforVector

STACKS_BOTTOM+0UNINIT

{Startup.o(StackBottom)}

STACKS0x40004000UNINIT//EndPointofInternalSRAM

{Startup.o(Stacks)}

ERAM0x81000000//外部RAM起始点OriginationPointofExternalSRAM

{*(+RW,+ZI)}

HEAP+0UNINIT

{Startup.o(Heap)}

HEAP_BOTTOM0x81800000UNINIT//外部RAM结束点EndPointofExternalSRAM

{Startup.o(HeapTop)}

}

其中,ROM_LOAD为加载区的名称,其后面的0x00000000表示加载区的起始地址(存放程序代码的起始地址),也可以在后面添加其空间大小,如“ROM_LOAD0x000000000x20000”表示加载区起始地址为0x00000000,大小为128K字节;ROM_EXEC描述了执行区的地址,放在第一块位置定义,其起始地址、空间大小与加载区起始地址、空间大小要一致。

从起始地址开始放置向量表(即Startup.o(vectors,+First),其中Startup.o为Startup.s的目标文件),接着放置其他代码(即映像文件)(即*(RO));变量区IRAM的起始地址为0x4000000040,放置Startup.o(MyStacks);变量区ERAM的起始地址为0x80000000,放置出Startup.o文件之外的其他文件的变量(即*(+RW,+ZI));紧靠ERAM变量区之后的是系统堆空间(HEAP),放置描述为Startup.o(Heap);堆栈区STACKS使用片内RAM,由于ARM的堆栈一般采用满递减堆栈,所以堆栈区的起始地址设置为0x40004000,放置描述为Startup.o(Stacks)

2.使用地址不连续的内存(LPC2368)

Lpc2368一共有56K的RAM,其中通用Ram32K,地址为0x40000000~0x40007fff;8KB的USB专用RAM,地址0x7fd00000~0x7fd01ffff;16KBEthernet专用RAM,地址为0x7fe00000~0x7fe03fff;以上的USB和Ethernet专用RAM也可用做通用RAM,需要做如下设置:

(1)target.c中将USB和Ethernet功能打开,需要设置PCONP寄存器,详见Datasheet。

(2)设置分散加载文件,分配这两段内存。

在DebugInRam模式下,有如下分散加载文件:

ROM_LOAD0x40000000

{

ROM_EXEC0x40000000//加载映像文件(通用RAM首地址)

{Startup.o(vectors,+First)

*(+RO)}

IRAM0x40007000//用户堆栈

{Startup.o(MyStacks)}

STACKS0x40008000UNINIT//系统堆栈

{Startup.o(Stacks)}

ERAM0x7fe00000/*变量,放置与Ethernet专用RAM首地址*/

{*(+RW,+ZI)}

HEAP+0UNINIT

{Startup.o(Heap)}

}

3.分散使用Flash地址(LPC2368)

项目中,要求将片内Flash起始几个扇区空出来留作他用,或者当用到的Flash地址不连续的时候,都可用以下方法来编写分散加载文件:

ROM_LOAD0x00000000

{

ROM_EXEC0x00000000/*中断向量表*/

{Startup.o(vectors,+First)}

……

ROM_LOAD10x00004000//加载映像文件,从第四个扇区开始

{ROM_EXEC10x00004000

{

*(+RO)

}

}

值得注意的是,中断向量表必须放在flash起始地址处,否则无法启动。

根据以上分散加载文件编译生成的Hex文件会有两个,分别如下:

Hex1:

:

020000040000FA

:

1000000018F09FE518F09FE518F09FE518F09FE5C0

……

Hex2:

:

020000040000FA

:

1040000090808FE20F0098E8080080E0081081E0BF

可以看出,生成的两段Hex文件的起始地址是不同的,其中一段为中断向量表;另一段为用户映像文件。

4.固定变量内存地址

嵌入式开发中,有时会需要在同一片内的不同段程序(比如Bootloader和主程序间)间传递数据,这时候往往需要固定变量地址。

一般来言,C语言编写的程序,变量地址是由C编译器来分配内存的,程序员无法实现知道变量地址。

而ADS中的分散加载文件可以告知编译器,固定某些变量的地址,如下:

ROM_LOAD0x00000000

{

ROM_EXEC0x00000000

{Startup.o(vectors,+First)

*(+RO)}

RAM0x40000000UNINIT//Mfile.c中的所有变量地址从0x40000000开始

{Mfile.O(+RW,+ZI)}

IRAM0x40000010

{Startup.o(MyStacks)

*(+RW,+ZI)}

HEAP+0UNINIT

{Startup.o(Heap)}

STACKS0x40004000UNINIT

{Startup.o(Stacks)}

}

上述分散加载文件固定了Mfile.c中变量的起始地址,以这种方法,可以固定任何全局变量的地址,以便其被其他系统访问。

;/********************************************************************************************************;**Filename:

Startup.s//起始文件

;定义堆栈的大小

SVC_STACK_LEGTHEQU0//管理堆栈长度

FIQ_STACK_LEGTHEQU0//快速中断堆栈长度

IRQ_STACK_LEGTHEQU256//通用中断堆栈长度

ABT_STACK_LEGTHEQU0//中止堆栈长度

UND_STACK_LEGTHEQU0//未定义堆栈长度

NoIntEQU0x80

USR32ModeEQU0x10//用户模式

SVC32ModeEQU0x13//管理模式

SYS32ModeEQU0x1f//系统模式

IRQ32ModeEQU0x12//通用中断模式

FIQ32ModeEQU0x11//快速中断模式

//以下几个定义是确定寄存器所在地址(保证前期初始化作业)书本191-193页PINSEL2EQU0xE002C014//定义引脚功能选择寄存器2在芯片中所在的地址(0xE002C014)(不管内容)

BCFG0EQU0xFFE00000//存储器组0所在芯片位置(0xFFE00000)设定与外设的读写及间隔速度设定BCFG1EQU0xFFE00004//存储器组1所在芯片位置(0xFFE00004)设定与外设的读写及间隔速度设定BCFG2EQU0xFFE00008//存储器组2所在芯片位置(0xFFE00008)设定与外设的读写及间隔速度设定BCFG3EQU0xFFE0000C//存储器组3所在芯片位置(0xFFE0000C)设定与外设的读写及间隔速度设定

IMPORT__use_no_semihosting_swi

IMPORT__use_two_region_memory

;引入的外部标号在这声明

IMPORTFIQ_Exception//快速中断异常处理程序

IMPORT__main//C语言主程序入口

IMPORTTargetResetInit//目标板基本初始化

;给外部使用的标号在这声明//这些标号都是代表一段字节的首地址,可参见后面的部分设定

EXPORTbottom_of_heap//heap的底部

EXPORTbottom_of_Stacks//stack的底部

EXPORTtop_of_heap//heap的顶部

EXPORTStackUsr

EXPORTReset//复位

EXPORT__user_initial_stackheap//库函数初始化堆和栈

CODE32//32位ARM代码

AREAvectors,CODE,READONLY//只读程序入口

ENTRY//进入

;中断向量表

Reset

LDRPC,ResetAddr//复位起始地址

LDRPC,UndefinedAddr//未定义异常向量地址

LDRPC,SWI_Addr//软件复位向量地址

LDRPC,PrefetchAddr//预指令中止

LDRPC,DataAbortAddr//数据异常向量地址

DCD0xb9205f80//将所有向量表合计为0的一个指定数据

LDRPC,[PC,#-0xff0]//IRQ(该指令会读取VICVectAddr寄存器的值,然后放入PC指针)

LDRPC,FIQ_Addr//快速中断地址

;给每一个向量分配连续的字存储单元

ResetAddrDCDResetInit//将ResetInit入口地址赋予ResetAddr复位初始化

UndefinedAddrDCDUndefined//将Undefined入口地址赋予UndefinedAddr未定义

SWI_AddrDCDSoftwareInterrupt//将SoftwareInterrupt入口地址赋予SWI_Addr软件复位

PrefetchAddrDCDPrefetchAbort//将PrefetchAbort入口地址赋予PrefetchAddr预指令中止

DataAbortAddrDCDDataAbort//将DataAbort入口地址赋予DataAbortAddr数据异常

NouseDCD0//将Nouse赋予0

IRQ_AddrDCD0//将IRQ_Addr赋予0通用中断

FIQ_AddrDCDFIQ_Handler//将FIQ_Handler入口地址赋予FIQ_Addr快速中断

;未定义指令

Undefined

BUndefined//原地循环

;软中断

SoftwareInterrupt

BSoftwareInterrupt//原地循环

;取指令中止

PrefetchAbort

BPrefetchAbort//原地循环

;取数据中止

DataAbort

BDataAbort//原地循环

;快速中断

FIQ_Handler

STMFDSP!

{R0-R3,LR}//入栈

BLFIQ_Exception//调快速中断程序

LDMFDSP!

{R0-R3,LR}//出栈

SUBSPC,LR,#4//返回当初的地址

;/*****************

展开阅读全文
相关资源
猜你喜欢
相关搜索
资源标签

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2023 冰点文库 网站版权所有

经营许可证编号:鄂ICP备19020893号-2