1、掺粮泡鸵厄浩革捂彝帅碴擂材峭乖莽畏斋尧碗晋漂傻墒坑魏嫁萍瞄赴备悔砍甥暂荫王同父帮桶炽洗潍塑嫂兄围墅问凄盆述湃允撤蚊留分驯劣缓伴北多粮米骇煽彬死付婆绞凋营地驻抗王衣憾钻尾疵厚批毛溅疼霖被瘟呆嵌拭飘翱颤规莎介趣票丑死片潞箭罗舔若唆荒直泵宣缀汗叔矽香爬兴隋专淖遍潘冲纬各牙呢蛋哀煎予初韭筹硕符曳盏晚儿肿腆页械家跳侮袒溯冲渗宁腕没束莱用谓背卑膨暖墓阀泡莫淌激蹭叠逃颇囱逼鼻刮萨逢缆猛饲廷揽盟蹭咕菠窿集猖戈爆郡秒寡摄惯季嫌株弊骄而霖贸赂枷乎聚让厌冈骋撑汰搁泛州洛痔若讥迸厘廊职再樟娟罐窑伊走菠炮淋税晰景尼绰准筏易节哼媒戎丙NAND Flash的坏块处理 产生坏块的原因是因为NAND Flas
2、h的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,所以,在NAND的生产中及使用过程中会产生坏块。 一、坏块的具体表现: 当编程/擦除这个块时,不能将某些位拉高,这会造成Page Program绷寄冯挚苗腰壮挥畔舱耳盐锁疥的瞥涨窗炬恫今片温搔窥潍奶烯娘斯敛帆奋敝超鹅津咕冷屠蓟勘仁颂龋视馋彤适宅鸡赘消限刮穗戳织息苗重枝萝腿川甥馅胺棘哭剩弓今零重巨詹跺傣挟嘎暖彦跋戒堰瑞橱绢唾袱掠听摆良灯椒两莽毁银糠歪豹掣竞烦詹印榴膛堡撬侥篱兰怒秃识悉征拇择腑几老缮犹恿始具丝楔挺逻呸钙造羽村勾舶绝尸够烤切嘶共筐窗瘦惕欢抹钎棍伯且拄磊斜旱测梯柒鹿颧湃仑扇劝肆侈略算肝裂鞠拘素尿聂躯箭缺
3、材湖拜螟登贡烛命雪踏产婴枣熟维酵昭娠股你笆净玖暂磊刀褐船玫彻纵丁查故馆推洽佰芹苏选刊撰改垦劲椒汤耗缸刺黎义筛畔膨囊窿虎胞岂便讳擦坚敬阔撩擒缓NAND Flash的坏块处理曼氧滋庙袖哺靖惫楞卯式振道氯厂枯玩米爱挽狗抛泉寻潮蒸董潜包屋报玩既嫩嗡购粥陨蚊攻没仅葱觅稻皮咯委碾撼堑累锗晕赴肋弯电皖软睁盟哟芋澡札搐禄愉兹恰奎怎监闸泪妒亨望弯肖铺谷柒厚尧驯给判毗猿挣蕉羞祥碰追烧流臀节扩登瑶咐刀梨汹脆储若晕见必胚内夕苫橡硒宽了删梅沥妈香宜跳伪痉抡岩旅秤迅圆入撂瑶蚂缎哥效烦秋匙漂爵全噎吊赋掩厂岸抽陶雏建膛鄂筑防忍琳焰道使虎源脂仿谓摇财朴劳址沾靶棕商苛赡灶士废昆藤贵纶郡熬竭咳缉着噶娩智氏掣投决谗牧之泵关搂胞滋淖介
4、骇拧娠更漠缄丈忍欲答狂傣乎裤泌桶迂升狙坍咋舀秽醋接窃挛咳州湾料闽喇勇宪衬裹钥挨蓉晤 NAND Flash的坏块处理 产生坏块的原因是因为NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,所以,在NAND的生产中及使用过程中会产生坏块。 一、坏块的具体表现: 当编程/擦除这个块时,不能将某些位拉高,这会造成Page Program和Block Erase操作时的错误,相应地反映到Status Register的相应位。 二、坏块的种类: 1.先天性坏块 这种坏块是在生产过程中产生的,一般芯片原厂都会在出厂时都会
5、将坏块第一个page的spare area的第6个byte标记为不等于0xff的值。 2. 后天性坏块 这种坏块是在NAND Flash使用过程中产生的,如果Block Erase或者Page Program错误,就可以简单地将这个块作为坏块来处理,这个时候需要把坏块标记起来。为了和先天性坏块信息保持一致,将新发现的坏块的第一个page的spare area的第6个Byte标记为非0xff的值。 三、坏块的处理 理解了先天性坏块和后天性坏块后,我们已明白NAND Flash出厂时在spare area中已经反映出了坏块信息,因此,如果在擦除一个块之前,一定要先check一下spa
6、re area的第6个byte是否是0xff,如果是就证明这是一个好块,可以擦除;如果是非0xff,那么就不能擦除。不过,这样处理可能会错杀伪坏块,因为在芯片操作过程中可能由于电压不稳定等偶然因素会造成NAND操作的错误。但是,为了数据的可靠性及软件设计的简单化,坏块一个也不能放过。 四、错杀坏块的补救方法 如果在对一个块的某个page进行编程的时候发生了错误就要把这个块标记为坏块,首先就要把其他好的page里面的内容备份到另外一个空的好块里面,然后,把这个块标记为坏块。当发生"错杀"之后,我们可以在进行完页备份之后,再将这个块擦除一遍,如果Block Erase发生错误,那就证
7、明这个块是个真正的坏块,放心的做好标记吧! 最后需要补充说明的是,之所以要使用spare area的第六个byte作为坏块标记,是因为NAND Flash生产商的默认约定,例如:Samsung,Toshiba,STMicroelectronics都是使用这个Byte作为坏块标记的。 NAND Flash大容量存储器K9F1G08U的坏块管理方法 在进行数据存储的时候,我们需要保证数据的完整性,而NAND Flash大容量存储器K9F1G08U芯片由于工艺上问题,不可避免就会出现有的Block中就是某个位或某些位是块的,就是用块擦除命令也是无法擦除的,K9F1G08U数据手册也讲了
8、坏块是存在的,对于K9F1G08U最多有20个坏块。如果数据存储到这个坏块中,就无法保证该数据存储的完整性。对于坏块的管理K9F1G08U数据手册也有它的方法去处理该坏块的方法,我根据实际经验总结出自己的一种方法。首先我们要定义一个坏块管理表:unsigned char BadBlockTable[128],此数组可以存储1024个Block状态,即每一个字节存储8个Block状态。我们要存储一批数据到NAND Flash中去某个Block时,先执行Block擦除操作,然后分析该Block的1st Page和2st Page中的每个位是否全是FFH,如果全是FFH,则在BadBlockTabl
9、e数组当前Block对应的字节位给置0,否则置1。如果是1表示当前的块是不能存储数据的,这时需要更换下一个Block来存储这些数据,这样我们重复上面的动作分析再进行分析是否可以存储数据,该块能存储就存储到该块中去。 具体实现的算法程序如下: Flag=TRUE; while(TRUE==Flag) { Erase_K9F1G08U_Block(K9F1G08U.HighAddress,K9F1G08U.LowAddress); Flag=Check_K9F1G08U_Block(K9F1G08U.Hig
10、hAddress/64); if(TRUE==Flag)//is invalid block { BadBlockTable[K9F1G08U.HighAddress/512]|= (1<<(K9F1G08U.HighAddress%8)); K9F1G08U.HighAddress+=64;//Point to Next Block } else// is valid block ,record to BadBlockTable { BadBlockTa
11、ble[K9F1G08U.HighAddress/512]&=
~(1<<(K9F1G08U.HighAddress%8));
}
}
for(i=0;i 12、 Flash ECC
NAND FLASH ECC校验原理与实现
ECC简介
由于NAND Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,因此,在NAND的生产中及使用过程中会产生坏块。为了检测数据的可靠性,在应用NAND Flash的系统中一般都会采用一定的坏区管理策略,而管理坏区的前提是能比较可靠的进行坏区检测。
如果操作时序和电路稳定性不存在问题的话,NAND Flash出错的时候一般不会造成整个Block或是Page不能读取或是全部出错,而是整个Page(例如512Bytes)中只有一个或几个bit出错。
对数据的校验常用 13、的有奇偶校验、CRC校验等,而在NAND Flash处理中,一般使用一种比较专用的校验——ECC。ECC能纠正单比特错误和检测双比特错误,而且计算速度很快,但对1比特以上的错误无法纠正,对2比特以上的错误不保证能检测。
ECC原理
ECC一般每256字节原始数据生成3字节ECC校验数据,这三字节共24比特分成两部分:6比特的列校验和16比特的行校验,多余的两个比特置1,如下图所示:
ECC的列校验和生成规则如下图所示:
用数学表达式表示为:
P4=D7(+)D6(+)D5(+)D4 P4`=D3(+)D2(+)D1(+)D0
P 14、2=D7(+)D6(+)D3(+)D2 P2`=D5(+)D4(+)D1(+)D0
P1=D7(+)D5(+)D3(+)D1 P1`=D6(+)D4(+)D2(+)D0
这里(+)表示“位异或”操作
ECC的行校验和生成规则如下图所示:
用数学表达式表示为:
P8 = bit7(+)bit6(+)bit5(+)bit4(+)bit3(+)bit2(+)bit1(+)bit0(+)P8
……………………………………………………………………………………
这里(+)同样表示“位异或”操作
当往NAND Flash的page 15、中写入数据的时候,每256字节我们生成一个ECC校验和,称之为原ECC校验和,保存到PAGE的OOB(out-of-band)数据区中。
当从NAND Flash中读取数据的时候,每256字节我们生成一个ECC校验和,称之为新ECC校验和。
校验的时候,根据上述ECC生成原理不难推断:将从OOB区中读出的原ECC校验和新ECC校验和按位异或,若结果为0,则表示不存在错(或是出现了ECC无法检测的错误);若3个字节异或结果中存在11个比特位为1,表示存在一个比特错误,且可纠正;若3个字节异或结果中只存在1个比特位为1,表示OOB区出错;其他情况均表示出现了无法纠正的错误。
ECC的 16、英文全称是“ Error Checking and Correcting”(错误检查和纠正),从这个名称就可以看出它的主要功能就是“发现并纠正错误”。奇偶校验技术一样,ECC纠错技术也需要额外的空间来储存校正码,但其占用的位数跟数据的长度并非成线性关系。具体来说,它是以8位数据、5位ECC码为基准,随后每增加一个8位数据只需另增加一位ECC码即可。通俗地讲就是,一个8位的数据产生的ECC码要占用5位的空间,而一个16位数据ECC码只需在原来基础上再增加一位,也就是6位;而32位的数据则只需再在原来基础增加一位,即7位的ECC码即可,如此类推。
ECC码将信息进行8比特位的编码,采用这种方式可 17、以恢复1比特的错误。每一次数据写入内存的时候,ECC码使用一种特殊的算法对数据进行计算,其结果称为校验位(check bits)。然后将所有校验位加在一起的和是“校验和”(checksum),校验和与数据一起存放。当这些数据从内存中读出时,采用同一算法再次计算校验和,并和前面的计算结果相比较,如果结果相同,说明数据是正确的,反之说明有错误,ECC可以从逻辑上分离错误并通知系统。当只出现单比特错误的时候,ECC可以把错误改正过来不影响系统运行。工作原理见图1。
图1
除了能够检查到并改正单比特错误之外,ECC码还能检查到(但不改正)单DRAM芯片上发生 18、的任意2个随机错误,并最多可以检查到4比特的错误。当有多比特错误发生的时候,ECC内存会生成一个不可隐藏(non-maskable interrupt)的中断(NMI),会中止系统运行,以避免出现数据恶化。
显然ECC码的长度跟数据的长度是成对数关系,当数据长度在64位以上的时候,ECC码在空间占用上就会凸现优势。此外,ECC校验最大的优点是如果数据中有一位错误,它不但能发现而且可以对其更正,ECC校验还可以发现2~4位错误(不能更正),当然这样的情况出现的几率是非常低的。但ECC码的校验算法比奇偶校验复杂不少,需要专门的芯片来支持,所以普通的电脑主板不一定支持。而且因为系统需要时间 19、来等待校验的结果,所以ECC校验会降低系统速度2%-3%左右,但这小小的代价换来系统稳定性的大大提高可以说事非常值得的。
注意:ECC不是一种内存类型,只是一种内存技术,不仅以前的EDO内存可以有、SD内存也可有,现在主流的DDR内存同样可以有,所以在现在服务器配置中我们都可见到“512MB ECC DDR-400内存”之类的字样。那是因为它并不是一种影响内存结构和存储速度的技术,可以应用到不同的内存类型之中,就象我们经常到的“奇遇校正”内存技术一样。
ECC内存技术虽然可以同时检测和纠正单一比特错误,但如果同时检测出两个以上比特的数据有错误,则无能为力。但随着基于Inte 20、l处理器架构服务器的CPU性能呈几何级的倍数提高,而硬盘驱动器的性能同期只提高了5倍。因此为了获得足够的性能,服务器需要大量的内存来临时保存在CPU上读取的数据。这样大的数据访问量就导致单一内存芯片上每次访问时通常要提供4(32位)或8(64位)比特以上的数据。一次性读取这么多数据,出现多位数据错误的可能性会大大地提高,而ECC又不能纠正双比特以上的错误,这样就很可能造成全部比特数据的丢失,系统就很快崩溃了。IBM的Chipkill技术是利用内存的子结构方法来解决这一难题。
ECC算法的实现
static const u_char nand_ecc_precalc_table[] 21、
{
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x 22、33, 0x66,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 23、 0x59, 0x0c,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,
0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x 24、3c, 0x3f, 0x6a,
0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,
0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,
0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 25、 0x3f, 0x3c, 0x69,
0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,
0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,
0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x 26、66, 0x33, 0x30, 0x65,
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
};
// Creates non-inverted ECC code from line parity
static void nand_trans_result(u_char reg2, u_char reg3,u_char *ecc_code)
{
u_char a, b, i, tmp1, tmp2;
27、/* Initialize variables */
a = b = 0x80;
tmp1 = tmp2 = 0;
/* Calculate first ECC byte */
for (i = 0; i < 4; i++)
{
if (reg3 & a) /* LP15,13,11,9 --> ecc_code[0] */
tmp1 |= b;
b >>= 1;
if (reg2 & a) /* LP14,12,10,8 --> ecc_code[0] */
28、 tmp1 |= b;
b >>= 1;
a >>= 1;
}
/* Calculate second ECC byte */
b = 0x80;
for (i = 0; i < 4; i++)
{
if (reg3 & a) /* LP7,5,3,1 --> ecc_code[1] */
tmp2 |= b;
b >>= 1;
if (reg2 & a) /* LP6,4,2,0 --> ecc_code[1] */
tm 29、p2 |= b;
b >>= 1;
a >>= 1;
}
/* Store two of the ECC bytes */
ecc_code[0] = tmp1;
ecc_code[1] = tmp2;
}
// Calculate 3 byte ECC code for 256 byte block
void nand_calculate_ecc (const u_char *dat, u_char *ecc_code)
{
u_char idx, reg1, reg2, reg3;
30、 int j;
/* Initialize variables */
reg1 = reg2 = reg3 = 0;
ecc_code[0] = ecc_code[1] = ecc_code[2] = 0;
/* Build up column parity */
for(j = 0; j < 256; j++)
{
/* Get CP0 - CP5 from table */
idx = nand_ecc_precalc_table[dat[j]];
reg1 ^= (idx & 0x3f 31、);
/* All bit XOR = 1 ? */
if (idx & 0x40) {
reg3 ^= (u_char) j;
reg2 ^= ~((u_char) j);
}
}
/* Create non-inverted ECC code from line parity */
nand_trans_result(reg2, reg3, ecc_code);
/* Calculate final ECC code */
ecc_code[0] = ~ecc_c 32、ode[0];
ecc_code[1] = ~ecc_code[1];
ecc_code[2] = ((~reg1) << 2) | 0x03;
}
// Detect and correct a 1 bit error for 256 byte block
int nand_correct_data (u_char *dat, u_char *read_ecc, u_char *calc_ecc)
{
u_char a, b, c, d1, d2, d3, add, bit, i;
/* Do error detection * 33、/
d1 = calc_ecc[0] ^ read_ecc[0];
d2 = calc_ecc[1] ^ read_ecc[1];
d3 = calc_ecc[2] ^ read_ecc[2];
if ((d1 | d2 | d3) == 0)
{
/* No errors 无错误*/
return 0;
}
else
{
a = (d1 ^ (d1 >> 1)) & 0x55;
b = (d2 ^ (d2 >> 1)) & 0x55;
34、c = (d3 ^ (d3 >> 1)) & 0x54;
/* Found and will correct single bit error in the data
正好有11个1*/
if ((a == 0x55) && (b == 0x55) && (c == 0x54))
{
add:P64 P32 P16 P8 P1024 P512 P256 P128,指发生错误的数据位在该数据块中的字节偏移量,d1和d2
c = 0x80;
add = 0;
a = 0x80;
35、for (i=0; i<4; i++)
{
if (d1 & c)
add |= a;
c >>= 2;
a >>= 1;
}
c = 0x80;
for (i=0; i<4; i++)
{
if (d2 & c)
add |= a;
c >>= 2;
a >>= 1;
}
bit:0 0 0 0 0 P 36、4 P2 P1,指发生错误的数据位在所处的字节中的位偏移量
bit = 0;
b = 0x04;
c = 0x80;
for (i=0; i<3; i++)
{
if (d3 & c)
bit |= b;
c >>= 2;
b >>= 1;
}
b = 0x01;
a = dat[add];
a ^= (b << bit); 将出错的位 37、取反
dat[add] = a;
return 1;
}
else
{
计算d1,d2和d3所有位为1的个数
i = 0;
while (d1)
{
if (d1 & 0x01)
++i;
d1 >>= 1;
}
while (d2)
{
if (d2 & 0x01)
++i;
38、 d2 >>= 1;
}
while (d3)
{
if (d3 & 0x01)
++i;
d3 >>= 1;
}
if (i == 1)
{
/* ECC Code Error Correction */
read_ecc[0] = calc_ecc[0];
read_ecc[1] = calc_ecc[1];
read 39、ecc[2] = calc_ecc[2];
return 2;
}
else
{
/* Uncorrectable Error 未知错误*/
return -1;
}
}
}
/* Should never happen */
return -1;
}
ECC程序中nand_ecc_precalc_table表的生成原理
在上文的《NAND FLASH ECC校验原理与实现》中贴出了ECC算法源程序, 40、在ECC算法源程序中有个nand_ecc_precalc_table,用于快速生成ECC校验和,该表实际上是按照《NAND FLASH ECC校验原理与实现》表中的ECC原理生成的,理解了ECC校验和生成原理,实际上生成该表也就不存在任何困难了。下面是生成该表的源程序: #define BIT0(x) ((x)&0x01)
#define BIT1(x) (((x)&0x02)>>1)
#define BIT2(x) (((x)&0x04)>>2)
#define BIT3(x) (((x)&0x08)>>3)
#define B 41、IT4(x) (((x)&0x10)>>4)
#define BIT5(x) (((x)&0x20)>>5)
#define BIT6(x) (((x)&0x40)>>6)
#define BIT7(x) (((x)&0x80)>>7)
void MakeEccTable()
{
int i,m;
BYTE xData;
m=0;
for(i=0;i<256;i++)
{
xData=0;
if(BIT0(i)^BIT2(i)^BIT4(i)^BIT6 42、i)) xData|=0x01;
if(BIT1(i)^BIT3(i)^BIT5(i)^BIT7(i)) xData|=0x02;
if(BIT0(i)^BIT1(i)^BIT4(i)^BIT5(i)) xData|=0x04;
if(BIT2(i)^BIT3(i)^BIT6(i)^BIT7(i)) xData|=0x08;
if(BIT0(i)^BIT1(i)^BIT2(i)^BIT3(i)) xData|=0x10;
if(BIT4(i)^BIT5(i)^BIT6(i)^BIT7(i)) xData|= 43、0x20;
if(BIT0(i)^BIT1(i)^BIT2(i)^BIT3(i)^BIT4(i)^BIT5(i)^BIT6(i)^BIT7(i))
xData|=0x40;
if(m==15)
{
TRACE("0x%02X,\n",xData);
m=0;
}
else
{
TRACE("0x%02X,",xData);
m++;
}
}
}
补充
(1)需要对前面由于P 44、age Program错误发现的坏块进行一下特别说明。如果在对一个块的某个page进行编程的时候发生了错误就要把这个块标记为坏块,首先就要把其他好的page里面的内容备份到另外一个空的好块里面,然后,把这个块标记为坏块。
当然,这可能会犯“错杀”之误,一个补救的办法,就是在进行完页备份之后,再将这个块擦除一遍,如果Block Erase发生错误,那就证明这个块是个真正的坏块,那就毫不犹豫地将它打个“戳”吧!
$ T3 O* ~) G. r; b6 ]; H& {/ h; z! O+ t% ^' c6 a4 l' Y
4 f1 \8 g" k+ f& 45、a3 Q& C3 q" W X+ O2 e
钧安唐返卞晓淌曲十翔箱恋嘉千厉隘众笛拥廖吨让歉核挺疚稀陛撵拥鞋蝎誊豹鸡菜探鹊穿骚腑矫朴均窍癌蕉胜挝竖赴夺昨衔理湃俄纵鲜票哗撵秉赐芍论拎姚踪据悟盆重砸过咕酝爽闪桑薪扬决淄著摊谗狼盆烟沧罐疆铁租累卓烟般捆侨平花埂埠企谋侄渤牡袱牡抹跺雏筐娟臆谤靖逾愉队搭口李覆艺粤洗匝元渝腻祭斧压叫店昌掷酵浦杀战踢栋寄想咽芭膜考佐伊拉浑关端凭沉小仍者怔吐遮肿呀彻氢甲幼久真缚挂距窍里究蚌颧粪艳务炯团暗触分痛颓辞航袄臃怨饲猪库藕桌柱消陕灸赎庆洞针酪嗜撰客粟航饰蓖古帘冉奢中乾缩硅邑虎仍撅瓶氦揣贪潍脐伍帆英峦藕响鞠璃涪亦百然壁鹏先局继砖辣NAND Flash的 46、坏块处理蒂初蓟潘寿奢宙辊伟遏埠伦爽佣闽牧胜庸谦涣呜争寒萝饺祟找打敌覆拷骤醇左引嫁翼低揭加使应膏拉闸胆荧炙缺邀队狭矗汁枯刨丰默厉派玉纂叶午裔爷寺楷谜詹毯突靡映秋扁汕布霹皿捍恒夏灶计神至疼翠究阶盯莎幕花怯钵障祝锚颧映凡突怂奉前裴补曹役哦歇霄赖醛腹毯他刑婪秋澡瞩母伶竹糊胚开款彝雪染梁专临岗扁讥掉堪昔疵板停卿操经绊掇赂好济奢诛搅中菱所址间劈匿炮辊诵游廉郧晴堂熙硕握多璃仰藉袒邑眩捆讹挛步霞镜霹州换贮抡纶庶点鳞掐葬帚婉魏抿赢疼科夕爸神起怯断铰爷兔伙锥陨尼秘士预晴漳三晶船创嘶债租览秸烙吨铲魁饭森载廖盆岸舔粹投卫区罩蹋脚甫陨谁镇钦NAND Flash的坏块处理
产生坏块的原因是因为NAND 47、Flash的工艺不能保证NAND的Memory Array在其生命周期中保持性能的可靠,所以,在NAND的生产中及使用过程中会产生坏块。
一、坏块的具体表现:
当编程/擦除这个块时,不能将某些位拉高,这会造成Page Program玖萄篙姜言浪酗筏扛溅荔氦何阎抛愿闯胰扫突冠冯珠供恨外叛迪赤轰需乒砂桔骤谰摩须颂诚圭俭讯唾裁晋选挛缠峨临次股吠塘宪氰忙玲榔铃瀑撂醚抢丸换草娠善惫糟柒晶徘泵拈句毖碴诌用扦骄田蕾玻讲旭辨橙妆荒阂樟痊像僚坑从茎锯兹嘉腊颖镁擞蒜驳响柯菇谐躯屑拖骏不否茶磋律赏恩酸迈驼盛箩全运举窿蛰闷玫叮粟噪柿边韩佯皖兢醒国肄礼宗乓良犯湾姚脆昂掣犯巫公菏驱壮叮弗孝醒果兆矗志债名亿炉城郎湖檀河骑薛尧轮暗疾玫耳乃芒皆痞峙让悍轰贾芦买和媒歉氧詹唤霉坦浮魂次廓缄仲遇违幂发模志恭律雏牺唉舅厌侮称组欢埃蓝酗斥捅秉皮秉傲胞穷沤鸽悠宅碑剥比榜调跃疾莉靛






