UT-S3C2416 +wince6.0开机Logo + NAND

以下内容参考自51cto博客的一个帖子,为尊重原创,给出链接http://jazka.blog.51cto.com/809003/664131

http://topic.csdn.net/u/20100126/14/ef1fc7c4-d8db-426b-b6bf-b74d74cdd05a.html


开机后Eboot通过读取NandFlash上的logo.bin,顺利显示并引导系统。

  这个过程大致如下:
  周一:
  1)跟踪分析bootloader源码,通过添加.h文件的方式修改启动界面,但Eboot.bin却烧不进去了。
  2)从技术支持得知,是因为从新编译的Eboot.bin太大——这就有矛盾,要将logo打包在Eboot.bin中,必然增大Eboot,怎么办呢?继续分析Eboot代码。
  周二:
  1)从各方面了解,要将大些的logo(750K)加载在启动界面中,一般的做法是将该logo烧写在
  NandFlash的某个固定位置,然后Eboot启动时从NandFlash读出并加载进显示缓冲区实现。
  2)顺着这个思路,开始研究分析Eboot的NandFlash分区和文件系统。
  周三:
  1)通过分析源码得知:NandFlash的0block放置Nboot,1block放置TOC,2~5block放置
  Eboot,而后被格式化BinFs文件系统放置NK镜像;
  2)思路很清楚,如何将logo.bin烧进6~13block(1M)的位置,而将Binfs文件系统后移,继续
  分析代码。
  周四:
  1)有两个结构体TOC、_IMAGE_DESCRIPTOR成为问题的难点,伴随整个Eboot的执行;其围
  绕.bin文件的生成、烧写位置、NandFlash分区、启动加速;
  2)特别是其特有的.bin文件,前几个字节不仅包含了接收地址、长度、校验和;还包括了要下载
  的地址和长度。
  3)通过修改PB下配置文件,成功将NandFlash分区,专门预留13~19block给logo;
  4)思路很清楚,只要能将logo生成Eboot支持的.bin文件,就能实现下载,通过寻找合适的工
  具、企图利用TOC、_IMAGE_DESCRIPTOR修改PB配置文件实现,但均以失败告终。
  周五:
  1)生成Eboot支持的.bin文件不可以,那修改Eboot来支持自己的.bin文件可以吗?答案是肯定
  的——到这时候才理解了好多前辈对我的建议;
  2)对Eboot修改主要有三处:1)添加自定义下载logo命令;2)修改NandFlash烧写函数;3)添
  加NandFlash读函数。
  3)当然还有相应修改image_cfg.h、loader.h、eboot.bin。
  然后就可以………………………………………………………………………………………………………


1、为了增加后期更加方便的升级开机启动Logo,在启动Eboot的主菜单中添加下载Logo的选项,如下图所示,选项G)便是通过USB下载Logo数据,同时将Logo数据写入到Nand Flash的某一位置上。


2 、在Eboot的初始化InitializeDisplay中,可以找到关于填充显示缓存的代码,改为从Flash的某一位置读取即可。
3、 关于写Logo的数据,可以是bin格式的,也可以是原始的bmp格式。其实bin格式的内容也都是通过读取bmp文件的位图阵列而生成的。两者的差别就在于一个在Eboot里面实现读取bmp的位图阵列,一个是在独立的应用程序中读取的。
4关于操作Nand Flash的位置问题,需要查看loader.h文件的相关代码,有关于Block的使用情况,如下所示。在这里为Logo数据分配一定的Block
5、Flash的读写操作函数实现主要在nand.cpp文件中,具体实现可以参考函数ReadOSImageFromBootMedia和WriteOSImageToBootMedia。

下面给出详细的修改步骤:
      1、首先修改loader.h文件,为Logo数据分配一定的Block空间。添加如下代码:
// NAND Boot (loads into SteppingStone) @ Block 0
#define NBOOT_BLOCK(0)
#define NBOOT_BLOCK_SIZE(1)
#define NBOOT_SECTORBLOCK_TO_SECTOR(NBOOT_BLOCK)


// TOC @ Block 1
#define TOC_BLOCK(1)
#define TOC_BLOCK_SIZE(1)
#define TOC_BLOCK_RESERVED(1)
#define TOC_SECTORBLOCK_TO_SECTOR(TOC_BLOCK)


// Eboot @ Block 2
#define EBOOT_BLOCK(3)
#define EBOOT_BLOCK_SIZE(5)
#define EBOOT_BLOCK_RESERVED(5)
#define EBOOT_SECTORBLOCK_TO_SECTOR(EBOOT_BLOCK)




