DM646x的启动程序备份机制实现
由于现在嵌入式系统较多使用nand flash,而nand flash存在一定的数据损坏概率,所以需要实现关键启动程序的备份功能,以在nand flash出现了部分数据损坏的情况下,仍然能启动系统,继续运行,或者提供远程修复的基本功能。对于TI的davinci平台,一般启动过程如下:
Rbl->[ubl->] uboot->kernel->rootfs->用户程序
注:nor flash上的启动,不需要ubl。
在Nand flash上的启动过程:
首先运行芯片中的Rbl,然后运行nand flash上的ubl,再启动uboot,加载kernel,使用rootfs,运行用户可执行程序。
本文对启动部分的备份机制分2部分介绍:ubl与uboot,kernel与rootfs。
第一部分,ubl与uboot的备份
下面对ubl与uboot的备份方法进行研究,主要是回答了下面几个问题:
1,为何使用ubl?
2,如何获得ubl与uboot?
3,ubl与uboot是如何写入的?
4,ubl与uboot写在什么位置上?
5,由谁来实现备份使用功能?
6,具体如何实现备用功能?
1,为何使用ubl?
(1)由于nand flash不能实现字节读写功能,不能像内存那样随机访问,所以存储在nand flash上的程序,需要复制到内存里,然后才能运行。
(2)芯片上电后,首先运行rbl。rbl是厂家固化在芯片里面的启动程序,做得相当精简,只做最基本的操作,不支持ddr,所以此时只能使用片上内存。
(3)由于片上内存比较小,例如DM646x的为16k,而uboot往往都是100k以上,不能存放到片上内存中。
(4)所以产生了ubl,在DM646x上是14k的,先由rbl搬移到片上内存,然后转移cpu控制权给ubl,由ubl初始化ddr,后面就可以将整个uboot复制到ddr上,转到uboot中运行了。
2,如何获得ubl?
http://sourceforge.net/projects/dvflashutils/files/DM646x/v1.50/
下载下来是个压缩包:DM646x_FlashAndBootUtils_1_50.tar.gz ,这是个串口烧写工具,其中就带有ubl的源码,目录为:
Common\ubl与Common\sft。
这里说明下,Common\ubl目录下的源码能生成最终写入nand的ubl.bin文件。
但是Common\sft也是需要关注的部分,它是通过串口烧写时,串口下载到芯片片上内存部分的程序,其功能基本与ubl是相同的作用,主要是进行ddr的初始化,以便于进行后续需要大内存的操作。简单说,就是要向nand写入多个ubl或者uboot,需要sft的支持。
uboot源码,一般随开发板就带有,也可以在ti的网站上获得,或者在uboot的官网下载。
3,ubl与uboot如何写入的?
通常有两种方法:使用仿真器通过jtag口烧写,或者使用串口烧写工具通过串口烧写。
由于仿真器不是很容易获得的资源,下面我主要就串口方式进行说明:
上一步我们已经获得了串口烧写工具,在GNU目录下有个可执行程序sfh_DM646x.exe,就是我们的串口烧写工具。将设备的串口与PC连接,在windows的命令行执行如下命令即可:
sfh_DM646x.exe -nanderase (擦除nand)
sfh_DM646x.exe -nandflash ubl_DM646x_nand.bin u-boot.bin (写入ubl与uboot)
4,ubl与uboot写在什么位置上?
通常,ubl是存放在nand flash的前几个块中,uboot存放在ubl之后。具体的使用情况,在本部分的结尾有一个实例。
5,由谁来实现备份使用功能?
备份的使用,是在默认启动程序有问题的时候,才启用的。而这个判断默认启动程序是否有问题,是需要上一级的启动程序来进行判断的。
例如,ubl的默认启动程序是否异常,需要rbl来判断,出了异常后,如何处理,是否启用备用程序,也是由rbl来决定的。
同样,uboot的备份是否使用,是依赖于ubl程序的。
我们已经获得了ubl的源码,所以,可以修改源码以使其支持uboot的异常判断及备份使用。这里,我们要当心的是rbl是否支持ubl备份的使用,很幸运,TI提供的DM646x的rbl提供了这个功能。
好了,理论工作做完了,下面进入实际操作了。
6,具体如何实现备用功能?
对于ubl与uboot的备份,分析起来步骤很多,其实最后要做的就只是一件事情:
修改sft程序,写入多个ubl与uboot。
其实DM646x_FlashAndBootUtils_1_50 的sft中已经提供了多次写入的机制,只是有点问题,需要修改下代码。在sft源码中,在收到的一个文件后,进行了5次写入操作。但是只有第一次的写入是有效数据,然后指针就跑飞了,后面四次写的是未知数据。只需要修改指针,改为每次都写入有效数据即可。
另外,是否都需要写5个备份,ubl与uboot是否需要备份的个数保持一样,答案都是否定的。我们可以改代码,例如ubl写3个,uboot写2个,都是可以的。
烧写之后的nand存储格局示例:
第0个块 (0-128k)为空。
第1个块 (20000存放块头)保存了ubl ,20800--238ab
第2个块 (40000存放块头),ubl
第3个块 (60000存放块头),ubl
第4个块 (80000),没有块头信息,存放uboot的参数。
第5个块 (a0000存放块头),ubl
第6-7个块 (C0000存放块头), 保存uboot,c0800--e261b
第8-9个块 (100000存放块头), 保存uboot,100800--12261b
第10-11个块 (140000存放块头), 保存uboot,140800--16261b
第12-13个块 (180000存放块头), 保存uboot,180800--1a261b
第14-15个块 (1c0000存放块头), 保存uboot,1C0800--1e261b
第16个块 200000--352c1b 没有块头信息, 存放内核
说明:
我使用的nand flash,一个块的大小为128k,一个ubl为14k,需要一个块来保存;一个uboot为136k,需要两个块来保存。
使用串口烧写工具烧写的数据,前面都有一个头信息,存放在第一个页上面,所以真实的数据,例如uboot.bin的数据,都是从第二个页开始存储的。这些信息,可以通过uboot的nand read命令读出来查看。而内核没有这样占第一页的块头数据,这是由于解析程序没有这样的需求。内核的解析程序是uboot,uboot的解析方式与rbl、ubl不一样。
第4个块,为何存放uboot的参数?在刚完成烧写ubl与boot时,第4个块是存放ubl的。uboot启动参数是在uboot环境下执行“saveenv”后写入的。当然,也可以修改uboot源码,将参数的存放位置转到其它地方。