remap, relocate的理解,codecARM为什么从ITCM启动,知道了

2019-04-14 20:40发布

remap, relocate的理解

0.什么是Remap 
我的理解是:在ROM从0x0用几句指令引导系统之后,把RAM映射到0x0就是Remap。

1.Remap的作用 
当ARM处理器上电或者Reset之后,处理器从0x0 取指。因此,必须保证系统上电时, 
0x0 处有指令可以执行。所以,上电的时候,0x0地址处必定是ROM 或者Flash(NOR)。 
但是,为了加快启动的速度,也方便可以更改异常向量表,加快中断响应速度,往往 
把异常向量表映射到更快、更宽(32bit/16bit)的RAM 中。但是异常向量表的开始地址是 
由ARM架构决定的,必须位于0x0处,因此,必须把RAM映射到0x0。 

2.Remap的配置 
Remap的实现和ARM处理器的实现相关。 
1)如果处理器有专门的寄存器可以完成Remap。那么Remap 是通过Remap 寄存器的 
相应bit置1 完成的。如Atmel AT91xx 
2)如果处理器没有专门的寄存器,但是memory的bank控制寄存器可以用来配置bank 
的起始地址,那么只要把RAM的起始地址编程为0x0,也可以完成remap。如samsung s3c4510 
3)如果上面两种机制都没有,那么Remap就不要做了。因为处理器实现决定了SDRAM 
对应的bank地址是不能改变的。如Samsung S3c2410. 

3.Remap配置前后要做的工作 
Remap 前后,不同之处就是RAM 的位置变了。为了达到Remap 的目的,就是加快启 
动的速度和异常处理速度,一定要初始化异常堆栈和建立异常向量表的。

4.如果象2410那样不能Remap的话怎么办? 
2410 不是不能Remap吗?为了加快启动速度,可以这样做 
1)使用它的NAND boot 模式。为什么NAND boot 会比较快,那是因为2410 里面有 
块小石头——“SteppingStone”,一块4KB SRAM,它是映射在0x0 的。启动程序会自动被 
copy 到这个石头里面。自然异常向量的入口放到这个地方,一样可以达到比NOR boot 快 
的启动、异常响应速度。 
2)如果你对NOR Boot 情有独衷,那么你只好把你的异常向量的入口copy到SDRAM 
里面,实现所谓的High Vector
结合自己项目(arm926j, uboot1.3.0)

UBOOT中的REMAP

1.为什么需要REMAP?
中断向量表在0处,如果不做REMAP,那么0地址处是Flash/ROM,这样中断响应没有RAM快。REMAP另外一个功能是
做完REMAP后,用户方便可以把程序从ROM/Flash中复制到RAM中,这样程序执行速度也快。

2.如何做REMAP?
因为REMAP前后地址空间完全变了,要保证程序正常执行不跑飞,必须小心处理PC指针。我们用的芯片内部有16K ITCM,
在REMAP前,把REMAP代码从ROM/Flash中复制到ITCM中,然后PC设置到ITCM中运行REMAP处理程序。

3.REMAP流程
                REMAP前地址空间            REMAP后地址空间
ROM/Flash         0x00000000                 0x80000000
ITCM              0x20010000                 0x00000000
RAM(DDR)          0x80000000                 0x00004000

从地址分配知道:上电时,MCU从0地址取值,0地址是ROM/Flash。当ROM/Flash开头的程序做完系统初始化后,
比如时钟初始化,DDR初始化。接下来从ROM/Flash中把REMAP处理部分复制到ITCM(此处是0x20010000)中,复制完后设
置PC指针到ITCM中运行。ITCM中处理程序主要是设置REMAP的寄存器使REMAP生效,REMAP生效后,整个地址空间分配变了。
这时程序需要跳到ROM/Flash中继续执行后面的程序,这里注意PC指针的衔接,按照上面的地址空间,应该跳到0x80000000
ROM/Flash开始的某个地方执行。

从REMAP后的地址可以看到,ITCM在0处,可以放中断向量表,16K后面接DDR RAM。


UBOOT RELOCATION
因为代码就放在nor flash中,代码可以直接在flash上运行。重定位就是为了代码执行快。uboot重定位就是把uboot从ROM/Flash
0x80000000)中复制到RAM中运行。这里不得不说的一点:uboot连接后的地址在0x800000,用objdump -d可以看汇编代码!实际复
制uboot到RAM(此处是DDR)的0x800000处,而不是0(0处是ITCM 16K)。这样中断向量表就在0x800000开始出,所以uboot根本没法
响应中断,如果需要响应中断,需要做的是把中断向量表同时复制到0处。

在做relocate的时候,需要判断现在的uboot是不是本身已经在ram中,不需要relocate。如何判断?ARM汇编做的比较巧妙,它根据当前的PC值和uboot的连接的入口地址(0x800000)比较,如果不等,说明需要relocate. 代码如下:

adr r0,_start              //current pc
ldr r1,_TEXT_BASE  //0x800000
cmp r0,r1
beq skip_relocate
relocate:
..............

什么情况下PC相于uboot的入口地址0x800000?
在debug情况下,比如:trace32直接下载uboot到RAM的0x800000,然后直接设置PC到0x800000.  如果程序从flash/rom走,也就是不在debug状态,程序会做remap等动作,PC肯定
不等于0x800000