2440 wince 5.0 BSP之flash驱动分析

作者:wogoyixikexie@gliet

这几天,使用立宇泰2440 开发板光盘的BSP放到手持机上,运行是没有问题了,但是却发现不了盘符。后来看串口打印信息,原来是页大小根本没有识别出来,本来是2048byte的,但是打印出来确实512byte。

  1. FMD::FMD_Init
  2. FMD::FMD_Init - pBSPArgs->nfsblk = 0xffffffff 
  3. FMD::FMD_Init - READ_REGISTER_BYTE(pNFSBLK) = 0x0 
  4. FMD::FMD_Init Softreset ..... 
  5. FMD::FMD_Init Done
  6. MID = 0xec, DID = 0xdc 4th Cycle : 0x10
  7. NUMBLOCKS : 4096(0x1000), SECTORSPERBLOCK = 256(0x100), BYTESPERSECTOR = 512(0x200)
  8. //每扇区字节数并不正确。是不是这个原因导致flash盘符发现不了呢?我猜我的flash驱动

 

BYTESPERSECTOR 不正确就从它入手

C:/WINCE500/PLATFORM/SMDK2440A/Src/Common/Smartmedia/fmd/fmd.cpp

  1. //  OK, instead of reading it from the chip, we use the hardcoded
  2. //  numbers here.
  3.     pFlashInfo->dwNumBlocks         = wNUM_BLOCKS;
  4.     pFlashInfo->wSectorsPerBlock    = PAGES_PER_BLOCK;
  5.     pFlashInfo->wDataBytesPerSector = SECTOR_SIZE;
  6.     pFlashInfo->dwBytesPerBlock     = (pFlashInfo->wSectorsPerBlock * pFlashInfo->wDataBytesPerSector);
  7.     RETAILMSG(1, (TEXT("NUMBLOCKS : %d(0x%x), SECTORSPERBLOCK = %d(0x%x), BYTESPERSECTOR = %d(0x%x) /r/n"), pFlashInfo->dwNumBlocks, pFlashInfo->dwNumBlocks, pFlashInfo->wSectorsPerBlock, pFlashInfo->wSectorsPerBlock, pFlashInfo->wDataBytesPerSector, pFlashInfo->wDataBytesPerSector));

很明显,SECTOR_SIZE是关键所在。看看SECTOR_SIZE调用以及定义的地方

// TODO: Make sector size generic
static BYTE g_pFLSBuffer[SECTOR_SIZE];——从这里看来,他像个宏定义,是常数。

  1. #ifndef __NAND_H__
  2. #define __NAND_H__
  3. #define LARGE_BLOCK_NAND        0
  4. #define SMALL_BLOCK_NAND        1
  5. #define USE_NFCE                0
  6. #define USE_GPIO                1
  7. #define LB_BLOCK_LOOP           1
  8. #define SB_BLOCK_LOOP           8
  9. //为什么会这么定义呢?这样怎么样识别大小页?
  10. #define SECTOR_SIZE             512
  11. #define SPARE_SIZE              16
  12. #define PAGES_PER_BLOCK         256                     // Phisical 64 * logical 4
  13. #define NAND_PAGE_CNT           PAGES_PER_BLOCK     /* Each Block has 32 Pages      */
  14. #define NAND_PAGE_SIZE          SECTOR_SIZE         /* Each Page has 512 Bytes      */
  15. #define NAND_BLOCK_SIZE         (NAND_PAGE_CNT * NAND_PAGE_SIZE)
  16. #endif    // __NAND_H_.
  17. ======================nand.h======================

我查找SECTOR_SIZE 出现的地方,全部是512的,三星介绍说已经支持大页flash,真是不太负责。

继续多看几个地方

