Nand Flash的VIVI装载器的分析与改进 (转)

引言

  在操作系统启动前,要先运行一段程序.这段程序就是BootLoader,即启动装载程序,它相当于PC机上的BIOS。通过这段程序,可以实现硬件设备的初始化,建立内存卒问映射等一系列初始化工作,从而将系统的软硬件环境初始化为一个合适的状态.以便为装载操作系统作好准备。在系统加电或复位后,CPU通常都是从一个预先定义的地址上取指令,而在嵌入式系统中,通常将某种类型的固态存储设备(如ROM、FIash等)映射到此地址处。通过烧写工具把BootLoader的映像烧写到这种固态存储设备上,在系统加电或复位后CPU就可以从这种固态存储设备上取指令执行BootLoader以实现系统的启动。由于在ROM及Flash等存储设备中程序的执行速度与效率不及程序在RAM中的执行速度与效率,因此在嵌入式程序设计中,通常都会有程序拷贝的操作。所谓程序拷贝,就是在程序运行过程中,通过软件的方法将周化在ROM或Flash中的程序拷贝到RAM中,然后再跳转到RAM相应地址继续执行程序。

  1 系统硬件平台及VIVI简介

  本实验平台的处理器采用的是SamSung公司的S3C2410.它是基于arm920T内核的处理器,片外存储器采用了64MB的SDRAM、32MB的Nand Flash、2MB的Nor Flash及4KB的片上SRAM,其中SDRAM映射到基地址为Ox30000000的存储空间,本实验平台支持两种方式启动,即Nand FIash启动和Nor Flash启动,这两种启动方式以跳线方式进行选择。

  VIVI是由韩国Mizi公司开发的一种针对arm9的BootLoader,支持S3C2410。与其它的Boot loader相比,它具有容易理解,易于移植等优点。它有两种工作模式:启动加载模式和下载模式。它的启动分为两个阶段,Stage1阶段和Stage2阶段。Stage1主要用汇编语言编写,主要进行与CPU核有关的一些寄存器的配置以及进行一些必要的初始化工作,这部分代码与具体的CPU体系结构依赖性很大。Stage2用一般的C语言编写,用来实现一些初始化工作,如建立内存映射,初始化驱动等,这部分代码会被拷贝到RAM中执行。本文要研究和论述的主要在Stage1阶段。

  2 Nand Flash启动过程分析

  Nand Flash使用I/O口串行地存取数据,它不映射到存储空间中任何一个BANK区域上.对Nand Flash的渎写操作通过串行数据总线进行传输。Nand Flash以页(page)为单位进行读写,以块(block)为单位进行擦除,本文用到的Nand Flash页(page)大小为(512+16)Byte,块(block)大小等于32个页的大小。每页的最后16Byte不用于存储程序数据,它主要用于存储ECC校验、标志位等信息。对Nand Flash的操作主要是通过向Nand F1ash控制器发送命令来进行的,对不同型号的Nand Flash,其命令有所不同。由于Nand Flash以块(block)为单位进行擦除,以页为单位进行写入,所以擦除与写入的速度都很快。

  由于Nand Flash不能芯片内执行,S3C2410必须提供一种机制支持从Nand Flash启动。S3C2410提供了这样一种机制,当设置为Nand flash启动时,系统加电或复位后,使能Nand Flash控制器的自动启动模式,Nand Flash中的前4KB代码自动地被拷贝到位于CPU内部的称为Steppingstone的SRAM中,这是启动代码的第一次拷贝,这次拷贝由硬件自动完成.然后这块SRAM被映射到存储空间中的0x00000000处,CPU从这个地址处开始执行启动代码。

  由于CPU内部的SRAM仅有4KB,不能保证整个VIVI都被从Nand Flash中拷贝到CPU内部的SRAM中,所以这前4KB的代码要保证完成把整个VIVI从Nand Flash拷贝到执行效率更高的RAM中运行以及程序的跳转任务,此时从Nand Flash到SDarm的拷贝过程就是所谓的软件拷贝。

  3 程序拷贝过程分析

  3.1 VIVI的编译与链接

  编泽器对程序的处理要经过预编译阶段、编译阶段、汇编阶段及链接阶段,每个目标文件都有一系列段(section),输入文件的段(section)称为输入段(input section).输出文件的段(section) 则称为输出段(output section)。在VIVI的链接过程中,用到了一个链接脚本文件,它描述了各个输入文件的各个段(section)如何映射到输出文件的各个(section)中,并控制输出文件中secrion和符号的内存布局,此内存布局决定了VlVI的运行时域。在此阶段,链接器LD利用链接脚本把各种目标文件和库文件链接起来,并重定向它们的数据,完成符号解析,最后把所有的目标文件链接成为一个可执行的目标文件,即为可烧写到Flash中的VIVI映像。针对本系统开发板的VIVI链接脚本对原链脚本进行了改进,添加了第<6>行,下文的论述会用到此处的变量vivi end。

 

  <1>SECTIONS{

  <2>.=0x33f00000;

  <3>.text   :{ * (.text)}

  <4>.data ALlGN(4) :{ * (.data)}

  <5>.bss ALIGN(4):{ * (.bss) * (COMMON)}

  <6>vivi_end=.:

  <7>}

 

