WinCE6.0 修改开机Logo方法集锦(二)

简介:
今天讲解第二种方法,将Logo图片的数据写入到Nand Flash中,在启动初始化LCD的时候,从固定的地址将数据读出并填充到显示缓存中。
       实验平台:WinCE6.0+Android6410 +4.3CLD
       以下内容参考自CSDN论坛的一个帖子,不过里面的描述不是特别清楚,该主题博文进行了整理。为尊重原创,给出链接http://topic.csdn.net/u/20100126/14/ef1fc7c4-d8db-426b-b6bf-b74d74cdd05a.html
      
       Logo图片写Flash的思路继续细分,又可以分为几种不同的实现方法,今天先描述实现方法一,这是其中比较简单的一种方法,不需要修改bib文件等配置性文件,只需要修改代码即可。
       首先提几个问题:
       1、在什么时候将Logo数据写入Nand Flash
       2、在什么时候读Nand Flash数据到显示缓存?
       3、要写的Logo的数据是什么?
       4、写入Flash的什么位置,又从什么位置读数据?
       5、写Flash的函数和读Flash的函数如何实现?
       上面几个问题弄清楚了,方法一基本就出来了。给出上面几个问题的解决方法:
       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
// NAND Boot (loads into SteppingStone) @ Block 0 
#define NBOOT_BLOCK                                 0 
#define NBOOT_BLOCK_SIZE                        1 
#define NBOOT_SECTOR                                BLOCK_TO_SECTOR(NBOOT_BLOCK) 

// TOC @ Block 1 
#define TOC_BLOCK                                     1 
#define TOC_BLOCK_SIZE                            1 
#define TOC_SECTOR                                    BLOCK_TO_SECTOR(TOC_BLOCK) 

// Eboot @ Block 2 
#define EBOOT_BLOCK                                 2 
#define EBOOT_SECTOR_SIZE                     FILE_TO_SECTOR_SIZE(EBOOT_RAM_IMAGE_SIZE) 
#define EBOOT_BLOCK_SIZE                        SECTOR_TO_BLOCK(EBOOT_SECTOR_SIZE) 
#define EBOOT_SECTOR                                BLOCK_TO_SECTOR(EBOOT_BLOCK)
       5 、答: Flash 的读写操作函数实现主要在 nand.cpp 文件中,具体实现可以参考函数 ReadOSImageFromBootMedia WriteOSImageToBootMedia
 
       下面给出详细的修改步骤:
      1 、首先修改 loader.h 文件,为 Logo 数据分配一定的 Block 空间。添加如下代码:
// Eboot @ Block 2 
#define EBOOT_BLOCK                                 2 
#define EBOOT_SECTOR_SIZE                     FILE_TO_SECTOR_SIZE(EBOOT_RAM_IMAGE_SIZE) 
#define EBOOT_BLOCK_SIZE                        SECTOR_TO_BLOCK(EBOOT_SECTOR_SIZE) 
#define EBOOT_SECTOR                                BLOCK_TO_SECTOR(EBOOT_BLOCK) 

//-----------------------add by jazka 2011.09.04------------------------- 
//-----------------------------start-------------------------------------- 
// Logo @ Block 6~ 
#define LOGO_BLOCK                    6 
#define LOGO_BLOCK_SIZE                20 
#define LOGO_SECTOR                            BLOCK_TO_SECTOR(LOGO_BLOCK) 
//----------------------------- end --------------------------------------- 

//-----------------------modify by jazka 2011.09.04----------------------- 
//-----------------------------start--------------------------------------- 
//#define RESERVED_BOOT_BLOCKS                (NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE) 
#define RESERVED_BOOT_BLOCKS                (NBOOT_BLOCK_SIZE + TOC_BLOCK_SIZE + EBOOT_BLOCK_SIZE + LOGO_BLOCK_SIZE)
从上面可以看出从 Block6 开始,为 Logo 分配了 20 Block Flash 空间,这样可以存放 64KB*20=1280KB 大小的 Logo 数据,即 1M 以内的图片数据。由于 Logo 占用了一定的 Block 空间,所以后面 Nk 的起始位置 RESERVED_BOOT_BLOCKS 需要向后移动。
       2 、在 Eboot 启动主菜单中增加下载 Logo 数据的相应的选项。修改的代码如下:
                EdbgOutputDebugString ( "F) Low-level format the Smart Media card\r\n"); 
    //add by jazka 2011.09.05 
    //-----------------------------start--------------------------------- 
    EdbgOutputDebugString ( "G) DOWNLOAD Logo now(USB)\r\n"); 
    //----------------------------- end --------------------------------- 
                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 jazak 2011.09.05 
                                     ( (KeySelect == 'L') || (KeySelect == 'l') ) || 
                                     ( (KeySelect == 'R') || (KeySelect == 'r') ) || 
                                     ( (KeySelect == 'U') || (KeySelect == 'u') ) || 
                                     ( (KeySelect == 'W') || (KeySelect == 'w') ) )) 
                { 
                        KeySelect = OEMReadDebugByte(); 
                }
    //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 -----------------------------
