S3C2450自动升级
在BSP包中,有两个bootloader文件夹,一个命名为bootloader,另一个命名为bootloader_update。Bootloader文件夹用于USB下载,调试用,bootloader_update用于生产,自动升级用。下面重点介绍bootloader_update文件夹。
Bootloader_update文件夹下有四个文件夹,分别是BLCOMMON,Eboot_boot,FAT_LIB以及IROM_SD_TOOL。BLCOMMON文件夹编译后生成oal_blcommon.lib文件,供Eboot_boot调用。FAT_LIB文件夹里面包含三个静态库文件FAT_LIB.lib,HSMMCEBOOT_LIB.lib以及SDREAD_UPDATE.lib。这些静态库封装了一些用于升级的函数。Eboot_boot文件夹编译后将会产生生产用的Eboot.bin文件,该文件即能够启动系统,也能够通过硬件平台的按键控制,实现自动升级。IROM_SD_TOOL文件夹编译后,会将前面的Eboot.bin文件封装成SD卡识别的程序,最终生成IROM_SD_EBOOT.nb0。通过三星提供的IROM_Fusing_Tool工具,将该文件烧到SD卡后,2450平台就能够实现从SD卡启动了。当然前提是硬件本身要设置跳线成SD卡启动。
主程序中(Eboot_boot文件夹)定义了三个重要的变量:AUTO_UPDATE_FROM_SD;
ERASE_ALL_FLASH_BLOCKS;
SHOW_UPDATE_LOGO。
当AUTO_UPDATE_FROM_SD为真时,Eboot将会进入升级程序,为假时将引导flash中的NK,启动系统。
当ERASE_ALL_FLASH_BLOCKS为真时,Eboot将会格式化flash,然后依次升级block0.nb0,eboot.bin,nk.bin,随后启动系统。
当SHOW_UPDATE_LOGO为真时,LCD上将会出现升级文件的提示,否则显示开机LOGO。
其中AUTO_UPDATE_FROM_SD标志位通过硬件平台的按键判断,当拨动电源键后在两秒之内回拨到LOCK位置,Eboot将识别到该LOCK标志,这时将AUTO_UPDATE_FROM_SD置高,程序进入升级状态。
ERASE_ALL_FLASH_BLOCKS标志位通过从SD卡中的update.txt文件中读取。
AUTO_UPDATE_FROM_SD的相关代码如下:
其中_FAT_Boot_ReadFile()函数用于从SD卡中读取_UPDATE_FILE_DETECT文件,该字符串在最前面有如下定义:
#define _UPDATE_FILE_DETECT "DETECT BIN"
auto_updatekey_isPressed()函数用于检测拍照键是否按下,从这里可以看出,如果SD卡中存在detect.bin文件,则升级时不用再按住拍照键了。如果没有则必须按住拍照键。
Flash格式化的程序如下:
下载映像的函数如下:
上面程序中有如下代码:
OEMShowProgress (nPkgNum ++);
while( nPkgNum>=8 )
{
nPkgNum = 0;
LcdDrawString(">");
}
该程序放在反复从SD卡中读取xip.bin的一条条记录的while循环中,这里是为了在升级界面上显示升级的进度。LcdDrawString(“>”)函数是调用了LcdDraw.c中的函数,用于在LCD上绘图。
这里一定要了解xip.bin的文件格式,否则很难理解整个数据流的流程。
Xip.bin以及NK.bin的组成:
组成:标记(7)+Image开始地址(1)+Image长度(1)
记录0地址+记录0长+记录0校验和+记录0内容(文件内容)
记录1地址+记录1长+记录1校验和+记录1内容(文件内容)
......
结束符号
从上面的程序可以看出,
if (!OEMReadData (BL_HDRSIG_SIZE, hdr))
{
EdbgOutputDebugString ("/r/nUnable to read image signature./r/n");
HALT (BLERR_MAGIC);
return (FALSE);
}
即是将xip.bin的前7个字节的数据读到数组hdr,供后面分析所读的文件的类型。
if (!OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageStart)//读取*.bin前7个头字节后的一个DWORD到dwImageStart。*.bin记录了其映像起始地址
|| !OEMReadData (sizeof (DWORD), (LPBYTE) &dwImageLength))//读取上面接着的一个DWORD到dwImageLength。*.bin记录了其映像长度
{
EdbgOutputDebugString ("Unable to read image start/length/r/n");
HALT (BLERR_MAGIC);
return (FALSE);
}
则是将紧接着前7个字节的两个WORD数据读到dwImageStart和dwImageLength。随后的
while (OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecAddr) &&
//读取*.bin的第n条记录的地址.
OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecLen) &&
//读取*.bin的第n条记录的长度.
OEMReadData (sizeof (DWORD), (LPBYTE) &dwRecChk))
//读取*.bin的第n条记录的校验和.
则开始一条条的解析xip.bin的记录。
if (!OEMReadData (dwRecLen, lpDest))
{
EdbgOutputDebugString ("****** Data record %d corrupted, ABORT!!! ******/r/n", nPkgNum);
HALT (BLERR_CORRUPTED_DATA);
return (FALSE);
}
用于将读取到的第N条记录存放到lpDest.
分析要下载的文件并写入flash的代码如下:
整个bootloader代码量大,但是细下心来慢慢分析,其实不难理解。这里就不一一分析了。