Chinaunix首页 | 论坛 | 博客
  • 博客访问: 430705
  • 博文数量: 56
  • 博客积分: 2262
  • 博客等级: 大尉
  • 技术积分: 711
  • 用 户 组: 普通用户
  • 注册时间: 2007-12-08 20:04
文章分类

全部博文(56)

文章存档

2013年(1)

2012年(9)

2011年(10)

2010年(7)

2009年(7)

2008年(22)

我的朋友

分类: 嵌入式

2011-01-25 17:53:30

经过几天的分析和搜索,终于实现了S3C2416+WinCE平台下的SD卡下载升级功能。实现烧写文件分别为block0img.nb0、EBOOT.bin、nk.bin。
    简单记录一下实现过程,以免以后忘记了。
    要实现这个功能首先得知道S3C2416+WinCE平台的Bootloader流程,之前转载的一篇文章叫做《Samsung的ARM处理器iROM启动模式介绍》,文中介绍了S3C6410使用IROM启动的流程。
 
    block0img.nb0中包含有两个loader,他们的加载顺序如下图:
 
    进入EBOOT之后,首先运行的是Main函数,Main函数的实现非常的简单:
 
void main(void)
{
    //MemoryTest_Function();
    BootloaderMain();
    // Should never get here.
    SpinForever();
}
   所以实际的下载和启动等过程都是在BootloaderMain中完成,这个函数微软已经为我们写好了,当然我们也可以拷贝出来自己更改,在WINCE600\PUBLIC\COMMON\OAK\DRIVERS\ETHDBG\BLCOMMON\blcommon.c目录下有实现源码,在WINCE600\PLATFORM\COMMON\SRC\COMMON\BOOT\BLCOMMON\blcommon.c目录下也有一份相同的代码,在Eboot中具体使用的哪个就要看Sources文件了。
    因此跟踪BootloaderMain函数看下去:
  BootloaderMain
    =>KernelRelocate:把镜像中的全局变量Copy到Ram中,该过程完成之后,其他模块才能正常访问保存的全局数据
    =>OEMDebugInit:OEM需要实现的函数,一般来讲是串口调试信息等初始化
    =>OEMPlatformInit:这个函数就是我们非常熟悉的OEM平台初始化了, EBoot的菜单选项就在这个里面实现的。
    =>OEMPreDownload:根据用户在菜单中的选择,判断是下载还是直接启动。
    =>DownloadImage:这里就是主要的下载过程,首先会判断下载的文件类型,并解析bin格式的文件
      =>GetImageType => OEMReadData读取前面7个字节做比较,具体可以参考blcommon.c文件。
      这个里面的OEMReadData就是实际的读取我们下载到的数据的操作。后面有我的实现代码。
    =>OEMLaunch:这里面实现了flash的写入
BOOL OEMReadData(DWORD dwData, PUCHAR pData)
{
    BOOL ret;
    OALMSG(OAL_FUNC, (TEXT("+OEMReadData.\r\n")));
    if ( g_dwDownloadDevice == DOWNLOAD_DEVICE_NONE )
    {
        ret = EbootEtherReadData(dwData, pData);
    }
    else if ( g_dwDownloadDevice == DOWNLOAD_DEVICE_USB )
    {
        ret = USBReadData(dwData, pData);
    }
    else if ( g_dwDownloadDevice == DOWNLOAD_DEVICE_SD )
    {
        ret = SDReadData(dwData, pData);
    }
    return(ret);
}
    在实际操作过程当中,实际已经将SD卡的文件读取到内存的BUFFER当中,可以在OEMPreDownload中实现,调用SDReadData实际是读取内存当中的数据。经过实现,如果不将数据读取到内存当中会出现校验出错,原因还有待分析。
   
    总结一下,要实现SD卡文件下载,只需要在原有boot代码的基础上实现SD卡文件读取到BUFFER的函数(ReadFileFromSD),和OEMReadData即可,下面一段代码是我从SD卡读取文件到BUF的代码:
 

 

