在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,给个微软的例子:
- #define?FLASH_START??????0
- #define?FLASH_LENGTH?????0x02000000
- BOOL?OEMIsFlashAddr(DWORD?dwAddr)
- {
- ????????//根据Flash的起始地址和长度判断该地址是否在Flash区域内
- ????????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,给个微软的例子:
- BOOL?OEMStartEraseFlash?(DWORD?dwStartAddr,?DWORD?dwLength)
- {
- ????ULONG?i?=?0;
- ????ULONG?nNumBlocks?=?0;
- ????//判断起始地址和终止地址是否都在Flash区域内
- ????if?(!OEMIsFlashAddr(dwStartAddr)?||?!OEMIsFlashAddr(dwStartAddr?+?dwLength?-?1))
- ????{
- ????????return(FALSE);
- ????}
- ????//确认该起始地址是Block对齐的
- ????if?(dwStartAddr?%?FLASH_BLOCK_SIZE)
- ????{
- ????????return(FALSE);
- ????}
- ????//确认长度是4字节对齐
- ????if?(dwLength?&?0x03)
- ????{
- ????????return(FALSE);
- ????}
- ????//根据Flash的基地址和Flash的Block大小计算要擦除的起始block和最后一个
- ????//block以及多少个Block
- ????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("Erasing?flash?blocks:?start?block?=?%d??end?block?=?%d/r/n",?gnStartBlock,?gnEndBlock);
- ????return(TRUE);
- }
?
3. void OEMContinueEraseFlash (void)
该函数用于擦除Flash区域,它会在image下载后被调用来擦除Flash中的block,给个微软的例子:
- void?OEMContinueEraseFlash(void)
- {
- ????UCHAR?nEraseCount?=?BLOCK_ERASE_STEP;???//要擦除的块
- ????//确认所有需要擦除的block都被擦除了
- ????if?(!gnBlocks?||?(gnBlockCount?==?gnEndBlock))
- ????????return;
- ????//擦除block
- ????while?((gnBlockCount?<?gnEndBlock)?&&?nEraseCount)
- ????{
- ????????if?(CFI_Erase_Block((unsigned32*)BLOCK_ADDR(gnBlockCount),?0,?NULL)?!=?PASS)
- ????????{
- ????????????EdbgOutputDebugString("ERROR:?OEMContinueEraseFlash?-?flash?erase?error?(block?number?%d)./r/n",?gnBlockCount);
- ????????????return;
- ????????}
- ????????++gnBlockCount;
- ????????--nEraseCount;
- ????}
- ????return;
- }
?
4. BOOL OEMFinishEraseFlash (void)
该函数用于确认Flash中所有的block都被擦除完成,给个微软的例子:
- BOOL?OEMFinishEraseFlash(void)
- {
- ????EdbgOutputDebugString("INFO:?Finishing?flash?erase.../r/n");
- ????while(gnBlocks?&&?(gnBlockCount?!=?gnEndBlock))
- ????{
- ????????OEMContinueEraseFlash();
- ????}
- ????return(TRUE);
- }
?
5. BOOL OEMWriteFlash(DWORD dwImageStart,DWORD dwImageLength)
该函数用于将下载的image写入到Flash当中,dwImageStart为被写入image在Flash中的起始地址,dwImageLength为image的大小,给个微软的例子:
- BOOL?OEMWriteFlash(DWORD?dwImageStart,?DWORD?dwImageLength)
- {
- ????DWORD?dwFlashAddr,?dwExtraBytes?=?0;
- ????LPBYTE?pbCache?=?NULL;
- ????UCHAR?nNumBlocks?=?0;
- ????//确认起始地址和长度都在Flash区域内
- ????if?(!OEMIsFlashAddr(dwImageStart)?||?!OEMIsFlashAddr(dwImageStart?+?dwImageLength?-?1))
- ????{
- ????????return(FALSE);
- ????}
- ????//确认起始地址是Block字节对齐的
- ????if?(dwImageStart?%?FLASH_BLOCK_SIZE)
- ????{
- ????????return(FALSE);
- ????}
- ????//计算要写入的block数量
- ????nNumBlocks???=?(UCHAR)(dwImageLength?/?FLASH_BLOCK_SIZE);
- ????dwExtraBytes?=?(dwImageLength?%?FLASH_BLOCK_SIZE);
- ????dwFlashAddr??=?dwImageStart;
- ????pbCache??????=?OEMMapMemAddr?(dwImageStart,?dwFlashAddr);
- ????//写Flash?
- ????while(nNumBlocks)
- ????{?
- ????????if?(CFI_Write_Block((unsigned32*)dwFlashAddr,?(unsigned32*)pbCache,?FLASH_BLOCK_SIZE,?NULL)?!=?PASS)
- ????????{
- ????????????EdbgOutputDebugString("ERROR:?OEMWriteFlash?-?unable?to?write?to?block?(block?address=0x%x)./r/n",?dwFlashAddr);
- ????????????return(FALSE);
- ????????}
- ????????dwFlashAddr?+=?FLASH_BLOCK_SIZE;
- ????????pbCache?=?OEMMapMemAddr?(dwImageStart,?dwFlashAddr);
- ????????--nNumBlocks;
- ????}
- ????//将额外的数据写入Flash中
- ????if?(dwExtraBytes)
- ????{
- ????????if?(CFI_Write_Block((unsigned32*)dwFlashAddr,?dwExtraBytes,?dwFlashAddr);
- ????????????return(FALSE);
- ????????}
- ????}
- ????return(TRUE);
- }
- ?
?
上面的5个函数用于在eboot中支持Flash操作功能。一般在开发BSP的时候,如果需要在EBOOT中实现Flash的功能,会在EBOOT中创建一个Flash.c文件,在该文件中实现上述这些函数。建议看看blcommon.c中的DownloadImage函数,可以帮助理解。