汤雅妃
(电子科技大学自动化工程学院,四川 成都 610054)
在一些脱机运行的系统中,系统上电后必须先初始化某些硬件,然后从非易失性存储器中将程序移植到系统内部高速存储器中执行,实现这部分功能的程序块叫BootLoader。它的作用是实现整个系统的启动任务装载,包括初始化硬件设备、建立内存空间的映射图,从而将系统的软硬件环境带到一个合适的状态,以便最终系统正常运行[1]。大多数 BootLoader都包含两种不同的操作模式(Operation Mode),启动装载模式和下载模式[2]。两者的区别在于前者是BootLoader从目标机上的固态存储设备上将程序装载到CPU内部RAM中运行,它属于正常的工作模式,一般应用于产品的发布,而后者是目标机上的BootLoader从主机下载文件并写入固态存储设备,应用于产品的升级[3]。
一般的嵌入式操作系统都有自带的启动装载模块如基于Linux的U-Boot,而在没有操作系统的系统中就需要自己编写BootLoader程序。该设计用于无操作系统数字存储示波器的启动装载。BootLoader程序通过检测系统特定标志位来实现不同的装载模式。正常模式下BootLoader初始化硬件,装载Flash中的程序到SDRAM中并启动系统。当用户选择在线升级时系统将更改特定标志位的值,重启系统后BootLoader即进入下载模式,通过USB读入正确的更新文件并写入Flash,同时BootLoader更改程序指针,重启系统后将从新地址启动装载程序。该文提出了一种存储BootLoader文件的新思路,减少了Flash的烧写时间并节约了Flash的空间。
如图1所示,系统程序在编译之后会生成一个以.dxe为后缀的可执行文件,然后由Elfloader.exe将Dxe文件擦除,按照Ldf规则生成以.ldr为后缀的可装载文件。Ldr文件一般包括一个Init Block和N个其他的Block。需要Init Block的主要原因是为了初始化硬件。每个Block前面都有一个大小为10个字节的Header,包括32位的地址Address,32位的文件长度信息Count,还有16位的标志信息Flag,启动装载的第一阶段需要用到这些信息。其中Address指定要装载程序的目的地址,Count指定拷贝的文件长度(以字节为单位),Flag指定BootLoader的运行方式。LDR文件存储格式见图1。
图1 LDR文件存储格式
BootLoader一般固化在系统CPU内部非易失存储器中,在此设计中它存放在BF531片内ROM中,起始地址为0XEF000000。上电后BootLoader首先接管系统,进行一些最基本的上电自检后,BootLoader将对系统的硬件如UART、GPIO、SDRAM进行初始化;如果系统的程序不是存放在目标机的ROM或者Flash中的,而是存放在磁盘、U盘、SD卡、CF卡中的,BootLoader还必须初始化好这些硬件设备。接下来,BootLoader需要将系统的程序拷贝到主存储器的特定地址,最后BootLoader将控制权交给系统,由系统完成接下来的工作。
BF531 BootLoader步骤如下:第一阶段,系统上电后片上引导存储器从复位中断复位程序返回并设置为管理员模式(Supervisor Mode)(在Bypass Mode下屏蔽此步骤),然后系统根据系统复位配置寄存器(SYSCR)第四位的值判断是否为软件复位,如果是软件复位,系统会屏蔽掉所有启动装载操作,程序指针跳转到0XFFA08000(L1存储器的起始地址)执行,否则程序会继续BootLoader的流程,根据BMODE状态选择用户设置的一种BootLoader方式,从外部存储器0x.0地址段读取前4个字节(这4个字节包含有需要导入程序的字节长度信息N),然后导入这N字节程序到以0xF000 0000开始的L2存储器,最后跳转到L2存储器开始执行。如果程序分多段存放在L1存储器或L2存储器或者SDRAM中就必须有第二阶段装载,首先复位后片上引导ROM会下载N字节(第五阶段装载程序)程序到以0x F000 0000起始的外部L2存储器中,然后第二阶段装载程序自我复制到L2存储器的底部,第二阶段的装载程序引导应用程序或数据到BF531的其他存储器,最后,引导后第二阶段装载程序跳转到L2存储器的起始处开始执行应用程序。
设计采用两个不同的工程来实现数字存储示波器系统的BootLoader及基本测量功能。工程1为BootLoader程序,用来完成程序装载及更新,存放在起始地址为0X20000000的存储区;工程2为示波器程序,用来实现示波器系统功能,存放在起始地址为0X20010000的存储区。ROM里面的BootLoader程序是利用MDMA顺序地读取Flash中的数据,然后根据Header文件,将数据搬移到指定的存取区域。由于两个工程存放在不同的存储区,因此在读完和调用了Init Block后,BootLoader需要跳转到工程1或2的存储地址去读取余下的Block[4]。
系统上电后BootLoader会检测特定标志位以选择不同的装载模式,这个标志位根据用户的操作设置不同的值。正常模式下BootLoader读取BMODE选择用户设置的BootLoader方式(该系统中BMODE设置为从16位Flash装载程序运行),然后直接初始化,GPIO,SDRAM,把Flash中的程序移植到SDRAM中指定地址段,程序指针跳转到此地址开始执行。当用户选择在线升级时,特定标志位的值会改变,用户插入U盘后重启系统,BootLoader检测到该标志位不是默认值后就会转入在线升级模式,对U盘里的文件进行一系列检测判断[5],将合适的更新文件写入Flash中同时更改BootLoader装载模式标志位,重新之后又回复到正常装载模式。其程序流程见图2。
图2 数字存储示波器BootLoader程序流程图
Init Block程序前面省略了PLL、SDRAM的初始化程序,最后的一段代码则是对Init Block程序的修改,让它符合实现程序更新的要求。经过详细分析ROM里面BootLoader的汇编代码,发现MDMA读取数据的源地址是由R0寄存器来控制的,所以需要在Init Bloack中改变R0的值,调用完成返回后,R0便会修改MDMA的源地址,使它指向正确的地址。需要指出的是,在Init汇编代码的开始和结尾需要保护现场和恢复现场,否则无法在调用后正确修改R0的值。
BootLoader是嵌入式系统程序的重要组成部分,用以实现硬件初始化并引导系统程序。该文分析了嵌入式系统BootLoader两种模式的区别和实现原理,介绍了ADI公司BF531的BootLoader流程,在此基础上提出了基于BF531的无操作系统数字存储示波器的BootLoader设计。该设计将系统程序分为两部分,初始化部分放在BootLoader中,这样更新时只需要更新数字示波器的程序,缩短了更新时间,节省了Flash空间。经测试,此设计能实现数字示波器系统的正常启动装载模式和在线升级,且用户界面友好,功能可靠。
[1]李兰英,刘 洋,姜秀丽.嵌入式系统Bootloader的设计与实现[J].电脑学习,2006(6):35-36.
[2]聂俊航,邱 辉.Bootloader的分析和设计[J].微处理机,2006,27(4):82-84.
[3]邵新颜,蔡梅琳.在Bootloader中实现嵌入式系统自动升级[J].单片机与嵌入式系统应用,2006(11):33-34.
[4]陈 峰.Blackfin系列DSP原理与系统设计[M].北京:电子工业出版社,2004:120-255.
[5]胡晓军,张爱成.USB接口开发技术[M].西安:西安电子科技大学出版社,2005:117-132.