在EBOOT中提供了操作Flash的功能,可以将下载的WinCE image烧到Flash当中,这需要实现一些Flash相关的OEM函数,
WinCE Eboot中的OEM Flash函数
。这些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,给个微软的例子:
1.#define FLASH_START 0
2.#define FLASH_LENGTH 0x02000000
3.BOOL OEMIsFlashAddr(DWORD dwAddr)
4.{
5. //根据Flash的起始地址和长度判断该地址是否在Flash区域内
6. if ((dwAddr >= FLASH_START) && (dwAddr < (FLASH_START + FLASH_LENGTH)))
7. {
8. return(TRUE);
9. }
10.
11. return(FALSE);
12.}
13.
2.BOOL OEMStartEraseFlash(DWORD dwStartAddr, DWORD dwLength)
该函数用于初始化Flash的擦除,dwStartAddr表示要擦除的起始地址,dwLength为长度。通过这两个参数计算Flash中要被擦除的起始block和最后一个block,以及要擦除多少个block,给个微软的例子:
1.BOOL OEMStartEraseFlash (DWORD dwStartAddr, DWORD dwLength)
2.{
3. ULONG i = 0;
4. ULONG nNumBlocks = 0;
5.
6. //判断起始地址和终止地址是否都在Flash区域内
7. if (!OEMIsFlashAddr(dwStartAddr) || !OEMIsFlashAddr(dwStartAddr + dwLength - 1))
8. {
9. return(FALSE);
10. }
11.
12. //确认该起始地址是Block对齐的
13. if (dwStartAddr % FLASH_BLOCK_SIZE)
14. {
15. return(FALSE);
16. }
17. //确认长度是4字节对齐
18. if (dwLength & 0x03)
19. {
20. return(FALSE);
21. }
22.
23. //根据Flash的基地址和Flash的Block大小计算要擦除的起始block和最后一个
24. //block以及多少个Block
25. gnStartBlock = (dwStartAddr - FLASH_BASE) / FLASH_BLOCK_SIZE;
26. gnEndBlock = ((dwStartAddr + dwLength + (FLASH_BLOCK_SIZE - 1) - FLASH_BASE) / FLASH_BLOCK_SIZE);
27. gnBlocks = (int)(gnEndBlock - gnStartBlock);
28. gnBlockCount = gnStartBlock;
29.
30. EdbgOutputDebugString("Erasing flash blocks: start block = %d end block = %d\r\n", gnStartBlock, gnEndBlock);
31.
32.
33. return(TRUE);
34.}
3.void OEMContinueEraseFlash (void)
该函数用于擦除Flash区域,它会在image下载后被调用来擦除Flash中的block,给个微软的例子:
1.void OEMContinueEraseFlash(void)
2.{
3. UCHAR nEraseCount = BLOCK_ERASE_STEP; //要擦除的块
4.
5.
6. //确认所有需要擦除的block都被擦除了
7. if (!gnBlocks || (gnBlockCount == gnEndBlock))
8. return;
9.
10. //擦除block
11. while ((gnBlockCount < gnEndBlock) && nEraseCount)
12. {
13. if (CFI_Erase_Block((unsigned32*)BLOCK_ADDR(gnBlockCount), 0, NULL) != PASS)
14. {
15. EdbgOutputDebugString("ERROR: OEMContinueEraseFlash - flash erase error (block number %d).\r\n", gnBlockCount);
16. return;
17. }
18.
19. ++gnBlockCount;
20. --nEraseCount;
21. }
22.
23.
24. return;
25.}
26.
27.
4.BOOL OEMFinishEraseFlash (void)
该函数用于确认Flash中所有的block都被擦除完成,给个微软的例子:
1.BOOL OEMFinishEraseFlash(void)
2.{
3. EdbgOutputDebugString("INFO: Finishing flash erase...\r\n");
4.
5. while(gnBlocks && (gnBlockCount != gnEndBlock))
6. {
7. OEMContinueEraseFlash();
8. }
9.
10. return(TRUE);
11.}
12.
5.BOOL OEMWriteFlash(DWORD dwImageStart, DWORD dwImageLength)
该函数用于将下载的image写入到Flash当中,dwImageStart为被写入image在Flash中的起始地址,dwImageLength为image的大小,给个微软的例子:
1.BOOL OEMWriteFlash(DWORD dwImageStart, DWORD dwImageLength)
2.{
3. DWORD dwFlashAddr, dwExtraBytes = 0;
4. LPBYTE pbCache = NULL;
5. UCHAR nNumBlocks = 0;
6.
7.
8. //确认起始地址和长度都在Flash区域内
9. if (!OEMIsFlashAddr(dwImageStart) || !OEMIsFlashAddr(dwImageStart + dwImageLength - 1))
10. {
11. return(FALSE);
12. }
13.
14. //确认起始地址是Block字节对齐的
15. if (dwImageStart % FLASH_BLOCK_SIZE)
16. {
17. return(FALSE);
18. }
19.
20. //计算要写入的block数量
21. nNumBlocks = (UCHAR)(dwImageLength / FLASH_BLOCK_SIZE);
22. dwExtraBytes = (dwImageLength % FLASH_BLOCK_SIZE);
23. dwFlashAddr = dwImageStart;
24. pbCache = OEMMapMemAddr (dwImageStart, dwFlashAddr);
25.
26.
27. //写Flash
28. while(nNumBlocks)
29. {
30. if (CFI_Write_Block((unsigned32*)dwFlashAddr, (unsigned32*)pbCache, FLASH_BLOCK_SIZE, NULL) != PASS)
31. {
32. EdbgOutputDebugString("ERROR: OEMWriteFlash - unable to write to block (block address=0x%x).\r\n", dwFlashAddr);
33. return(FALSE);
34. }
35.
36. dwFlashAddr += FLASH_BLOCK_SIZE;
37. pbCache = OEMMapMemAddr (dwImageStart, dwFlashAddr);
38. --nNumBlocks;
39. }
40.
41. //将额外的数据写入Flash中
42. if (dwExtraBytes)
43. {
44. if (CFI_Write_Block((unsigned32*)dwFlashAddr, (unsigned32*)pbCache, dwExtraBytes, NULL) != PASS)
45. {
46. EdbgOutputDebugString("ERROR: OEMWriteFlash - unable to write to block (block address=0x%x).\r\n", dwFlashAddr);
47. return(FALSE);
48. }
49. }
50.
51. return(TRUE);
52.}
53.
54.
上面的5个函数用于在eboot中支持Flash操作功能,