//-----------------------add by grubly 2011.09.04------------------------- 
//-----------------------------start-------------------------------------- 
// Logo @ Block 6~ 
#if 1
#define LOGO_BLOCK
(13) //logo存储的起始位置
#define LOGO_BLOCK_SIZE
(4) //图片预留多大空间 4*4k*128 = 2M
#define LOGO_BLOCK_RESERVED
(2) //预留坏块
#define LOGO_SECTOR
BLOCK_TO_SECTOR(LOGO_BLOCK) 
//----------------------------- end --------------------------------------- 


//-----------------------modify by grubly 2011.09.04----------------------- 
//-----------------------------start--------------------------------------- 
#define RESERVED_BOOT_BLOCKS
(NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE +TOC_BLOCK_RESERVED + EBOOT_BLOCK_SIZE + EBOOT_BLOCK_RESERVED+ LOGO_BLOCK_SIZE+LOGO_BLOCK_RESERVED)
#endif

#if 0
#define RESERVED_BOOT_BLOCKS(NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE +TOC_BLOCK_RESERVED + EBOOT_BLOCK_SIZE + EBOOT_BLOCK_RESERVED)
#endif
从上面可以看出从Block13开始,为Logo分配了4BlockFlash空间,这样可以存放4*4k*128 = 2M大小的Logo数据,即2M以内的图片数据。由于Logo占用了一定的Block空间,所以后面Nk的起始位置RESERVED_BOOT_BLOCKS需要向后移动。
   2、在Eboot启动主菜单中增加下载Logo数据的相应的选项。修改的代码如下:
  EdbgOutputDebugString ( "D) Download image now\r\n");
EdbgOutputDebugString ( "G) Download Logo now\r\n");
        EdbgOutputDebugString ( "L) LAUNCH existing Boot Media image\r\n");
        EdbgOutputDebugString ( "R) Read Configuration \r\n");
        EdbgOutputDebugString ( "U) DOWNLOAD image now(USB)\r\n");
        EdbgOutputDebugString ( "W) Write Configuration Right Now\r\n");
        EdbgOutputDebugString ( "\r\nEnter your selection: ");


        while (! ( ( (KeySelect >= '0') && (KeySelect <= '9') ) ||
                   ( (KeySelect == 'A') || (KeySelect == 'a') ) ||
                   ( (KeySelect == 'B') || (KeySelect == 'b') ) ||
                   ( (KeySelect == 'C') || (KeySelect == 'c') ) ||
                   ( (KeySelect == 'D') || (KeySelect == 'd') ) ||
                   ( (KeySelect == 'E') || (KeySelect == 'e') ) ||
                   ( (KeySelect == 'F') || (KeySelect == 'f') ) ||
   
( (KeySelect == 'G') || (KeySelect == 'g') ) ||                 //add by grubly 2011.10.09
                   ( (KeySelect == 'T') || (KeySelect == 't') ) ||
                   ( (KeySelect == 'L') || (KeySelect == 'l') ) ||
                   ( (KeySelect == 'R') || (KeySelect == 'r') ) ||
                   ( (KeySelect == 'U') || (KeySelect == 'u') ) ||
                   ( (KeySelect == 'W') || (KeySelect == 'w') ) ||
                   ( (KeySelect == 'X') || (KeySelect == 'x') ) ))
        {
            KeySelect = OEMReadDebugByte();
        }

        switch(KeySelect)
        {
#if 1
//add by jazka 2011.09.05 
//--------------------------start----------------------------- 
case 'G': 
case 'g': 

OALMSG(TRUE, (TEXT("Please send the Logo through USB.\r\n"))); 
g_bUSBDownload = TRUE; 

DWORD dwStartAddr = 0; 
LPBYTE lpDes = NULL;         
lpDes = (LPBYTE)(FILE_CACHE_START); 


if (!OEMReadData(LCD_WIDTH*LCD_HEIGHT*2, lpDes)) 

OALMSG(TRUE, (TEXT("Error when sending the Logo through USB.\r\n"))); 
SpinForever(); 



dwStartAddr = (DWORD)lpDes; 


if (!WriteLogoToBootMedia(dwStartAddr, (DWORD)(LCD_WIDTH*LCD_HEIGHT*2), dwStartAddr)) 

OALMSG(TRUE, (TEXT("Error when WriteLogoToBootMedia.\r\n"))); 
SpinForever(); 


 } 
 break; 
//-------------------------- end -----------------------------
#endif

