none
windows CE4.2下nand flash驱动坏块管理 RRS feed

  • 问题

  • 各位高手:

         windows ce4.2里,Nandflash驱动分为2层,FAL层和FMD层,其中FAL层是以LIB文件形式提供,FMD层则实现一些接口函数,如FMD_GetBlockStatus等。
    本人的平台(pxa255+wce4.2)每次开机的时候都会去检测nandflash的坏区情况,也即有上层模块循环调用FMD_GetBlockStatus(FMD层驱动里的一个函数)去检测,它有8192个block,也即循环执行8192次,很浪费时间。个人觉得已经存在的坏区不用再检测了,出现新的坏区后去更新坏区表而已;如果存在一个坏区表,比如在第0个block,第一次开机的时候先读取三星原有的坏区并更新第0个block,以后就不再读了;如果使用过程中发现坏区,再去更新第0个block;然后在擦除或者写入block的时候,先检测当前是否是坏区,如果是坏区,便转到下一个block。
         现在想修改驱动程序,把开机自检部分去除,但上层FAL代码没有公开,不知怎样去避免FMD_GetBlockStatus函数被循坏调用8192次。我现在的驱动,写入或者擦除的时候没有去检测当前是否坏区。部分代码如下:

                  NF_CMD(CMD_WRITE);

                //  Set up address
                NF_ADDR((unsigned char)(((SectorAddr%4)*512)&0xff));
                NF_ADDR((unsigned char)((((SectorAddr%4)*512)>>8)&0xff));
                NF_ADDR((unsigned char)((SectorAddr/4)&0xff));
                NF_ADDR((unsigned char)(((SectorAddr/4)>>8)&0xff));
                NF_ADDR((unsigned char)(((SectorAddr/4)>>16)&0xff));
                for(i=0; i <NAND_PAGE_SIZE; i++)
                {
                    NF_DATA_W((UCHAR)pSectorBuff);
                }
               
                NF_CMD(0x85);
                NF_ADDR((unsigned char)((2048+((SectorAddr%4)*16))&0xff));
                NF_ADDR((unsigned char)(((2048+((SectorAddr%4)*16))>>8)&0xff));

                //  Write the bad block flag
                NF_DATA_W((unsigned char)(pSectorInfoBuff->bBadBlock));

    问题:
    1、pSectorInfoBuff->bBadBlock的信息从何而来?为什么不是写到第0或第1页的第2048个字节呢?而是NF_DATA_W((unsigned char)(pSectorInfoBuff->bBadBlock));写入呢?
    2、怎样避免系统自动调用FMD_GetBlockStatus函数呢?
    3、nandflash加载FAT文件系统后,第0个block是不是被文件系统占用(比如FAT表区)?还能使用第0个block记录坏块信息吗?
    2008年10月31日 5:06

答案

  • 关于你上面说的1,2和3,也许你看到的并不是真的。因为在检测坏块的同时,也会读取Nandflash的Sector信息,你怎么知道速度慢不是读nandflash造成的呢?所以我想你说的是你主观上的判断,实际可能并不像你想象的那样。

     

    关于4,你不要拿嵌入式系统和PC相比,没什么可比性。

     

    关于5,你的nandflash驱动中有一个函数FMD_EraseBlock就是用来擦除Nandflash的,你在FMD_Init函数最后循环调用这个函数把所有的block都擦除一遍,就可以了。然后再测试一下。

     

     

    WinCE本身就是要跑在性能较高的处理器上面,你的Nandflash驱动也是需要优化的,这样才能提高你的启动速度。你这两块板子启动速度不一样,可能还是你的驱动造成的,你有没有再在第3个板子上面测试呢?

     

     

     

    2008年11月6日 1:53