其中:SECTIONS表示段。第<2>行表示当前地址为0x33f00000,它是text段的起始地址,也是运行时域的起始地址。第<3>行用了通配符*表示所有字符,这里的意思就是说指定的每个目标文件的text section的内容都放到同一个.text中。第<4>行表示指定的每个目标文件的data section的内容都放到问一个.data中,而且要四字节对齐。每<5>行表示指定的每个目标文件的bss section的内容都放到同一个.bss中,所有的普通符号都放到COMMON中,也要四字节对齐。第<6>行是把当前地址赋值给变量vivi_end,它也是运行时域的末地址。

  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: b  lb  @ 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: eafffffe  b 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]

  [2]133f000eO: e281f000 add pc,rl,#0

  [3]133mooe4: eaffffffe  b Oxe4

  [4]33fOOOe8 :

  ...

  [5]33f00358: 000055aa andeq  r5,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的链接脚本上,使程序设计更合理。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: CPU和NANDflash控制是两种不同的芯片,分别用于不同的功能。 CPU是中央处理的缩写,是一种用于执行计算机指令的芯片。它是计算机的核心部件,负责处理和执行各种计算和控制任务。CPU通常包括运算、控制和寄存等组件,能够执行算术逻辑运算、数据传输和控制操作等任务。它是计算机系统中最重要的部分,对于整个系统的性能和功能起着至关重要的作用。 NANDflash控制是一种特定类型的控制芯片,用于管理和控制NANDflash存储的操作。NANDflash是一种非易失性存储,具有高密度和较低成本等特点。NANDflash控制负责处理与NANDflash存储的交互,包括读取、写入和擦除等操作。它管理数据的读取和写入过程,并确保正确的数据传输和存储。 CPU和NANDflash控制具有不同的功能和作用。CPU主要负责计算和控制任务,控制整个计算机系统的运行;而NANDflash控制则专门用于管理和控制NANDflash存储的读写操作。两者在计算机系统中各司其职,相互配合,实现计算和存储的高效运行。 总之,CPU和NANDflash控制是两种不同的芯片,用于不同的功能。CPU用于执行计算和控制任务,而NANDflash控制用于管理和控制NANDflash存储的操作。 ### 回答2: CPU是中央处理的简称,它是电脑中最重要的组件之一。CPU可以执行各种计算、控制和处理任务,并且是电脑系统的大脑。CPU通过从内存中读取指令、执行运算和控制外部设备来完成各种操作。 NAND闪存控制是负责管理和控制NAND闪存芯片的硬件。NAND闪存是一种非易失性存储,广泛用于各种设备,例如闪存驱动、SSD等。NAND闪存控制负责处理闪存读取、写入、擦除等操作,并管理闪存中的数据块、页面和块的擦除计数等信息。它还负责管理闪存中的逻辑地址与物理地址的映射关系,以及错误检测和纠正,确保数据的可靠性和一致性。 CPU与NAND闪存控制之间有着密切的协作关系。当CPU需要读取或写入数据到闪存时,它通过与NAND闪存控制进行通信,发送相应的指令和地址信息。NAND闪存控制接收到指令后,负责从闪存中读取数据,并将数据传输给CPU,或者将CPU发送的数据写入到闪存中。 此外,CPU还可以通过与NAND闪存控制进行协作,实现一些高级的功能。例如,可以通过特定的命令和协议实现闪存中数据的压缩、加密或解密等操作。CPU还可以与NAND闪存控制一起处理闪存的错误纠正,通过检测和修复数据中的错误位,提高数据的可靠性和稳定性。 综上所述,CPU和NAND闪存控制之间的合作关系至关重要,它们共同协作完成数据的读取和写入,为电脑系统和其他设备提供高效、可靠的存储解决方案。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值