这里把 g_bUSBDownload 设置为 TRUE ,以便后面选择 USB 进行下载。由于 USB 下载的速度和写 Flash 速度不匹配,所以先下载到内存中,然后在一下子写入 Flash 中(这部分详解见博客 http://jazka.blog.51cto.com/809003/605776 )。 WriteLogoToBootMedia 便是 Flash 的写函数,后面给出实现。
       3 、修改 LCD 初始化函数 InitializeDisplay ,修改代码如下:
        // Fill Framebuffer 
#if(SMDK6410_LCD_MODULE == LCD_MODULE_UT_LCD35A) 
        memcpy((void *)EBOOT_FRAMEBUFFER_UA_START, (void *)InitialImage_rgb16_320x240, 320*240*2); 
#elif        (LCD_BPP == 16) 
        { 
    //delete by jazka 2011.08.31    修改开机启动界面 
             /* int i; 
                unsigned short *pFB; 
                pFB = (unsigned short *)EBOOT_FRAMEBUFFER_UA_START; 

                for (i=0; i<LCD_WIDTH*LCD_HEIGHT; i++) 
    { 
                        //*pFB++ = 0x0000;//0x001F;                // Blue 
      //*pFB++ = 0x001F;                                             //modify by jazka 2011.07.22 
      *pFB++ = InitialImage_rgb16_480x272[i]; 
    } 
    */ 

    //add by jazka 2011.08.31 
    //memcpy((void *)EBOOT_FRAMEBUFFER_UA_START, (void *)InitialImage_rgb16_480x272, 480*272*2); 

    //modify by jazka 2011.09.07 
    DWORD dwReadAddr = (DWORD)EBOOT_FRAMEBUFFER_UA_START; 
    if (!DisplayLogoFromBootMedia(dwReadAddr, (DWORD)LCD_WIDTH*LCD_HEIGHT*2, dwReadAddr)) 
    { 
      int i; 
      unsigned short *pFB; 
      pFB = (unsigned short *)EBOOT_FRAMEBUFFER_UA_START; 

      for (i=0; i<LCD_WIDTH*LCD_HEIGHT; i++) 
        *pFB++ = 0x0000;//0x001F;                // Blue 
    }
DisplayLogoFromBootMedia 函数便是 Flash 的度函数,这里将读出的数据写入到显示缓存 EBOOT_FRAMEBUFFER_US_START 中,该函数的实现后面给出。
      4 、修改 nand.cpp 文件,添加 WriteLogoToBootMedia DisplayLogoFromBootMedia 两个函数的实现。
/* 
  Write the Logo data to Nand Flash 
  add by jazka 2011.09.05 
*/ 
BOOL WriteLogoToBootMedia(DWORD dwImageStart, DWORD dwImageLength, DWORD dwLaunchAddr) 

  DWORD dwBlock,dwNumBlocks; 
  LPBYTE pbBuffer; 
  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)); 

  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, NULL, &si, 1); 

    // 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 )) 
    { 
      ++dwBlock; 
      ++dwNumBlocks;                // Compensate for fact that we didn't write any blocks. 
      continue; 
    } 

    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 *)EBOOT_FRAMEBUFFER_UA_START; 
  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; 
}
       5、关于Logo数据的文件bin的生成,网上有很多工具可以实现,其实可以自己写一个应用程序完成该功能。本人编写了24Bmp文件生成RGB565格式的bin文件的程序,这部分代码也可以在nand.app中写成一个函数,在写入Flash时调用转换为相应的RGB565数据即可,这样更新Logo时可以更直接。注意下载时的数据量是现在的3倍。
       这里就不给出源代码了,如果需要,请留言。
 

       今天就到这里,改天上实现方法二:将Logo.bin做成和Eboot.bin一样的格式,这样下载Eboot.bin的很多代码就可以直接使用。