全部回复

  •  

    1. pSectorInfoBuff应该是一个SectorInfo结构,找到这个结构的定义,看看是写在了什么地方。一般坏块标记都会写在nandflash的带外数据的第0个字节或者第5个字节,大小page不太一样,这里应该遵循nandflash的datasheet上面的描述,写在相应的位置上。

     

    2. 无法避免,这个是由FAL层调用的。

     

    3. WinCE每次启动以后,都会调用FMD_GetBlockStatus获得坏块信息,你不需要再维护了。再说,即使你自己维护的坏块信息对于WinCE系统来说也没用。至于第0个block是否被文件系统占用,这取决于你的nandflash驱动,你完全可以把第0个block空出来。

     

    最后补充一下,真正检测坏块是花不了太多时间的,真正的时间都花在了mount文件系统上了,而且你的文件系统中的文件越多,WinCE启动时间越慢。

    2008年10月31日 5:58
  • 非常感谢你的解答,小弟感激不尽,如果可以,很希望能和你称为好友!

    不过小弟还是有几个疑问,恳请帮忙...

    1、我的FMD_WriteSector函数里没有判断当前块是好是坏,而是直接往扇区写入数据。是不是这样就说明好块坏块的判断是在FAL层实现的?因为好块才允许写入数据,坏块不允许。

    2、FMD驱动里,怎么把第0个block空出来呢?是不是在FMD_WriteSector函数里增加判断,如果是第0个block,就返回FALSE?

    3、在PC机上,硬盘FAT32文件系统也肯定是存储在硬盘上;在Nand Flash上,FAT文件系统的相关信息存放的位置是由FMD驱动程序决定的?

    4、platform.reg上设置了"AutoMount"=dword:1,是不是说文件系统是系统启动后自动mount的?“文件系统中的文件越多”,你说的多,是不是指Nand Flash中存放的文件越多?也即剩余空间越少?

    5、我现在有两套一模一样的系统(pxa255+wce4.2),NandFlash 为1GB,一共8192(编号从0到8191)个块。一套启动正常(共检测出9个坏块),一套启动特别慢(只检测出一个坏块,编号为3000)。也就是说,后者检测到第3000个块的结果时已经占用了很长的时间(1min),是不是因为后者mount文件系统占用了很长时间?为什么两套系统的mount时间不一样呢?

    6、给出我系统的platform.reg如下。

    [HKEY_LOCAL_MACHINE\System\StorageManager\AutoLoad\NandFls]
    "DriverPath"="Drivers\\BuiltIn\\NandFls"
    ;"LoadFlags"=dword:1  ;load synchronously
    "LoadFlags"=dword:0  ;load asynchronously
    ;"Order"=dword:0
    "Order"=dword:4

    [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\NandFls]
    "Dll"="FLASHDRV.DLL"
    ;"Order"=dword:2
    "Order"=dword:4
    "Prefix"="DSK"
    "Ioctl"=dword:4
    "Profile"="NandFls"
    "IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
    "Flags"=dword:1000

    ; Override names in default profile
    [HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NandFls]
    "DefaultFileSystem"="FATFS"
    "PartitionDriver"="mspart.dll"
    "AutoMount"=dword:1
    "AutoPart"=dword:1
    ;"AutoFormat"=dword:1
    "AutoFormat"=dword:0
    "BootPhase"=dword:0
    "Name"="NAND FLASH STORAGE"
    "Folder"="WFFlash"
    "MountFlags"=dword:2


    [HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NandFls\FATFS]
    "FriendlyName"="FAT FileSystem"
    "Dll"="fatfsd.dll"
    ;"Flags"=dword:00000024
    "Paging"=dword:1
    "CacheSize"=dword:0
    "EnableCacheWarm"=dword:0
    "EnableCache"=dword:1
    "MountFlags"=dword:2

    2008年11月1日 7:08
  • 我看过CE5.0/6.0下nandflash的driver的FMD_WriteSector/FMD_ReadSector函数都会带上一个结构体PSectorInfo

     

    BOOL FMD_WriteSector(SECTOR_ADDR startSectorAddr, LPBYTE pSectorBuff, PSectorInfo pSectorInfoBuff, DWORD dwNumSectors)

     

    这个结构体中包含了nandflash每一个sector的附加信息,包括是否是Bad sector, (一般一个block中有一个sector是Bad sector, 这个block就标记为bad block)

     

    关于block0是否是放的fat表, 先来看看SectorInfo的结构

    typedef struct _SectorInfo
    {
     DWORD dwReserved1;    // Reserved - used by FAL
     BYTE  bOEMReserved;    // For use by OEM
     BYTE  bBadBlock;    // Indicates if block is BAD
     WORD  wReserved2;    // Reserved - used by FAL

     DWORD dwReserved3Devil;
    }SectorInfo, *PSectorInfo;

     

    其中bBadBlock 标记坏块, bOEMReserved 标记是否为保留块, 其他的我没有注意, 好象还有标识是否是只读的信息

    在nandflash的driver中, 被标记为BadBlock和OEMReserved 的block是不可用的块, 所以你想保留住block0就可以把它标记为OEMReserved.  Wince启动只会去访问可用的块, 所以第一个可用的块必定包含MBR, 

    MBR包含你的分区信息, 你有多少个分区, 每个分区的文件系统都在这里决定

     

    关于为什么检测flash那么慢, 我就不得而知了

    2008年11月2日 1:08
  •  

    非常感谢朋友们的关注,不过小弟的几个问题还是没有答案...呵呵,希望高手们走过路过,给予指点迷津...老板下了最后通牒了...

     

    1、我的FMD_WriteSector函数里没有判断当前块是好是坏,而是直接往扇区写入数据。是不是这样就说明好块坏块的判断是在FAL层实现的?因为好块才允许写入数据,坏块不允许。

    2、platform.reg上设置了"AutoMount"=dword:1,是不是说文件系统是系统启动后自动mount的?wce_studying说“文件系统中的文件越多,系统mount文件系统越慢”,是不是指Nand Flash中存放的文件越多?也即剩余空间越少?

    3、我现在有两套一模一样的系统(pxa255+wce4.2),NandFlash 为1GB,一共8192(编号从0到8191)个块。一套启动正常(共检测出9个坏块),一套启动特别慢(只检测出一个坏块,编号为3000)。也就是说,后者检测到第3000个块的结果时已经占用了很长的时间(1min),是不是因为后者mount文件系统占用了很长时间?为什么两套系统的mount时间不一样呢?

    4、给出我系统的platform.reg如下。

    [HKEY_LOCAL_MACHINE\System\StorageManager\AutoLoad\NandFls]
    "DriverPath"="Drivers\\BuiltIn\\NandFls"
    ;"LoadFlags"=dword:1  ;load synchronously
    "LoadFlags"=dword:0  ;load asynchronously
    ;"Order"=dword:0
    "Order"=dword:4

    [HKEY_LOCAL_MACHINE\Drivers\BuiltIn\NandFls]
    "Dll"="FLASHDRV.DLL"
    ;"Order"=dword:2
    "Order"=dword:4
    "Prefix"="DSK"
    "Ioctl"=dword:4
    "Profile"="NandFls"
    "IClass"="{A4E7EDDA-E575-4252-9D6B-4195D48BB865}"
    "Flags"=dword:1000

    ; Override names in default profile
    [HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NandFls]
    "DefaultFileSystem"="FATFS"
    "PartitionDriver"="mspart.dll"
    "AutoMount"=dword:1
    "AutoPart"=dword:1
    ;"AutoFormat"=dword:1
    "AutoFormat"=dword:0
    "BootPhase"=dword:0
    "Name"="NAND FLASH STORAGE"
    "Folder"="WFFlash"
    "MountFlags"=dword:2


    [HKEY_LOCAL_MACHINE\System\StorageManager\Profiles\NandFls\FATFS]
    "FriendlyName"="FAT FileSystem"
    "Dll"="fatfsd.dll"
    ;"Flags"=dword:00000024
    "Paging"=dword:1
    "CacheSize"=dword:0
    "EnableCacheWarm"=dword:0
    "EnableCache"=dword:1
    "MountFlags"=dword:2


     

    2008年11月4日 10:40
  •  

    1. FMD_WriteSector函数中不需要判断,FAL层会掉用FMD_GetBlockStatus函数判断坏块。你应该看看微软提供的参考代码。

     

    2. Automount是指自动mount文件系统。每次启动,系统都会扫描整个Nandflash,读取Sector信息。如果你的Nandflash上的文件系统中没有任何文件,启动会相对快。但是如果启动以后,你拷贝了很多目录和文件在Nandflash上面,那么启动就会变慢。

     

    3. 你的两套完全一样的系统,用的是同一个WinCE image么?确认注册表配置和驱动都是一样的。你最好把两个系统上面的Nandflash都全部擦除一遍,然后看看启动速度是否还是相差很大?

     

     

    2008年11月5日 3:27
  • 再次感谢 WinCE_Studying的指点...

     

    1、我通过修改FMD层驱动代码,发现FAL层调用FMD_GetBlockStatus函数判断坏块时,前1000多个坏块检测非常慢,后面的就非常快。

     

    2、我把FMD_GetBlockStatus中设置为固定值,即没有任何访问实际nand flash的操作,依然出现坏块检测快慢不一的怪现象。

     

    3、我在想是不是不同的block,上层FAL的处理过程不一样?导致坏块检测前后时间不一样?不然为什么一个空函数的执行时间会前后不一样呢?

     

    4、你说的“nand flash存放的目录和文件越多,启动越慢”,小弟非常认同,可就是不明白的是,我的另一套系统上面的文件也不少,两者几乎一样多。另外,为什么PC机硬盘存放东西越多,启动并不变慢呢?nand flash的这种特性是不是太不合理呢?或者说,有方法可以避免这种结果的出现?不然将来nand flash基本饱和时,机器甚至无法启动了。

     

    5、小弟还没有尝试过擦除nand flash呢,看到FMD代码里有,但不知道该怎么去擦除?在PC机上,格式化U盘只需要右键选择‘格式化’就可以了,不知道wce上怎么格式化。

    2008年11月6日 1:09
  • 关于你上面说的1,2和3,也许你看到的并不是真的。因为在检测坏块的同时,也会读取Nandflash的Sector信息,你怎么知道速度慢不是读nandflash造成的呢?所以我想你说的是你主观上的判断,实际可能并不像你想象的那样。

     

    关于4,你不要拿嵌入式系统和PC相比,没什么可比性。

     

    关于5,你的nandflash驱动中有一个函数FMD_EraseBlock就是用来擦除Nandflash的,你在FMD_Init函数最后循环调用这个函数把所有的block都擦除一遍,就可以了。然后再测试一下。

     

     

    WinCE本身就是要跑在性能较高的处理器上面,你的Nandflash驱动也是需要优化的,这样才能提高你的启动速度。你这两块板子启动速度不一样,可能还是你的驱动造成的,你有没有再在第3个板子上面测试呢?

     

     

     

    2008年11月6日 1:53
  • thanks,英雄!

     

    真的了,我在调试中发现,启动时nand flash既循环读取每个sector的信息,又去读取坏块的信息,导致读取前1000个坏块特别慢,因为是同时做两件事情。不过系统为什么要不厌其烦的去读取每个sector的信息?1GB的flash总共有8192个block,每个block有256个secotr,这样循环去读太浪费时间了,有何意义呢?

     

    我现在还真的不明白如何去优化驱动程序,因为我能控制的部分只有FMD层,FAL层代码都没有公开(我的版本是wce4.2),读取sector的函数就是去读nand flash的sector,上层循环去调,根本无法避免;就像当初我很想屏蔽上层循环调用FMD_GetBlockStatus去读取坏块一样...

     

    暂时没有第三块板子,问题是,我才接手这个板子,听之前做的人说,板子nand flash的启动速度是逐渐变慢...这个暂时也无法得到解释...

    2008年11月6日 6:14
  •  

    两套板子,同一个内核,我在FMD_ReadSector函数中规定,如果当前sector的序号是50000的倍数,就打印一条信息出来。

    代码中,读取坏块的打印信息为:

    IsBlockBad(block的编号): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD

     

    读取sector的打印信息为:

    FMD_ReadSector(sector编号,0,40AEE54,1)

     

    结果打印信息分别如下:

     

    1、启动较慢的板子

    FMD_ReadSector(50000,0,40AEE54,1)
    FMD_ReadSector(100000,0,40AEE54,1)
    FMD_ReadSector(150000,0,40AEE54,1)
    FMD_ReadSector(200000,0,40AEE54,1)
    FMD_ReadSector(250000,0,40AEE54,1)
    FMD_ReadSector(300000,0,40AEE54,1)
    FMD_ReadSector(350000,0,40AEE54,1)
    IsBlockBad(ADD): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    FMD_ReadSector(800000,0,40AEE54,1)
    FMD_ReadSector(1600000,0,40AEE54,1)

    2、启动较快的板子

    FMD_ReadSector(50000,0,40AEE54,1)
    IsBlockBad(F9): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    FMD_ReadSector(100000,0,40AEE54,1)
    IsBlockBad(353): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    IsBlockBad(6EB): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    IsBlockBad(83E): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    IsBlockBad(BE7): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    FMD_ReadSector(800000,0,40AEE54,1)
    IsBlockBad(EC0): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    FMD_ReadSector(1600000,0,40AEE54,1)
    IsBlockBad(1948): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    IsBlockBad(1C80): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD
    IsBlockBad(1FBB): TRUE(0)
    FMD::FMD_GetBlockStatus-------BLOCK_STATUS_BAD

     

    由上可知,

    1、启动时nand flash读取每个sector的信息和读取坏块信息是同时进行的。

    2、sector的读取并不是从第0个读到最后一个,大概到了160000后便停止了。

    3、sector读取的越多,启动速度越慢,这就是第2块板子启动较快的原因了。

    4、sector的读取并非严格连续,读到800000和1600000就是跳跃性的。

     

    问题:

    1、FAL层读写sector的目的是什么?为什么还是非严格连续的读呢?

    2、有没有办法阻止上层循环读sector呢?好像在FMD层是无法阻止的。

    2008年11月6日 7:53
  •  

    你有没有测试一下把两片Nandflash全部擦除,然后比较一下时间呢?

     

    你用的是什么平台,介绍一下?

    2008年11月7日 1:43
  • 是准备去擦除测试的,不过由于上面数据较多,暂时还没有动手去做,还要请示下其他人。

     

    我的平台是pxa255+wce4.2,Nand Flash是三星的1GB的。问题就是前面那个帖子所讲的,启动速度慢是因为去读那么多sector的状态!

    2008年11月7日 1:51
  • 读Sector是很正常的,不读才不正常呢。甚至每次读只是读一个扇区的Sector信息,也就几个字节。所以你的FMD_ReadSector函数会被频繁的调用,这个取决于你的Nandflash上面的文件系统。

     

    让你完全擦除两片Nandflash就是为了区分是否是由于文件系统造成的。

     

    2008年11月7日 4:40
  •  

    虽然这篇帖子我之前的几次发言中提出的问题到现在还有不少没有得到解决,但还是非常感谢WinCE_Studying你的殷切指导。下一步我准备去擦除nand flash,那么擦除nand flash时,是不是首先要调用FMD_GetBlockStatus获得块的状态,如果是好块,才调用FMD_EraseBlock擦除;否则跳过?
    2008年11月7日 7:11
  • 2008年11月7日 7:25