由于NAND FLASH擦除时,只能按按块擦除,因此在写扇区时,
首先要擦除一个块。在擦除块前,必须将块内其他数据复制出来,
由于一个块比较大(128KB),无法在MCU内开辟如此大的缓冲区。
只好借助该NAND FLASH内的页复制命令,将原来的块暂时复制到
一个交换用的交换块中。但是如果仅用一个块作为交换的话,它
就会被频繁擦写,因而寿命会大大降低。所以在该系统中,保留了
10个块用来作为交换区,轮流使用。另外对扇区的连续写进行了
优化,当连续写扇区时,就不必每次重复上面的操作,只有当地址
跨块时,才需要重新擦除。连续写扇区的实现原理如下:当检测到
扇区地址跨块时,就把原来的整块数据复制到交换块中,然后将
该块内当前所写地址的前面部分页面复制到原来的块中,接着就从
交换块中取出当前扇区地址所在页(使用页复制-随机写入命令),
再把一个扇区的数据写入,并接着写入其他扇区,当扇区地址跨页
时,就把该页写入到原来的块中,直到扇区被写完(当然如果写
的过程中跨块了,还需要重复前面的块擦除以及复制过程)。接着
把交换块中剩余的页再复制回原来的块中,这样一个连续写过程就
完成了。
因为NAND FLASH在生产和使用过程中,会产生坏块,所以必须
增加坏块管理。在该系统中,保留了50个块用做坏块管理。当上述
的擦、写过程中,如果发现坏块,那么就把该块的地址重新影射到
一个保留的块中。以后每次对该坏块地址操作时,都被重新定位到
新的块地址。使用一个二维数组来保存该影射关系。二维数组的前
半部分为坏块地址,后半部分为重新影射过后的块地址。每当发现
坏块时,就需要重建这张表(主要是增加新的影射并排序,方便地
址重新影射的二分查表法),并将其三份一样的写入到专门为此而
保留的三个块中。之所以使用三个备份保存,是考虑到这些数据的
重要性,因为一旦这个影射关系被破坏,后果将会是灾难性的。在
保存这个表格时,做了特殊处理,首先标志他们准备擦除,然后才
依次擦除并写入数据,这样即使在操作过程中突然断电,也至少有
两个块的备份数据是可以用的,在系统开机初始化时,可以将这些
数据恢复。数据使用了特殊标志(0x0055AAFF)以及累加和校验来
判断是否有效。对于新出厂的FALSH,在加载坏块表时,就会校验
失败,程序就会假设没有坏块并初始化该数组后保存。每个备用块
还由另外一个数组用来标志其状态(未用、已损坏、已用等)。
当需要使用新的备用块时,就从该数组中查找未用的,并标志为
已用。如果备用块本身是坏的,那么就标志它已损坏。该数组与
坏块重影射表一并保存。此外还保存了当前坏块的数量。
地址的重新影射过程:当对一个地址进行读写操作时,首先要
对其进行重影射。首先判断是否有坏块,当坏块数量为0时,就直接
返回原来的地址即可。当坏块数量不为0时,先判断最后一次访问和
本次访问的地址是否属于同一页,如果属于,那么就直接影射到上
一次影射过的块地址。如果不属于,那么就需要去查坏块影射表了。
如果只有一个坏块,只要直接比较即可,不用查表。如果坏块数量
大于2,那么就需要查表。由于表中地址是按从小到大的顺序排列的,
所以可以先和第一个和最后一个判断,如果不在该范围内,那么也
不用重新影射,返回原来的地址即可。如果在该范围内,就使用二
分查表法查表,搜索它是否在坏块表中。如果是的话,就重新影射
地址,并将这个地址保存,以备下一次重影射时地址未跨块直接使用。
最大支持50个坏块,在最坏的情况下,该二分查表法需要判断6次。