本文转自jazka 51CTO博客,原文链接:http://blog.51cto.com/jazka/664131,如需转载请自行联系原作者

相关文章
|
13天前
|
存储 JSON API
TOON:专为 LLM 设计的轻量级数据格式
TOON(Token-Oriented Object Notation)是一种专为降低LLM输入token消耗设计的数据格式。它通过省略JSON中冗余的括号、引号和重复键名,用类似CSV与YAML结合的方式表达结构化数据,显著减少token数量,适合向模型高效传参,但不替代JSON用于存储或复杂嵌套场景。
301 2
TOON:专为 LLM 设计的轻量级数据格式
|
9月前
|
运维 安全 数据挖掘
趋势还是噪声?ADF与KPSS检验结果矛盾时的高级时间序列处理方法
在时间序列分析中,ADF(增广迪基-富勒)和KPSS检验用于评估数据的平稳性。当ADF检验失败而KPSS检验通过时,表明序列具有确定性趋势但整体平稳。
249 25
趋势还是噪声?ADF与KPSS检验结果矛盾时的高级时间序列处理方法
|
SQL DataWorks 监控
DataWorks产品使用合集之怎么针对表中已经存在的数据进行更新
DataWorks作为一站式的数据开发与治理平台,提供了从数据采集、清洗、开发、调度、服务化、质量监控到安全管理的全套解决方案,帮助企业构建高效、规范、安全的大数据处理体系。以下是对DataWorks产品使用合集的概述,涵盖数据处理的各个环节。
DataWorks产品使用合集之怎么针对表中已经存在的数据进行更新
|
存储 运维 安全
云计算:优势与挑战
在数字化浪潮的推动下,云计算已经成为企业信息化建设的重要组成部分。本文将针对云计算的优势和劣势进行深入分析,旨在为读者提供全面的了解和参考。
1712 5
|
存储 Java 程序员
Java 中的堆栈和堆有什么区别?
【8月更文挑战第22天】
685 0
|
存储
算数移位,逻辑移位以及循环移位
算数移位,逻辑移位以及循环移位
542 0
|
机器学习/深度学习 人工智能 自然语言处理
从人工智能到大模型的演变
本文概述了人工智能从早期的规则基础系统到现代大模型的演变过程,涵盖了符号主义、专家系统、统计学习、深度学习、自然语言处理以及大模型的出现与应用,分析了各阶段的关键技术和面临的挑战,展望了未来的发展方向。
594 3
|
存储 运维 数据可视化
【技术分析】低代码平台的专有存储技术
低代码是一个新兴的技术,有着非常明确而鲜明的技术特点,比如:拖拽组件、可视化编程、零代码编程等等。但传统软件企业在进行技术融合时却往往是困难重重,旧有的技术积累很难能继承应用过来。本文作为一组技术分析,来逐一分解低代码背后的支撑技术。今天我们给大家带来的一个专题分析是,低代码平台的专有存储技术。
|
安全 Windows
Windows 无法连接打印机,请检查打印机名并重试。如果这是网络打印机,请确保打印机已打开,并且打印机地址正确。报错代码:0x00000709
Windows 无法连接打印机,请检查打印机名并重试。如果这是网络打印机,请确保打印机已打开,并且打印机地址正确。报错代码:0x00000709
Windows 无法连接打印机,请检查打印机名并重试。如果这是网络打印机,请确保打印机已打开,并且打印机地址正确。报错代码:0x00000709
|
存储 数据采集 运维
日志服务(SLS)测评
在本次测评中,我将对日志服务SLS产品进行全面评估,主要从以下四个方面展开。首先,我将进行功能测试,基于之前参加的两次训练实验,对其功能进行评估。其次,我将与其他数据分析&可观测性产品进行比较,以了解SLS的优势和差异。然后,我将进行成本与收益分析,探讨SLS作为一站式的可观测数据存储分析平台所带来的成本节约和收益提升。最后,我将对SLS进行简要总结,并提出一些期待,希望能够为用户提供有用的参考信息。
986 58