这里把g_bUSBDownload设置为TRUE,以便后面选择USB进行下载。由于USB下载的速度和写Flash速度不匹配,所以先下载到内存中,然后在一下子写入Flash中(这部分详解见博客http://jazka.blog.51cto.com/809003/605776)。WriteLogoToBootMedia便是Flash的写函数,后面给出实现。
3、修改LCD初始化函数InitializeDisplay,修改代码如下:
if(  LCD_MODULE_TYPE ==       LCD_MODULE_UT35A){
         memcpy((void *)IMAGE_FRAMEBUFFER_UA_BASE, prayer16bpp, LCD_ARRAY_SIZE_TFT_16BIT);
        }
    else //if(LCD_MODULE_TYPE == LCD_MODULE_UT43A)
{
//pWORD = (unsigned short *)prayer16bpp;
        //pFB = (unsigned short *)IMAGE_FRAMEBUFFER_UA_BASE;
  //add by grubly 2011.10.09 图片下载到放到中.c的数组编译进eboot中
    //--------------------------start-----------------------------
#if 0

PWORD pWord = (PWORD)prayer16bpp;
PWORD pFB = (PWORD)IMAGE_FRAMEBUFFER_UA_BASE;
for (i=0; i<400*240; i++)
{
pFB[4*i - 2 * (i % 400)]= pWord[i];
pFB[4*i - 2 * (i % 400)+1] = pWord[i];
pFB[4*i - 2 * (i % 400)+400*2] = pWord[i];
pFB[4*i - 2 * (i % 400)+1+400*2] = pWord[i];
}
#endif
//-------------------------- end -----------------------------
   //add by grubly 2011.10.09 图片下载到nand flash中
    //--------------------------start-----------------------------
#if 1
DWORD dwReadAddr = (DWORD)IMAGE_FRAMEBUFFER_UA_BASE; 
    if (!DisplayLogoFromBootMedia(dwReadAddr, (DWORD)LCD_WIDTH*LCD_HEIGHT*2, dwReadAddr)) 
    { 
      int i; 
      unsigned short *pFB; 
      pFB = (unsigned short *)IMAGE_FRAMEBUFFER_UA_BASE; 
      for (i=0; i<LCD_WIDTH*LCD_HEIGHT; i++) 
        *pFB++ = 0x0000;//0x001F;                // Blue 
    }
#endif

DisplayLogoFromBootMedia函数便是Flash的度函数,这里将读出的数据写入到显示缓存 IMAGE_FRAMEBUFFER_UA_BASE 中,该函数的实现后面给出。
4、修改nand.cpp文件,添加WriteLogoToBootMediaDisplayLogoFromBootMedia两个函数的实现。
/* 
  Write the Logo data to Nand Flash 
  add by grubly 2011.09.05 
*/ 
#if 1
BOOL WriteLogoToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr) 

  DWORD dwBlock,dwNumBlocks; 
  LPBYTE pbBuffer; 
  LPBYTE g_pbLogeBlock;
  SectorInfo si; 


  OALMSG(TRUE, (TEXT("+WriteLogoToBootMedia\r\n"))); 


  dwBlock = LOGO_BLOCK; 
  pbBuffer = (LPBYTE)dwImageStart; 


  OALMSG(TRUE, (TEXT("^^^^^^^^ 0x%x ^^^^^^^^\r\n"), (unsigned short *)pbBuffer)); 


  dwNumBlocks = (dwImageLength/(g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock)) +    
                                                 (dwImageLength%(g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock) ? 1: 0); 


  OALMSG(TRUE, (TEXT("dwImageLength = 0x%x \r\n"), dwImageLength)); 
  OALMSG(TRUE, (TEXT("dwNumBlocks = 0x%x \r\n"), dwNumBlocks)); 
  memset (g_pbLogeBlock, 0xff, g_FlashInfo.wSectorsPerBlock);
  while (dwNumBlocks--) 
  { 
    OALMSG(TRUE, (TEXT("dwBlock(0x%x) X "), dwBlock)); 
    OALMSG(TRUE, (TEXT("g_FlashInfo.wSectorsPerBlock(0x%x)"), g_FlashInfo.wSectorsPerBlock)); 
    OALMSG(TRUE, (TEXT(" = 0x%x \r\n"), dwBlock*g_FlashInfo.wSectorsPerBlock)); 




   /* FMD_ReadSector(dwBlock*g_FlashInfo.wSectorsPerBlock, g_pbLogeBlock, &si, 1); 
//ReadBlock (dwBlockNum, g_pbBlock, NULL);
    // Stepldr & Eboot image in nand flash 
    // block mark as BLOCK_STATUS_RESERVED & BLOCK_STATUS_READONLY & BLOCK_STATUS_BAD 
    if ((si.bBadBlock == 0x0) && (si.bOEMReserved !=3 )) 
    { 
 OALMSG(TRUE, (TEXT("si.bBadBlock \r\n)"))); 
      ++dwBlock; 
      ++dwNumBlocks;                // Compensate for fact that we didn't write any blocks. 
      continue; 
    } 


OALMSG(TRUE, (TEXT("dwBlock(0x%x) X "), dwBlock)); 


    if (!ReadBlock(dwBlock, NULL, g_pSectorInfoBuf)) 
    { 
      OALMSG(OAL_ERROR, (TEXT("WriteData: failed to read block (0x%x).\r\n"), dwBlock)); 
      return(FALSE); 
    } */



    if (!FMD_EraseBlock(dwBlock)) 
    { 
      OALMSG(OAL_ERROR, (TEXT("WriteData: failed to erase block (0x%x).\r\n"), dwBlock)); 
      return FALSE; 
    } 


    if (!WriteBlock(dwBlock, pbBuffer, g_pSectorInfoBuf)) 
    { 
      OALMSG(OAL_ERROR, (TEXT("WriteData: failed to write block (0x%x).\r\n"), dwBlock)); 
      return(FALSE); 
    } 


    ++dwBlock; 
    pbBuffer += g_FlashInfo.dwBytesPerBlock; 
    OALMSG(TRUE, (TEXT("dwBytesPerBlock : %d\r\n"), g_FlashInfo.dwBytesPerBlock)); 
  } 


  OALMSG(TRUE, (TEXT("_WriteLogoToBootMedia\r\n"))); 


  return TRUE; 
}
/* 
  Read the Logo data from Nand Flash 
  add by jazka 2011.09.05 
*/ 
BOOL DisplayLogoFromBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr) 