现在我加了一些串口打印信息

  1. OEMIoControl: Unsupported Code 0x10100b4 - device 0x0101 func 45
  2. OEMIoControl: Unsupported Code 0x101008c - device 0x0101 func 35
  3. FMD::FMD_Init
  4. FMD::FMD_Init - pBSPArgs->nfsblk = 0xffffffff 
  5. FMD::FMD_Init - READ_REGISTER_BYTE(pNFSBLK) = 0x0 
  6. FMD::FMD_Init Softreset ..... 
  7. FMD::FMD_Init Done
  8. [S2440:  IN] ++_ReadXID()
  9. MID = 0xec, DID = 0xdc 4th Cycle : 0x10
  10. NUMBLOCKS : 4096(0x1000), SECTORSPERBLOCK = 64(0x40), BYTESPERSECTOR = 2048(0x800) 
  11. FMD_LB_GetBlockStatus (0x0)0x0 
  12. FMD::FMD_LB_ReadSector 0x0 
  13. FMD::NAND_LB_ReadSectorInfo 0x0 
  14. FMD::FMD_LB_ReadSector 0x0 
  15. FMD::NAND_LB_ReadSectorInfo 0x0 
  16. FMD_LB_GetBlockStatus (0x1)0x40 
  17. FMD::FMD_LB_ReadSector 0x100 
  18. FMD::NAND_LB_ReadSectorInfo 0x100 
  19. FMD::FMD_LB_ReadSector 0x40 
  20. FMD::NAND_LB_ReadSectorInfo 0x40 
  21. //------------到了4096就出现错误
  22. [ERROR:nLength>4096]
  23. [ERROR:nLength>4096]
  24. FMD::FMD_LB_ReadSector 0x2b540 
  25. FMD::NAND_LB_ReadSectorInfo 0x2b540 
  26. FMD_LB_GetBlockStatus (0xad6)0x2b580 
  27. FMD::FMD_LB_ReadSector 0xad600 
  28. FMD::NAND_LB_ReadSectorInfo 0xad600 
  29. FMD::FMD_LB_ReadSector 0x2b580 
  30. FMD::NAND_LB_ReadSectorInfo 0x2b580 
  31. .............................
  32. .............................
  33. .............................
  34. //一直检测到这里
  35. FMD_LB_GetBlockStatus (0xfff)0x3ffc0 
  36. FMD::FMD_LB_ReadSector 0xfff00 
  37. FMD::NAND_LB_ReadSectorInfo 0xfff00 
  38. FMD::FMD_LB_ReadSector 0x3ffc0 
  39. FMD::NAND_LB_ReadSectorInfo 0x3ffc0 
  40. FMD_OEMIoControl: unrecognized IOCTL (0x71c24).
  41. OEMIoControl: Unsupported Code 0x10100d0 - device 0x0101 func 52
  42. OEMIoControl: Unsupported Code 0x10100f8 - device 0x0101 func 62

------根据上面的打印信息启动时候和FMD_LB_GetBlockStatus,FMD::FMD_LB_ReadSector ,NAND_LB_ReadSectorInfo 这几个函数相关。

现在我来看FMD_LB_GetBlockStatus这个函数(被FMD_GetBlockStatus 调用

  1. //  FMD_GetBlockStatus
  2. //
  3. //  Returns the status of a block.  The status information is stored in the spare area of the first sector for
  4. //  the respective block.
  5. //
  6. //  A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
  7. //  根据一些参数确定是大页还是小页,但是这里没有支持我512Mflash的block大小
  8. DWORD FMD_GetBlockStatus(BLOCK_ID blockID)
  9. {
  10.     DWORD dwResult = 0;
  11.     int i;
  12.     if ( blockID < wPRIMARY_NAND_BLOCKS )
  13.     {
  14.         if ( astNandSpec[dwPrimaryNandDevice].nSctsPerPg == 4 )
  15.         {//小心LB_BLOCK_LOOP这个宏定义:#define LB_BLOCK_LOOP   1
  16.             for ( i = 0; i < LB_BLOCK_LOOP; i++ )
  17.             {
  18.                 dwResult |= FMD_LB_GetBlockStatus(blockID*(LB_BLOCK_LOOP) + i, USE_NFCE);
  19.             }
  20.         }
  21.         else
  22.         {
  23.             for ( i = 0; i < SB_BLOCK_LOOP; i++ )
  24.             {
  25.                 dwResult |= FMD_SB_GetBlockStatus(blockID*(SB_BLOCK_LOOP) + i, USE_NFCE);
  26.             }
  27.         }
  28.     }
  29.     else
  30.     {
  31.         if ( astNandSpec[dwSecondaryNandDevice].nSctsPerPg == 4 )
  32.         {
  33.             for ( i = 0; i < LB_BLOCK_LOOP; i++ )
  34.             {
  35.                 dwResult |= FMD_LB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(LB_BLOCK_LOOP) + i, USE_GPIO);
  36.             }
  37.         }
  38.         else
  39.         {
  40.             for ( i = 0; i < SB_BLOCK_LOOP; i++ )
  41.             {
  42.                 dwResult |= FMD_SB_GetBlockStatus((blockID-wPRIMARY_NAND_BLOCKS)*(SB_BLOCK_LOOP) + i, USE_GPIO);
  43.             }
  44.         }
  45.     }
  46.     return dwResult;
  47. }

