MergeFile下载(微软SkyDrive):
http://cid-a0a942ebd8c6c3b5.office.live.com/self.aspx/.Documents/MergeFiles.rar
一般来说,现在的ARM Linux嵌入式系统都是将Image拷贝到SDRAM中进行运行的标准方式,尤其是像S3C6410和S3C2410这些支持NAND Flash的处理器,一般硬件设计直接把NOR Flash都省了,更是必须在SDRAM中运行。
可是存在就是合理的,XIP作为一项古老的技术,还是有一定的用处的,比如可以减少开机等待时间,也可能可以增加电池寿命,当然这个都是有条件的,在Intel的《creating optimized XIP systems》
elinux.org/upload/d/dd/CELF-XIP_Linux.pdf 这个pdf上有详细的介绍。
不过在我这个EVB板子上,最现实的原因就是RAM太少了,总共只有8M,而我编译的内核就有2.5M左右,加上系统运行驻留的Init等进程已经动态库,内存所剩无几。
打开XIP还是很简单的,Linux 2.6.32.15在这上面做的还是相当好的,只需要打开内核编译的XIP选项,填入内核在NOR Flash中的地址即可,比如我的0x80000,编译以后就会在arch/arm/boot下面生成一个叫xipImage的文件,将这个文件烧录到Flash中的对应位置就OK了。
在我的系统中,由于要使用现有的EVB的bootloader,并且只烧录在CP段,因此就必须自己做一个bootloader来引导Linux,系统启动时先运行EVB自己的bootloader,然后跳到这个Linux Bootloader,copy文件系统(目前是RAMDISK),设置TAG,命令行,启动的寄存器等,跳到Flash中相应位置开跑。
为了将Linux bootloader, xipImage和RAMDISK整到一个Image中以便使用ETS烧写,在Cygwin下面写了一个小程序mergefile来完成合并的工作。mergefile使用一个配置文件进行配置,配置文件类似于Windows的.ini 文件,
[OUTPUT]
#The number of file to be merged.Example, if FileCount=10 you should have sections INPUT0....INPUT10
FileCount=3
FileName=cp.rom
#total size is 10M bytes.
TotalSize=10485760
[INPUT0]
FileName=lboot.rom
BaseAddress=0
[INPUT1]
FileName=xipImage
BaseAddress=0x40000
[INPUT2]
FileName=mmufs.cramfs
BaseAddress=0x3C0000
其中OUTPUT段是控制输出的,FileCount表示要合并的文件数量,比如例子中是3,就对应3个Input段,然后是输出文件名和总的大小。后面输入段包括每段的文件名和在输出文件中的基址。
解析这个配置文件使用的是MiniGUI里面的读取MiniGUI.cfg的函数GetIntValueFromEtcFile和GetValueFromEtcFile及其子函数。想想也是蛮有意思的,2003年第一次接触MiniGUI的时候就把这两个函数移植来读取我们的工控设备的配置参数,7年过去了,再次用起了这两个函数。不过那当时的Feyman还在创始人魏永明先生的家里上班,而且还只支持带MMU的Linux,现在都做了这么多年了,还做得不错,绝大部分操作系统都支持。因此坚持并精益求精的做一件事是多么的重要!
mergefile的处理过程是:先读取配置文件,知道了输入和输出的信息,开一个输出文件大小的outputbuffer(比如10M),然后把输入文件通过mmap都map到内存中,用memcpy拷贝到outputbuffer中对应的基址开始的位置上,所有输入文件都拷贝完毕后,把outputbuffer写到输出文件即可。这样做的目的,一方面是输出文件大小不会太大,现在计算机内存都1G以上,所以开个大buffer也无所谓了,而且mmap把文件映射成内存后,都是内存操作,代码写起来相当的快捷。
由于MiniGui的配置参数是以Linux的标准0x0A结束行的,而Windows上是以0x0D0A结束的,因此MiniGUI那两个函数的底层还要修改一下,以便同时支持在Linux和Windows上修改配置文件。