unsigned int * pFB32 = (unsigned int *)IMAGE_FRAMEBUFFER_UA_BASE; 
unsigned int * dst = pFB32;        
  //unsigned int * p = NULL; 
SectorInfo si; 


DWORD dwBlock,dwNumBlocks; 


OALMSG(TRUE, (TEXT("+ReadLogoFromBootMedia\r\n"))); 


dwBlock = LOGO_BLOCK; 


OALMSG(TRUE, (TEXT("dwImageLength = 0x%x \r\n"), dwImageLength)); 
OALMSG(TRUE, (TEXT("dwImageLength = 0x%x \r\n"), g_FlashInfo.wDataBytesPerSector)); 
OALMSG(TRUE, (TEXT("dwImageLength = 0x%x \r\n"), g_FlashInfo.wSectorsPerBlock)); 


if (0 == g_FlashInfo.wDataBytesPerSector || 0 == g_FlashInfo.wSectorsPerBlock) 

return FALSE; 



dwNumBlocks = (dwImageLength / (g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock)) + 
                (dwImageLength%(g_FlashInfo.wDataBytesPerSector*g_FlashInfo.wSectorsPerBlock) ? 1: 0); 
OALMSG(TRUE, (TEXT("dwNumBlocks = 0x%x \r\n"), dwNumBlocks)); 


while (dwNumBlocks--) 
{    
OALMSG(TRUE, (TEXT("dwBlock(0x%x) X "), dwBlock)); 
OALMSG(TRUE, (TEXT("g_FlashInfo.wSectorsPerBlock(0x%x)"), g_FlashInfo.wSectorsPerBlock)); 
OALMSG(TRUE, (TEXT(" = 0x%x \r\n"), dwBlock*g_FlashInfo.wSectorsPerBlock)); 


    //BOOL ReadBlock(DWORD dwBlock, LPBYTE pbBlock, PSectorInfo pSectorInfoTable) 
if (!ReadBlock(dwBlock, (LPBYTE)dst, g_pSectorInfoBuf)) 

OALMSG(OAL_ERROR, (TEXT("WriteData: failed to read block (0x%x).\r\n"), dwBlock)); 
return(FALSE);    

dst += g_FlashInfo.dwBytesPerBlock/4; 
++dwBlock; 

OALMSG(TRUE, (TEXT("_ReadLogoFromBootMedia\r\n"))); 


return TRUE; 
}
#endif
    上面红色部分是原创作者加的,在UT-S3C2416的开发板上,如果加上红色部分代码,会出现在调用ReadBlock时返回错误,直接跳出写函数,进过测试,屏蔽掉那部分代码也可以实现将图片写进nand flash中,如果有坏块,可能导致不能写入flash中,需要添加坏块检测函数。
5、这个是针对UT-S3C2416开发板,需要在BOOL OEMPlatformInit(void) 函数中,将初始化LCD的函数InitDisplay()放到nand flash初始化之后,不然在读取logo的内容时,会出现g_FlashInfo.wSectorsPerBlock=0的现象,不能读取数据。直接把InitDisplay()放到函数的末尾即可;
7、最后在 loader.h中添加 上述两个函数的声明:
#if 1 
BOOL WriteLogoToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr) ;
BOOL DisplayLogoFromBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr) ;
#endif
6 、关于Logo数据的文件bin的生成,网上有很多工具可以实现,我在网上找了一个挺好用的,推荐给大家http://download.csdn.net/detail/anthone_ligang/3705198






  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值