作者:ARM-WinCE
在EBOOT中提供了操作Flash的功能,可以将下载的WinCE image烧到Flash当中,这需要实现一些Flash相关的OEM函数。
这些OEM函数会在BLCOMMON模块中被调用,也就是在blcommon.c文件的DownloadImage函数中被调用。在DownloadImage函数中,一般image文件的header会被先下载并进行解析。然后调用OEMIsFlashAddr判断image所在的区域,如果是在Flash的地址空间内,那么接下来会下载image文件并调用Flash相关的OEM函数将Flash擦除并写入。下面简单介绍一下这些函数:
1. BOOL OEMIsFlashAddr(DWORD dwAddr)
该函数用于判断下载的WinCE image文件是在Flash区域中还是在RAM区域中,dwAddr是image文件的地址,如果在Flash区域中返回TRUE,否则返回FALSE,给个微软的例子:<?xml:namespace prefix = o ns = "urn:schemas-microsoft-com:office:office" />
- #defineFLASH_START0
- #defineFLASH_LENGTH0x02000000
- BOOLOEMIsFlashAddr(DWORDdwAddr)
- {
-
- if((dwAddr>=FLASH_START)&&(dwAddr<(FLASH_START+FLASH_LENGTH)))
- {
- return(TRUE);
- }
- return(FALSE);
- }
2. BOOL OEMStartEraseFlash(DWORD dwStartAddr, DWORD dwLength)
该函数用于初始化Flash的擦除,dwStartAddr表示要擦除的起始地址,dwLength为长度。通过这两个参数计算Flash中要被擦除的起始block和最后一个block,以及要擦除多少个block,给个微软的例子:
- BOOLOEMStartEraseFlash(DWORDdwStartAddr,DWORDdwLength)
- {
- ULONGi=0;
- ULONGnNumBlocks=0;
-
- if(!OEMIsFlashAddr(dwStartAddr)||!OEMIsFlashAddr(dwStartAddr+dwLength-1))
- {
- return(FALSE);
- }
-
- if(dwStartAddr%FLASH_BLOCK_SIZE)
- {
- return(FALSE);
- }
-
- if(dwLength&0x03)
- {
- return(FALSE);
- }
-
-
- gnStartBlock=(dwStartAddr-FLASH_BASE)/FLASH_BLOCK_SIZE;
- gnEndBlock=((dwStartAddr+dwLength+(FLASH_BLOCK_SIZE-1)-FLASH_BASE)/FLASH_BLOCK_SIZE);
- gnBlocks=(int)(gnEndBlock-gnStartBlock);
- gnBlockCount=gnStartBlock;
- EdbgOutputDebugString("Erasingflashblocks:startblock=%dendblock=%d\r\n",gnStartBlock,gnEndBlock);
- return(TRUE);
- }
3. void OEMContinueEraseFlash (void)
该函数用于擦除Flash区域,它会在image下载后被调用来擦除Flash中的block,给个微软的例子:
- voidOEMContinueEraseFlash(void)
- {
- UCHARnEraseCount=BLOCK_ERASE_STEP;
-
- if(!gnBlocks||(gnBlockCount==gnEndBlock))
- return;
-
- while((gnBlockCount<gnEndBlock)&&nEraseCount)
- {
- if(CFI_Erase_Block((unsigned32*)BLOCK_ADDR(gnBlockCount),0,NULL)!=PASS)
- {
- EdbgOutputDebugString("ERROR:OEMContinueEraseFlash-flasheraseerror(blocknumber%d).\r\n",gnBlockCount);
- return;
- }
- ++gnBlockCount;
- --nEraseCount;
- }
- return;
- }
4. BOOL OEMFinishEraseFlash (void)
该函数用于确认Flash中所有的block都被擦除完成,给个微软的例子:
- BOOLOEMFinishEraseFlash(void)
- {
- EdbgOutputDebugString("INFO:Finishingflasherase...\r\n");
- while(gnBlocks&&(gnBlockCount!=gnEndBlock))
- {
- OEMContinueEraseFlash();
- }
- return(TRUE);
- }
5. BOOL OEMWriteFlash(DWORD dwImageStart, DWORD dwImageLength)
该函数用于将下载的image写入到Flash当中,dwImageStart为被写入image在Flash中的起始地址,dwImageLength为image的大小,给个微软的例子:
- BOOLOEMWriteFlash(DWORDdwImageStart,DWORDdwImageLength)
- {
- DWORDdwFlashAddr,dwExtraBytes=0;
- LPBYTEpbCache=NULL;
- UCHARnNumBlocks=0;
-
- if(!OEMIsFlashAddr(dwImageStart)||!OEMIsFlashAddr(dwImageStart+dwImageLength-1))
- {
- return(FALSE);
- }
-
- if(dwImageStart%FLASH_BLOCK_SIZE)
- {
- return(FALSE);
- }
-
- nNumBlocks=(UCHAR)(dwImageLength/FLASH_BLOCK_SIZE);
- dwExtraBytes=(dwImageLength%FLASH_BLOCK_SIZE);
- dwFlashAddr=dwImageStart;
- pbCache=OEMMapMemAddr(dwImageStart,dwFlashAddr);
-
- while(nNumBlocks)
- {
- if(CFI_Write_Block((unsigned32*)dwFlashAddr,(unsigned32*)pbCache,FLASH_BLOCK_SIZE,NULL)!=PASS)
- {
- EdbgOutputDebugString("ERROR:OEMWriteFlash-unabletowritetoblock(blockaddress=0x%x).\r\n",dwFlashAddr);
- return(FALSE);
- }
- dwFlashAddr+=FLASH_BLOCK_SIZE;
- pbCache=OEMMapMemAddr(dwImageStart,dwFlashAddr);
- --nNumBlocks;
- }
-
- if(dwExtraBytes)
- {
- if(CFI_Write_Block((unsigned32*)dwFlashAddr,(unsigned32*)pbCache,dwExtraBytes,NULL)!=PASS)
- {
- EdbgOutputDebugString("ERROR:OEMWriteFlash-unabletowritetoblock(blockaddress=0x%x).\r\n",dwFlashAddr);
- return(FALSE);
- }
- }
- return(TRUE);
- }
-
上面的5个函数用于在eboot中支持Flash操作功能。一般在开发BSP的时候,如果需要在EBOOT中实现Flash的功能,会在EBOOT中创建一个Flash.c文件,在该文件中实现上述这些函数。建议看看blcommon.c中的DownloadImage函数,可以帮助理解。