根据上面的情况,再来看看FMD_LB_GetBlockStatus这个函数原型

  1. //  FMD_LB_GetBlockStatus
  2. //
  3. //  Returns the status of a block.  The status information is stored in the spare area of the first sector for
  4. //  the respective block.
  5. //
  6. //  A block is BAD if the bBadBlock byte on the first page is not equal to 0xff.
  7. //
  8. DWORD FMD_LB_GetBlockStatus(BLOCK_ID blockID, int mode)
  9. {
  10.     SECTOR_ADDR sectorAddr = blockID << LB_NAND_LOG_2_PAGES_PER_BLOCK;
  11.     SectorInfo SI;
  12.     DWORD dwResult = 0;
  13. //这个函数启动的时候会被调用很多次,串口信息打开影响速度
  14.     //RETAILMSG(1, (TEXT("FMD_LB_GetBlockStatus (0x%x)0x%x /r/n"), blockID, sectorAddr));
  15.     BOOL bLastMode = SetKMode(TRUE);
  16.     
  17.     if(!FMD_LB_ReadSector(sectorAddr<<2, NULL, &SI, 1, mode))
  18.     {
  19.         return BLOCK_STATUS_UNKNOWN;
  20.     }
  21.     if(!(SI.bOEMReserved & OEM_BLOCK_READONLY))
  22.     {
  23.         dwResult |= BLOCK_STATUS_READONLY;
  24.     }
  25.     
  26.     if( blockID < pBSPArgs->nfsblk )
  27.     {
  28.         dwResult |= BLOCK_STATUS_READONLY;
  29.     }
  30.     
  31.     if(SI.bBadBlock != 0xFF)
  32.     {
  33.         dwResult |= BLOCK_STATUS_BAD;
  34.     }
  35.     SetKMode(bLastMode);
  36.     return dwResult;
  37. }

 

