ARM是在嵌入式学习过程中必不可少的一个环节。但是对于很多新手来说ARM启动过程是一个非常复杂的过程。本文就将为大家介绍ARM启动过程,感兴趣的朋友快来看一看吧。
对于一般的嵌入式系统来讲,考虑到系统成本,运行速度等因素,往往联合使用好几种存储器件。在下面讲到的例子中,是我在开发中用到的一个ARM9EJ的处理器,系统中采用了SDRAM,ROM,Nand FLASH,ITCM,DTCM等。
SDRAM: 程序正常运行时所在的存储器, 物理地址0x24000000 - 0x24800000(以8M为例);
ROM: 复位后,ARM从ROM启动,ROM是只读的,出厂时就烧好了,不可更改,正常运行时,物理地址:
0x2C000000 - 0x2C006000 (24KB);
Nand FLASH: 外接存储器件,正常运行的程序会通过烧录工具先放在这里。也可以做为用户的数据存储区,通过文件系统来访问。
ITCM,DTCM:类似与SDRAM,但是速度比SDRAM快很多,当进行大量,繁琐,且实时性要求较高的运算时,使用该存储。
从开机,即对处理器发送一个RESET信号后,ARM处理器就进入中断模式,从中断向量RESET处理,即地址0x00000000处开始执行。但是,我们看到,整个系统在物理地址0处是没有存储器件的。实际上是, 对与大多数的ARM处理器来讲,有一个硬件映射的机制。对与这个处理器来说,开始时,默认将ROM(0x2C000000 - 0x2C006000) 映射到地址零处,注意,此动作是由硬件达成的,软件不用考虑。此时,送到地址总线的地址是0x00000000, 但是对应的却是ROM中offset为0处的代码。 看看ROM中代码是怎么考虑的:
.section .boot #1
__RESET_ADDR:
/* Move PC to ROM address */
LDR PC,=0x2C000024 #2
/* Hardward init */
BL __HARDWARD_INIT
/* Detect SDRAM size */
BL __SDRAM_DETECT
/* SDRAM init */
BL __SDRAM_INIT
/* Data section init */
BL __DATA_INIT #3
/* BSS section init */
BL __BSS_INIT #4
/* ARM mode stacks init */
BL __STACK_INIT #5
/* Enter C code */
B __MMU_START_MAIN #6
需要注意的是上面标出来的6个地方,下面分别解释:
#1
GCC 会把以下的代码放到.boot段中,通过ld中对.boot的安排,可将该段放在指定的地址空间,参见后面的ld描述;
#2
此处将PC指针赋值为0x2C000024, 通过对这个.boot段进行反汇编,可以看到该地址对应
BL __HARDWARD_INIT, 就是该条指令的下一条。 此时,物理地址0x00000024和0x2C000024都对应这条指令,这是由于重映射机制造成的。通过,执行
LDR PC,=0x2C000024, 使得处理器的地址空间从原来的0x0000000变到0x2C000000,这是必要的。其一:ROM本身就对应在0x2C000000这个地址空间,恢复到此空间是很自然的。其二:为后面的重映射做准备。因为ROM的运行速度没有SDRAM快,所以通常把程序加载到SDRAM中运行,由于中断向量的在0x00000000处,所以需要把SDRAM映射到0地址去,这也是硬件映射的。如果不做这种转换的话,当进行了硬件映射后,两条指令就接不上了,上一条指令是0x0000xxxx, 位于ROM中,下一条指令0x0000xxxy为与SDRAM,会接着从SDRAM中执行,很容易出问题。
#3
此处做数据段的初始化的,数据段是可读可写的。所以必须把数据段搬到SDRAM中去,方可使用。该数据段的LMA和VMA是不同的,通过在ld中加上标签,可以得知从哪儿搬数据,要搬到那儿去。
#4
做BSS段初始话,一般清0。 值得注意的是,对于初始化为0的全局变量,可能会放在这里。
#5
初始化,各个模式下的堆栈。
#6
启动MMU,进入main函数。
声明:本内容为作者独立观点,不代表电源网。本网站原创内容,如需转载,请注明出处;本网站转载的内容(文章、图片、视频)等资料版权归原作者所有。如我们采用了您不宜公开的文章或图片,未能及时和您确认,避免给双方造成不必要的经济损失,请电邮联系我们,以便迅速采取适当处理措施;欢迎投稿,邮箱∶editor@netbroad.com。