LPC2210(3)

前次错怪ZLG了,他还是有include文件,在他的工程文件里有一个config.h文件,里面有
#include "LPC2294.h"
包含了寄存器的定义

//----------------------------------------------------//

最近在看ARM的boot code,学习总结如下

一、分散装载(Scatlerloading)
即工程里的.scf文件
在scatterfile中可以为每一个代码或数据区在装载和执行时指定不同的存储区域地址,Scatlertoading的存储区块可以分成二种类型:
装载区:当系统启动或加载时应用程序的存放区。
执行区:系统启动后,应用程序进行执行和数据访问的存储器区域,系统在实时运行时可以有一个或多个执行块。
映像中所有的代码和数据都有一个装载地址和运行地址(二者可能相同也可能不同,视具体情况而定)。

1.scatter文件语法
scatter文件是一个简单的文本文件,包含一些简单的语法。
My Region 0x0000 0x1000
{
;the context of region
}
标题
每个块由一个头标题开始定义,头中至少包含块的名字和起始地址,如(0x0000),另外还有最大长度等其他一些属性选项(注:这些属性是可选的,如0x1000)。
内容
块定义的内容包括在紧接的一对花括号内,依赖于具体的系统情况。
一个加载块必须至少含有一个执行块;实践中通常有多个执行块。
一个执行块必须至少含有一个代码或数据段;这些通常来自源文件或库函数等的目标文件;通配符号*可以匹配指定属性项中所有没有在文件中定义的余下部分。

2.分散加载样例分析
选取ADS的Examples中embed文件夹下的scat_b.scf进行分析,代码如下
ROM_LOAD 0x0                                                       (1)
{
ROM_EXEC 0x0                                                       (2)
{
vectors.o (Vect, +First)                                            (3)
* (+RO)
}

RAM 0x28000000                                                    (4)
{
* (+RW,+ZI)                                                               (5)
}

HEAP +0 UNINIT
{
heap.o (+ZI)                                                              (6)
}

STACKS 0x28080000 UNINIT
{
stack.o (+ZI)                                                             (7)
}

UART0 0x16000000 UNINIT                                (8)
{
uart.o (+ZI)
}
}
(1)样例中,只有一个加载块ROM_LOAD,包含了所有的代码和数据(存放在ROM),起始地址为0x0。这个加载块一共对应五个执行块(ROM_EXEC, RAM, HEAP, STACKS, UART0)。
(2)RO的代码和数据会从ROM_EXEC开始执行,执行地址与装载地址相同。
(3)vectors.o是vectors.s的目标文件(vectors.s也在这个工程下),Vect是在Vector.s定义的+FIRST是感觉像个指针,整个句子的意思是把整个vectors.s编译生成的目标文件(向量表)从Vect开始依次从ROM_EXEC的顶部放下来(以上用不肯定语气的地方属于个人猜测,不一定准确)
(4)所有的RW和ZI数据包含在RAM执行块里,起始地址为0x28000000。
(5)RW数据是从ROM_LOAD copy 过来的,ZI数据是在RAM中初始化的,其位置在RW之上
(6)HEAP是用来定位堆栈的底的,堆栈底的位置在ZI之上所以使用"+0",heap会从此地址增加
(7)STACKS是用来定位堆栈顶的,堆栈顶的位置在可以用来作为存储的内存的顶部。Stacks会从堆栈顶的地址下降。
(8) UART0是用来对应相应的UART0寄存器。标记UNINIT会使得他不会在芯片启动时被C library初始化。

二、_user_initial_stackheap重定向
应用程序的堆栈和heap是在C库函数初始化过程中建立起来的。可以通过重定向对应的子程序来改变堆栈和heap的位置,在ADS的库函数中,即_user_initial_stackheap()函数。
_user_initial_stackheap()可以用C或汇编来实现,它必须返回如下参数:
r0:heap基地址;
r1:堆栈基地址;
r2:heap长度限制值(需要的话);
r3:堆栈长度限制值。
ADS的Examples中embed文件夹下的retarget.c中有相应的代码
__value_in_regs struct __initial_stackheap __user_initial_stackheap(
unsigned R0, unsigned SP, unsigned R2, unsigned SL)
{
struct __initial_stackheap config;

config.heap_base = (unsigned int)&bottom_of_heap; // defined in heap.s
// placed by scatterfile
config.stack_base = SP; // inherit SP from the execution environment

return config;
}
在<rt_misc.h>文件中你可以找到结构体__initial_stackheap的定义
struct __initial_stackheap {
unsigned heap_base; /* low-address end of initial heap */
unsigned stack_base; /* high-address end of initial stack */
unsigned heap_limit; /* high-address end of initial heap */
unsigned stack_limit; /* low-address end of initial stack */
};
extern __value_in_regs struct __initial_stackheap
__user_initial_stackheap(unsigned /*R0*/, unsigned /*SP*/,
unsigned /*R2*/, unsigned /*SL*/);
当用户使用分散装载功能的时候,必须重调用_user_initial_stackheap(),否则连接器会报错


三、ROM/RAM重定向
当系统启动的时候,为了保证0地址处有正确的启动代码存在,需要非易失性的存储器(如Flash)。
一种简单的方法,就是把系统0x0000开始的一块地址分配给ROM。其缺点是,由于ROM的访问速度比RAM慢很多,当执行中断响应需要从中断向量表跳转时,会给系统性能带来损失;同时,在ROM中的向量表内容也不能被用户程序动态修改。

另外一种可行的方案是在系统复位时ROM被存储器控制器映射到0x0000地址处。这样当系统启动之后,在地址0x0000看到的是ROM,系统执行这块ROM中的启动代码,而启动代码会在执行一定的初始化(如将向量表copy到0x0000处的RAM中去)之后让存储器控制器移除对ROM的地址映射。这时0x0000地址处的存储器又恢复回了RAM。(注:ARM的中低地址为RAM,高地址为FLASH)
ADS的Examples中embed文件夹下的vectors.s中有中断向量初始化的相应代码
; *****************
; Exception Vectors
; *****************

; Note: LDR PC instructions are used here, though branch (B) instructions
; could also be used, unless the ROM is at an address >32MB.

ENTRY

LDR PC, Reset_Addr
LDR PC, Undefined_Addr
LDR PC, SWI_Addr
LDR PC, Prefetch_Addr
LDR PC, Abort_Addr
NOP ; Reserved vector
LDR PC, IRQ_Addr
LDR PC, FIQ_Addr

IMPORT Reset_Handler ; In init.s

Reset_Addr DCD Reset_Handler
Undefined_Addr DCD Undefined_Handler
SWI_Addr DCD SWI_Handler
Prefetch_Addr DCD Prefetch_Handler
Abort_Addr DCD Abort_Handler
IRQ_Addr DCD IRQ_Handler
FIQ_Addr DCD FIQ_Handler
如果ROM是被定位在0x0位置,以上代码就成为在用户程序中不可更改的代码,被安置在0x0
如果使用了ROM/RAM重定向,则这些代码会被copy到RAM里,整个copy动作是由C library 中的__main 自动完成的

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值