很明显上面这个函数是根据BLOCKID读这个BLOCK的Spare区的一些信息,从上面的串口信息可以看出,这个函数要把所有的block读完,但是控制这所有block的循环在哪里呢?我现在找不到,真是太奇怪了。因为:#define LB_BLOCK_LOOP   1 所以FMD_GetBlockStatus这个函数在哪里调用了是关键。请看下面他被调用的地方

  1. static BOOL DefineLayout()
  2. {
  3.     PFlashRegion pRegion = NULL;
  4.     DWORD dwBlock = 0;
  5.     if (!FMD_GetInfo (&g_flashInfo)) {
  6.         return FALSE;
  7.     }
  8.     
  9.     // Find the MBR to determine if there is a flash layout sector
  10.     g_dwNumRegions = 0;
  11.     // Find the first usuable block要找的地方就是这里了。哈哈!
  12.     while (dwBlock < g_flashInfo.dwNumBlocks) {
  13.         if (!(FMD_GetBlockStatus(dwBlock) & (BLOCK_STATUS_BAD | BLOCK_STATUS_RESERVED))) {
  14.             break;
  15.         }
  16.         dwBlock++;
  17.     }
  18.     RETAILMSG(1, (TEXT("DefineLayout: dwBlock = 0x%x /r/n"), dwBlock));
  19.     DWORD dwSector = dwBlock * g_flashInfo.wSectorsPerBlock;
  20.     if (!FMD_ReadSector (dwSector, g_pFLSBuffer, NULL, 1)) {
  21.         return FALSE;
  22.     }
  23.     // compare the signatures
  24.     if (IS_VALID_BOOTSEC(g_pFLSBuffer)) 
  25.     {
  26.         if (!FMD_ReadSector (dwSector+1, g_pFLSBuffer, NULL, 1)) {
  27.             return FALSE;
  28.         }
  29.         if (IS_VALID_FLS(g_pFLSBuffer)) 
  30.         {           
  31.             PFlashLayoutSector pFLS = (PFlashLayoutSector)(g_pFLSBuffer);
  32.             
  33.             // Cache the flash layout sector information
  34.             g_dwNumRegions = pFLS->cbRegionEntries / sizeof(FlashRegion);
  35. //          RETAILMSG(1, (TEXT("DefineLayout: g_dwNumRegions = 0x%x /r/n"), g_dwNumRegions));
  36.            
  37.             // FlashRegion table starts after the ReservedEntry table. 
  38.             if (g_dwNumRegions)
  39.             {
  40.                 pRegion = (PFlashRegion)((LPBYTE)pFLS + sizeof(FlashLayoutSector) + pFLS->cbReservedEntries); 
  41.             }
  42.         }
  43.     }
  44.    
  45.     if (!g_dwNumRegions) 
  46.     {
  47.         g_dwNumRegions = 1;
  48.     }
  49.     if (g_dwNumRegions > MAX_REGIONS)
  50.         return FALSE;
  51.     if (pRegion)
  52.     {
  53.         memcpy (g_pRegionTable, pRegion, g_dwNumRegions * sizeof(FlashRegion));
  54.     }
  55.     else
  56.     {
  57.         g_pRegionTable[0].dwStartPhysBlock = 0;
  58.         g_pRegionTable[0].dwNumPhysBlocks = g_flashInfo.dwNumBlocks;
  59.         g_pRegionTable[0].dwNumLogicalBlocks = FIELD_NOT_IN_USE;        
  60.         g_pRegionTable[0].dwBytesPerBlock = g_flashInfo.dwBytesPerBlock;
  61.         g_pRegionTable[0].regionType = FILESYS;
  62.         g_pRegionTable[0].dwSectorsPerBlock = g_flashInfo.wSectorsPerBlock;
  63.         g_pRegionTable[0].dwCompactBlocks = DEFAULT_COMPACTION_BLOCKS;    
  64.     }
  65. //——这个地方非常关键,一些MBR和文件系统相关的东西都在这里了
  66.     RETAILMSG(1, (TEXT("DefineLayout: g_pRegionTable[0].dwNumPhysBlocks = 0x%x /r/n"), g_pRegionTable[0].dwNumPhysBlocks));
  67.     
  68.     return TRUE;
  69. }

不过并没有这么顺利

#if defined (MAGNETO)
static BOOL DefineLayout();
#endif

--------------#if defined (MAGNETO) 这个并没有定义,所以上面的函数并没有被编译。从串口打印信息也可以看的出来。不过FMD_GetBlockStatus在哪里被调用多次呢?真是很晕了。难道是文件系统做的事情?

wogoyixikexie@gliet 说:
我对比了启动正常和不正常的加载饿文件系统DLL,发现有两个DLL没有被加载
wogoyixikexie@gliet 说:
diskcache.dll和fatfsd.dll没有被加载

=======================无计可施,幸好有朋友帮忙===================

gsymichael      2008年11月20日 09点10分23秒 说:
我看到你的帖子了,这个是比较奇怪的一个问题。
因为在存储管理部分对于一个块设备来说,在这里就是你的NandFlash,会创建一个对应的Stroe对象。
之后会通过注册表中Profile中的给定去相应的地方读取驱动的Dll,也就是你的smflash.dll。在这个dll中存储
管理会通过一个IoCtl去获得DISK_INFO的结构,那么这部分由于你是用FAL+FMD的结构这部分在FMD.cpp中没有体现
我之前也搞不清这个是怎么回事,后来网上有人说设置好GetInfo就OK,我猜想这个IoCtl是在FAL里面实现的,然后FAL调用
GetInfo去获得DISK的内容。
现在有个方法,就是你按照我博客的内容把Private下的CoreOS中的Storage移植到你的BSP中,这样你就可以在其中加入Debug
信息调试了。那个存储管理的代码分析我的博客上也有。
还有在你的QQ群里有个三星的技术支持,他也是用FAL+FMD结构的,你也可以问问他。
  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值