BOOL ReadFileFromSD( const char *sFileName, UINT32 dwImageType, BYTE *Buffer )
{
    ULONG nFileNumber;
    ULONG i;
    BYTE * ptxBuf;
    unsigned int nCheckSum = 0;
    ULONG fileSize;
    FILEINFO hFile = {0};

    if (!FATOpenFile(&hFile, sFileName))
        return FALSE;

    EdbgOutputDebugString("Reading '%s' from SD Card, Waitting\r\n", sFileName);
    EdbgOutputDebugString("Please don't remove Card\r\n");

    if ( dwImageType == UBIIMAGE || dwImageType == BINIMAGE )
    {
        fileSize = FATGetFileSize (&hFile);
        if ( !fileSize )
        {
            EdbgOutputDebugString("%s file Get size Error\n", sFileName);
            return FALSE;
        }
        FATReadFile(&hFile, Buffer, fileSize);

        g_pDownPt += fileSize;

        EdbgOutputDebugString("Read from Card OK\r\n");
    }
    else if ( dwImageType == NB0IMAGE || dwImageType == DIOIMAGE )
    {
        nFileNumber = 1;

        memset((void *)Buffer, 0, 7+4+4+4+4+MAX_PATH);

        ptxBuf = Buffer;
        
        *(ptxBuf++)=0x4E;//N000FF\x0A

        *(ptxBuf++)=0x30;
        *(ptxBuf++)=0x30;
        *(ptxBuf++)=0x30;
        *(ptxBuf++)=0x46;
        *(ptxBuf++)=0x46;
        *(ptxBuf++)=0xa;

        fileSize = FATGetFileSize (&hFile);        //nb0 filesize

        // Read nb0 file

        if (!FATReadFile(&hFile, (BYTE *)(Buffer+7+4+4+4+4+MAX_PATH + 1), fileSize))
        {
            RETAILMSG(1,(TEXT("#### File READ ERROR\r\n")));
            while(1);
        }
        // 缓冲区字节对齐读取后,数据被后移一个字节,拷贝回来

        memcpy(Buffer+7+4+4+4+4+MAX_PATH, Buffer+7+4+4+4+4+MAX_PATH + 1, fileSize);

        ptxBuf = Buffer + 7 + 4 + 4;

        *(ptxBuf+0) = 0;                //nb0 start address == 0

        *(ptxBuf+1) = 0;                //nb0 start address == 0

        *(ptxBuf+2) = 0;                //nb0 start address == 0

        *(ptxBuf+3) = 0;                //nb0 start address == 0

        
        *(ptxBuf+4) = (BYTE)((fileSize >> 0) & 0xff);
        *(ptxBuf+5) = (BYTE)((fileSize >> 8) & 0xff);
        *(ptxBuf+6) = (BYTE)((fileSize >> 16) & 0xff);
        *(ptxBuf+7) = (BYTE)((fileSize >> 24) & 0xff);

        strcpy((char *)(ptxBuf+8), sFileName);

        nCheckSum = 0;
        for ( i = 0; i < 4+4+MAX_PATH; i++ )
        {
            nCheckSum += (unsigned char)(*(ptxBuf+i));
        }

        ptxBuf = Buffer+7;

        *(ptxBuf+0) = (BYTE)((nCheckSum >> 0) & 0xff);
        *(ptxBuf+1) = (BYTE)((nCheckSum >> 8) & 0xff);
        *(ptxBuf+2) = (BYTE)((nCheckSum >> 16) & 0xff);
        *(ptxBuf+3) = (BYTE)((nCheckSum >> 24) & 0xff);
        
        *(ptxBuf+4) = (BYTE)((nFileNumber >> 0) & 0xff);
        *(ptxBuf+5) = (BYTE)((nFileNumber >> 8) & 0xff);
        *(ptxBuf+6) = (BYTE)((nFileNumber >> 16) & 0xff);
        *(ptxBuf+7) = (BYTE)((nFileNumber >> 24) & 0xff);

        g_pDownPt += (7+4+4+4+4+MAX_PATH);
        g_pDownPt += FATGetFileSize (&hFile);
    }
    else
    {
        EdbgOutputDebugString("SDInterface Parsing param error!!!\r\n");
    }

    FATCloseFile(&hFile);
    return TRUE;
}

 

   其实大部分的功能实现都是仿照USB下载来完成的,如果EBOOT中没有USB下载可以仿照,也可以仿照网络下载,实现方式都是大同小异。只是FAT文件系统和SD读写需要自己实现。


 

阅读(4002) | 评论(2) | 转发(0) |
给主人留下些什么吧!~~

chinaunix网友2011-07-08 18:25:13

哎呀,最近也在研究这个东西,能不能提供点代码给我看看啊? xiaowye@gmail.com

chinaunix网友2011-03-07 13:47:31

很好的, 收藏了 推荐一个博客,提供很多免费软件编程电子书下载: http://free-ebooks.appspot.com