一种基于FAT文件系统的NANDFLASH管理方法 【技术领域】
本发明涉及NANDFLASH的应用,特别是一种基于FAT文件系统的NANDFLASH管理方法。
背景技术
FAT文件系统是MicroSoft早期提出的一种文件管理方法,现在多用于PDA设备上。由于Nandflash的结构和工艺问题决定了基于Nandflash的FAT文件系统和基于硬盘上的FAT文件系统是有差别的。Nandflash下的FAT文件系统大致可以分为以下几个部分:
(1)、DBR区:对于NANDFLASH,最重要的就是BPB(BIOS Parameter Block)区,它位于DBR区的跳转指令和厂商标志以及OS版本号之后的53个字节,里面记录了文件系统的相关信息,比如:Nandflash的类型、版本号、每扇区字节数、每簇的扇区数、Nandflash容量等。另外还有Nandflash的逻辑分区表和主引导程序,以55AA为结束标记;
(2)、保留区:在FAT表之前的所有扇区,包括DBR扇区,在FAT16中,保留区一般为1个扇区,仅有DBR区,而在FAT32中一般为32,其作用主要是对一些重要的信息进行备份,以防数据丢失而无法找回;
(3)、FAT表区:记录Nandflash的利用情况,以簇为单位,每个簇占用FAT表的2Bytes,空闲簇用00 00来表示,所以最多可以管理65536个簇;其中在FAT文件系统中都是高字节在后,低字节在前的表示方式,比如第三簇,正确的表示方式应该是:03 00,而不是00 03;
(4)、根目录区:记录文件名的编号、文件大小、修改时间、数据簇链的起始簇等文件属性;
(5)、数据区:存放数据的地方。
NANDFLASH作为一种非易失存储器,具有存储速度快、体积小、容量大、掉电数据不丢失等特性,具有很高的性价比,因而被广泛的应用于各行个业。但是由于工艺上的问题使得NANDFLASH在出厂或是应用的过程中都会出现坏块,坏块一般可以分为两类:一是固有坏块,即芯片出厂就存在,厂家会在坏块第一页的SpareArea区的第六个字节处标记,若标记为非0xFF,则表明是坏块;另一类是使用坏块,即在使用过程中出现的坏块。对于坏块,这是一个很笼统的概念,除了连擦除命令都不能成功的块绝对是坏块之外,其余类型的坏块都是相对的,也就是说某个坏块里面也许只有一个或几个Bit不能正常的读写,而其余的Bit都能正常的读写,这也说明了如果数据纠错能力强的话,所谓的坏块会少很多。由于坏块是不能使用的,所以这就给我们的开发加大了难度。
传统的管理方法是先定义一个坏块表,然后检测出坏块,再将坏块标记入坏块表,为了节约空间,坏块一般都以一个Bit来表示(0则代表好块;1则代表坏块),之后再建立一个映射表来将块的物理地址信息转换成逻辑地址信息,通过逻辑地址去对应相应的物理地址,由于映射表已经将坏块剔除,所以在表面上看来NANDFLASH的地址空间是连续的,其实在物理上并不连续。这是一种在底层解决坏块问题的方法,它为上层的文件系统提供一个看似连续的存储介质,这种方法最大的优点在于通用性很强,因为它在底层已经将坏块处理掉了,非FAT文件系统同样可以凌驾于它之上。
但是这种在底层解决坏块问题的方法有这样几个缺点:
1、因为坏块表和映射表的问题,使得它的算法变得相对复杂,代码量加大,从而耗费大量的CPU资源,使系统的速度变慢;
2、因为其需要建立坏块表和映射表,所以其耗费的存储空间也会增加。
【发明内容】
本发明为解决上述问题提供了一种基于FAT文件系统的NANDFLASH管理方法,特别适用于嵌入式设备、工控等需要用NANDFLASH作为存储介质的地方,直接在FAT表上标记坏块,而不用单独地去建立坏块表和映射表。
一种基于FAT文件系统的NANDFLASH管理方法,其特征在于:首先是对NANDFLASH中的各个块进行检测,找出坏块,然后对坏块进行处理,将坏块的物理地址转换成簇号,最后在FAT表中将坏块的簇号标记,所述标记的值大于FAT表中最大的簇号。
所述坏块的物理地址转换成簇号是通过坏块处理程序进行转换的,转换的代码为:
for(i=0;i<ClusPerBlk;i++)
{
BadClusNum[i]=BadBlkNum*ClusPerBlk+2;
}
其中,ClusPerBlk表示每块的簇数;BadClusNum表示坏块所对应的簇号;BadBlkNum表示坏块地址,+2是因为FAT表里面的簇号是从2开始的。假设一片NANDFLASH的每一块有4个簇(每一块具体有几个簇需要由电脑根据NANDFLASH的容量来确定,这里只是假设),如果检测出了第二块是坏块,那么根据以上的换算代码就知道此块所对应的簇号是10、11、12和13簇;最后在FAT表中把簇号所对应的位置做上标记,标记完成之后再更新FAT表。
所述检测是先擦除块,当擦除块不成功时,则说明其为坏块,当擦出成功则向该块写数据,然后将写入的数据读出和原始数据(即刚才擦出成功后写入的数据)进行比较,当两者有差异则表示该块为坏块。
在做坏块标记的时候,标记值一定要大于最大的簇号,是为了使标记值不与有效的簇号重复,而且这样的话在写入文件的时候永远都不会写到这个簇上来。
本发明的有益效果如下:
本发明不用单独的去建立坏块表和映射表,而是将坏块信息标记于FAT表之上,这种通过在文件系统上去处理的方法适用于基于FAT文件系统的设备,方法简单,代码量少,不会耗费大量的CPU资源和存储空间,可以有效提高系统的可靠性和稳定性,开发周期较短。
【附图说明】
图1为本发明的坏块检测流程图
【具体实施方式】
实施例1
如图1所示,一种基于FAT文件系统的NANDFLASH管理方法,首先是对NANDFLASH中的各个块进行检测,找出坏块,然后对坏块进行处理,将坏块的物理地址转换成簇号,最后在FAT表中将坏块的簇号标记;所述标记的值必须大于FAT表中最大的簇号,是为了使标记值不与有效的簇号重复,而且这样的话在写入文件的时候永远都不会写到这个簇上来。
所述坏块的物理地址转换成簇号是通过坏块处理程序进行转换的,转换的代码为:
for(i=0;i<ClusPerBlk;i++)
{
BadClusNum[i]=BadBlkNum*ClusPerBlk+2;
}
其中,ClusPerBlk表示每块的簇数;BadClusNum表示坏块所对应的簇号;BadBlkNum表示坏块地址,+2是因为FAT表里面的簇号是从2开始的。假设一片NANDFLASH的每一块有4个簇(每一块具体有几个簇需要由电脑根据NANDFLASH的容量来确定,这里只是假设),如果检测出了第二块是坏块,那么根据以上的换算代码就知道此块所对应的簇号是10、11、12和13簇;最后在FAT表中把簇号所对应的位置做上标记,标记完成之后再更新FAT表。
所述检测是先擦除块,当擦除块不成功时,则说明其为坏块,当擦出成功则向该块写数据,然后将写入的数据读出和原始数据进行比较,当两者有差异则表示该块为坏块。
下面是一个典型的FAT表的一部分。
offset 0 1 2 3 4 5 6 7 8 9 A B C D E F 0x0000 F8 FF FF FF 00 00 00 00 00 00 08 00 07 00 FF FF 0x0001 0C 00 FF FF
F8 FF FF FF是FAT表的开始标志。
00 00表示为空闲簇。
FF FF是文件结束标志。
比如要读出一个文件,假设它的开始簇是第5簇,FAT表上第5簇上的内容为0800,接下来就到达第8簇,第8簇上的内容是0C00,然后到达第12簇,第12簇的内容为FFFF,表示此文件最后的数据不足一簇,读文件到此结束(也就是说这个文件的数据位于第5、8、12簇上)。如果我们要写入一个文件,首先是在根目录区查找一个空闲的目录,然后再在FAT表上查询空闲的簇(查询空闲标志0000),查找到之后擦出该簇对应的物理块,若擦出失败,则把该块所对应的簇标上FE FF,以表明不可用,否则向此簇写入数据,写入之后再读出,之后再进行数据纠错,如果纠错之后的数据和原来的数据都不一样,则把该块所对应的簇标上FE FF,以表明不可用,标好之后继续查找空闲簇,直到文件写入完成,然后更新FAT表。
实施例2
当NANDFLASH被格式化的时候,电脑会根据FLASH的容量计算出相关的信息放入DBR中,FAT将FLASH空间按照一定数目的扇区进行划分,每个扇区512Bytes,多个扇区构成一个“簇”。以下结构体为DBR内的详细信息:
#define UINT8 unsigned char
#define UINT16 unsigned int
#define UINT32 unsigned long
typedef struct
{
UINT8 jmpBoot[3]; /*跳转指令 */
UINT8 OEMName[8]; /*厂商名 */
UINT16 BytsPerSec; /*每扇区字节数 */
UINT8 SecPerClus; /*每簇扇区数 */
UINT16 RsvdSecCnt; /*保留扇区数 */
UINT8 NumFATs; /*FAT表个数 */
UINT16 RootEntCnt; /*根目录文件最大数,FAT32中为0 */
UINT16 TotSec16; /*扇区总数,FAT32中为0 */
UINT8 Media; /*介质描述符 */
UINT16 FATSz16; /*每FAT扇区数 */
UINT16 SecPerTrk; /*每磁道扇区数 */
UINT16 NumHeads; /*磁头数(面数) */
UINT32 HiddSec; /*隐藏扇区数 */
UINT32 TotSec32; /*若BPB_TotSec16=0,记录总扇区数 */
UINT8 DrvNum; /*中断13的驱动器 */
UINT8 Reserved1; /*保留 */
UINT8 BootSig; /*扩展引导标记 */
UINT32 VolID; /*卷序列号 */
UINT8 VolLab[11]; /*卷标 */
UINT8 FilSysType[8]; /*文件系统类型 */
UINT8 Code[448]; /*引导代码 */
UINT16 Over; /*结束标志 */
}DBRINFO;
以三星K9K8G08U1M为例,它有4096个blocks,每个block包含64pages,而每个page由4个sectors和64bytes的spare area组成,总的大小为512M+16M(16M是spare area)。下面是在此块NANDFLASH上建立的FAT文件系统的DBR区信息。
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01:EB 3C 90 4D 53 57 49 4E 34 2E 31 00 02 10 01 00
02:02 00 02 00 00 F8 F9 00 20 00 3E 00 20 00 00 00
03:00 86 0F 00 80 00 29 22 96 1B 00 61 61 61 00 00
04:00 00 00 00 00 00 46 41 54 31 36 20 20 20 FA 33
05:C0 8E D0 BC 00 7C 16 07 BB 78 00 36 C5 37 1E 56
06:16 53 BF 3E 7C B9 0B 00 FC F3 A4 06 1F C6 45 FE
07:0F 8B 0E 18 7C 88 4D F9 89 47 02 C7 07 3E 7C FB
08:CD 13 72 79 33 C0 39 06 13 7C 74 08 8B 0E 13 7C
09:89 0E 20 7C A0 10 7C F7 26 16 7C 03 06 1C 7C 13
10:16 1E 7C 03 06 0E 7C 83 D2 00 A3 50 7C 89 16 52
11:7C A3 49 7C 89 16 4B 7C B8 20 00 F7 26 11 7C 8B
12:1E 0B 7C 03 C3 48 F7 F3 01 06 49 7C 83 16 4B 7C
13:00 BB 00 05 8B 16 52 7C A1 50 7C E8 92 00 72 1D
14:B0 01 E8 AC 00 72 16 8B FB B9 0B 00 BE E6 7D F3
15:A6 75 0A 8D 7F 20 B9 0B 00 F3 A6 74 18 BE 9E 7D
16:E8 5F 00 33 C0 CD 16 5E 1F 8F 04 8F 44 02 CD 19
17:58 58 58 EB E8 8B 47 1A 48 48 8A 1E 0D 7C 32 FF
18:F7 E3 03 06 49 7C 13 16 4B 7C BB 00 07 B9 03 00
19:50 52 51 E8 3A 00 72 D8 B0 01 E8 54 00 59 5A 58
20:72 BB 05 01 00 83 D2 00 03 1E 0B 7C E2 E2 8A 2E
21:15 7C 8A 16 24 7C 8B 1E 49 7C A1 4B 7C EA 00 00
22:70 00 AC 0A C0 74 29 B4 0E BB 07 00 CD 10 EB F2
23:3B 16 18 7C 73 19 F7 36 18 7C FE C2 88 16 4F 7C
24:33 D2 F7 36 1A 7C 88 16 25 7C A3 4D 7C F8 C3 F9
25:C3 B4 02 8B 16 4D 7C B1 06 D2 E6 0A 36 4F 7C 8B
26:CA 86 E9 8A 16 24 7C 8A 36 25 7C CD 13 C3 0D 0A
27:4E 6F 6E 2D 53 79 73 74 65 6D 20 64 69 73 6B 20
28:6F 72 20 64 69 73 6B 20 65 72 72 6F 72 0D 0A 52
29:65 70 6C 61 63 65 20 61 6E 64 20 70 72 65 73 73
30:20 61 6E 79 20 6B 65 79 20 77 68 65 6E 20 72 65
31:61 64 79 0D 0A 00 49 4F 20 20 20 20 20 20 53 59
32:53 4D 53 44 4F 53 20 20 2053 59 53 00 00 55 AA
上表中的下划线部分即是53个bytes的BPB信息,从表中可以知道:
每扇区的字节数:BytesPerSector=0x0200;
每簇的扇区数:SecPerClus=0x10;
总的扇区数:TotSec32=0xF8600;
由于SecPerBlock=256。
所以可以算出每块的簇数:
ClusPerBlock=SecPerBlock/SecPerClus=16。
下表是经过坏块处理之后的FAT表的一个扇区(表中已经做了坏块标记):
00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F
01:F8 FF FF FF 00 00 00 00 00 00 00 00 00 00 00 00
02:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
03:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
04:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
05:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
06:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
07:00 00 00 00 FE FF FE FF FE FF FE FF FE FF FE FF
08:FE FF FE FF FE FF FE FF FE FF FE FF FE FF FE FF
09:FE FF FE FF 00 00 00 00 00 00 00 00 00 00 00 00
10:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
11:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
12:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
13:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
14:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
15:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
16:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
17:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
18:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
19:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
20:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
21:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
22:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
23:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
24:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
25:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
26:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
27:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
28:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
29:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
30:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
31:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
32:00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00