新闻中心

EEPW首页 > 嵌入式系统 > 设计应用 > 基于Nand Flash的VIVI装载器的分析与改进

基于Nand Flash的VIVI装载器的分析与改进

作者: 时间:2016-12-02 来源:网络 收藏


3.2 程序拷贝的改进

在嵌入式系统中,映像文件都是存储在Flash存储器等一些非易失性器件中的,而在运行时,映像文件中的RW段必须重新装载到可渎写的RAM中。这就涉及到映像文件的加载时域和运行时域:加载时域就是指映像文件烧入nash中的状态,
也就是映像文件运行之前的地址;运行时域是指映像文件执行时的状态,针对本文提到的Nand Flash启动方式可以这么理解加载时域与运行时域:加载时域的起始地址从(映射后的内部SRAM处)0x00000000开始,运行时域的地址从0x33f00000开始。由于加载时域与运行时域的地址不同,从加载时域到运行时域的转换要由系统引导程序完成,所以VIVI必须进行数据和代码的拷贝及程序跳转工作,以完成从加载时域到运行时域的转换。

VIVI的拷贝首先要确定拷贝的起始地址和目标地址,还要确定要拷贝多少代码。在此笔者对所搬运代码量进行了改进,下面是改进前的代码:

ldr r0,=VIVI_RAM_BASE
<2>mov rl,#Ox0
<3>mov r2,#0x20000
<4>bl nand_read_ll

其中:第<1>行:获取VIVI在RAM中的基地址VIVI_RAM_BASE,也是运行时域的首地址。第<2>行:获取VIVI映像在Flash中的起始地址OxO。第<3>行:获取拷贝的代码量0x20000。第<4>行:跳转到nand_read_ll函数,它是用C语言写的拷贝函数(略)。此时寄存器rO,rl,r2是传递给函数nand_read_ll的三个参数。

程序这样设计的缺点是不论VIVI映像有多大,它都会拷贝128KB的代码量,这样造成时间及空间的浪费或者拷贝不完整,为此笔者对上述代码进行改进:

[1]ldr r0,=VIVI_RAM_BASE
[2]ldr r2,=vivi_end
[3]sub r2,r2,r0
[4]mov r2,r2,lsr #9
[5]mov r2,r2,lsr #9
[6]add r2,r2, #0x200
[7]mov r1,#OxO
[8]bl nand_read_ll

代码中用到了外部变量vivi_end,它是在链接脚本文件中定义的,是VIVI映像运行时域的末地址,在此代码中使用前要用如下语句进行声明:

.extern vivi_end

其中:第[l]、[7]、[8]行的解释分别与未改进前的第、<2>、<4>行。第[2]行:获取VIVI映像运行时域的末地址。第[3]行:获取拷贝的真实代码量。第[4],[5],[6]行:上文论述到Nand Flash是按页进行读写的,本文用到的Nand Flash每页有(512+16)Byte,实际用于存储映像文件的是每页的前512Byte。所以需要对上述“真实代码量”进行调整,把它调整为整数页大小,它的大小必须是页对齐的。首先把它的低9位调整为0,即是把代码量不足512Byte的部分清零,然后再加1页(page)大小(Ox200)以保证VlVI数据的完整性,这就是第[4],[5],[6]行的作用。对此代码进行改进后,拷贝的代码量更接近实际的代码量,拷贝的冗余代码量不会达到1页(page)的大小。对于其它类型的Nand Flash可以根据页的大小进行类似的改进。

3.3 程序的跳转

针对本文所论及的系统,当系统加电或复位后,首先Nand Flash中的前4KB由硬件拷贝到位于0x40000000处的大小为4KB的内部SRAM中,然后此SRAM被映射到BankO处(Ox00000000)。PC从0x00000000处取指令执行。当遇到B或BL等跳转指令时,它会跳到当前地址加上一个偏移量的位置,它们属于相对跳转,它们的跳转范围是±32 MB,这使得B或BL指令不依赖于代码的存储位置,此时这些地址为加载时域的地址。在嵌入式系统中,还有一种实现长跳转的方式,就是使用ldr指令,它町以实现程序的绝对跳转,跳转范围为4G空间。

VIVI中实现程序跳转的代码为:

@jump to rain
ldr r1.=on_the_ram
<2>add pc, r1, #O
<3>1: blb@ infinite loop
<4>on_the_ram:

上文提到了加载时域与运行时域的概念,此时第<1>行获取的on_the_ram的地址就是运行时域的地址,此地址由上述链接脚本文件决定,第<2>行跳转到SDRAM中的on_the_ram处。

为了进一步深入说明程序的跳转,可以利用VIVI的反汇编文件来查看上述代码的反汇编情况。现分别给出此段代码下载时域和运行时域的存储布局。

下载时域此段代码在内部SRAM中的存储布局为:

<1>000000dc: e59f1278 ldr rl,[pc,#278];0x35c
<2>000000eO: e281f000 add pc,rl,#0
<3>000000e4: eafffffeb Oxe4
<4>000000e8
...
<5>00000358:000055aa andeq r5,rO,r10,lsr #ll
<6>0000035c: 33f000e8 mvnccs rO.#240

运行时域此段代码被拷贝到SDRAM中的存储布局:

[1]33fOOOdc: e59f1278 ldr r1,[pc,#278]
[2133f000eO: e281f000 add pc,rl,#0
[3] 133mooe4: eaffffffeb Oxe4
[4]33fOOOe8
...
[5]33f00358: 000055aa andeqr5,rO,r10,lsr #11
[6]33f0035c: 33fOOOe8 mvnccs rO,#240

系统加电或复位从基地址0x00000000运行到上述代码的第<1>行时,r1获得地址0x0000035c处的值,从第<6>行知道此地址处的值为33f000e8,运行到第<2>行处,进行跳转,由于此时程序映像已经拷贝到SDRAM中,程序就跳到了运行时域此段代码的第[4]行处断续执行下面的程序,从而实现了程序从SRAM到SDRAM的跳转。

4 结语

Boot Loader的设计是嵌入式系统中的重要环节,它为系统的正常启动完成了一系列的初始化工作,设计一个简单高效功能强大的Boot Loader是嵌入式系统设计中一项重要工作。

本文的创新点:深入研究和分析了VIVI如何实现自己拷贝以及拷贝后如何实现程序的跳转,并给出了原理性和实验性的说明;<2>对程序进行了改进,主要体现在拷贝的代码量上及VIVI的链接脚本上,使程序设计更合理。

上一页 1 2 下一页

关键词: NandFlashVIVI装载

评论


技术专区

关闭