ChinaUnix首页 > 精华文章 > Linux > 正文

[原创] [原创]Nand ECC校验和纠错原理及2.6.27内核ECC代码分析


http://www.chinaunix.net 作者:wwxbei  发表于:2009-07-27 10:09:06
发表评论】 【查看原文】 【Linux讨论区】【关闭

ECC的全称是Error Checking and Correction,是一种用于[font=Times New Roman]Nand[/font][font=宋体]的差错检测和修正算法。[/font]如果操作时序和电路稳定性不存在问题的话,[font=Times New Roman]NAND Flash[/font][font=宋体]出错的时候一般不会造成整个[/font][font=Times New Roman]Block[/font][font=宋体]或是[/font][font=Times New Roman]Page[/font][font=宋体]不能读取或是全部出错,而是整个[/font][font=Times New Roman]Page[/font][font=宋体](例如[/font][font=Times New Roman]512Bytes[/font][font=宋体])中只有一个或几个[/font][font=Times New Roman]bit[/font][font=宋体]出错。[/font][font=Times New Roman]ECC[/font][font=宋体]能纠正[/font]1[font=宋体]个[/font]比特错误和检测2[font=宋体]个[/font]比特错误,而且计算速度很快,但对[font=Times New Roman]1[/font][font=宋体]比特以上的错误无法纠正,对[/font][font=Times New Roman]2[/font][font=宋体]比特以上的错误不保证能检测。[/font]
校验码生成算法:ECC[font=宋体]校验每次对[/font][font=Times New Roman]256[/font][font=宋体]字节的数据进行操作,包含列校验和行校验。对每个待校验的[/font][font=Times New Roman]Bit[/font][font=宋体]位求异或,若结果为[/font][font=Times New Roman]0[/font][font=宋体],则表明含有偶数个[/font][font=Times New Roman]1[/font][font=宋体];若结果为[/font][font=Times New Roman]1[/font][font=宋体],则表明含有奇数个[/font][font=Times New Roman]1[/font][font=宋体]。列校验规则如表[/font][font=Times New Roman]1[/font][font=宋体]所示。[/font][font=Times New Roman]256[/font][font=宋体]字节数据形成[/font][font=Times New Roman]256[/font][font=宋体]行、[/font][font=Times New Roman]8[/font][font=宋体]列的矩阵,矩阵每个元素表示一个[/font][font=Times New Roman]Bit[/font][font=宋体]位。[/font]

其中CP0 ~ CP5 [font=宋体]为六个[/font][font=Times New Roman]Bit[/font][font=宋体]位,表示[/font][font=Times New Roman]Column Parity[/font][font=宋体](列极性),[/font]
CP0[font=宋体]为第[/font][font=Times New Roman]0[/font][font=宋体]、[/font][font=Times New Roman]2[/font][font=宋体]、[/font][font=Times New Roman]4[/font][font=宋体]、[/font][font=Times New Roman]6[/font][font=宋体]列的极性,[/font][font=Times New Roman]CP1[/font][font=宋体]为第[/font][font=Times New Roman]1[/font][font=宋体]、[/font][font=Times New Roman]3[/font][font=宋体]、[/font][font=Times New Roman]5[/font][font=宋体]、[/font][font=Times New Roman]7[/font][font=宋体]列的极性,[/font]
CP2[font=宋体]为第[/font]0、[font=Times New Roman]1[/font][font=宋体]、[/font][font=Times New Roman]4[/font][font=宋体]、[/font][font=Times New Roman]5[/font][font=宋体]列的极性,[/font][font=Times New Roman]CP3[/font][font=宋体]为第[/font]2、[font=Times New Roman]3[/font][font=宋体]、[/font][font=Times New Roman]6[/font][font=宋体]、[/font][font=Times New Roman]7[/font][font=宋体]列的极性,[/font]
CP4[font=宋体]为第[/font][font=Times New Roman]0[/font][font=宋体]、[/font][font=Times New Roman]1[/font][font=宋体]、[/font][font=Times New Roman]2[/font][font=宋体]、[/font][font=Times New Roman]3[/font][font=宋体]列的极性,[/font][font=Times New Roman]CP5[/font][font=宋体]为第[/font][font=Times New Roman]4[/font][font=宋体]、[/font][font=Times New Roman]5[/font][font=宋体]、[/font][font=Times New Roman]6[/font][font=宋体]、[/font][font=Times New Roman]7[/font][font=宋体]列的极性。[/font]
用公式表示就是:[font=Times New Roman]CP0=[/font]Bit0^Bit2^Bit4^Bit6, 表示第[font=Times New Roman]0[/font][font=宋体]列内部[/font][font=Times New Roman]256[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]位异或之后再跟第[/font][font=Times New Roman]2[/font][font=宋体]列[/font][font=Times New Roman]256[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]位异或,再跟第[/font][font=Times New Roman]4[/font][font=宋体]列、第[/font][font=Times New Roman]6[/font][font=宋体]列的每个[/font][font=Times New Roman]Bit[/font][font=宋体]位异或,这样,[/font][font=Times New Roman]CP0[/font][font=宋体]其实是[/font][font=Times New Roman]256*4=1024[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]位异或的结果。[/font][font=Times New Roman]CP1 ~ CP5 [/font][font=宋体]依此类推。[/font]
行校验如下图所示



其中RP0 ~ RP15 [font=宋体]为十六个[/font][font=Times New Roman]Bit[/font][font=宋体]位,表示[/font][font=Times New Roman]Row Parity[/font][font=宋体](行极性),[/font]
RP0[font=宋体]为第[/font][font=Times New Roman]0[/font][font=宋体]、[/font][font=Times New Roman]2[/font][font=宋体]、[/font][font=Times New Roman]4[/font][font=宋体]、[/font][font=Times New Roman]6[/font][font=宋体]、[/font]….252、[font=Times New Roman]254 [/font][font=宋体]个字节的极性[/font]
RP1-----1、[font=Times New Roman]3[/font][font=宋体]、[/font][font=Times New Roman]5[/font][font=宋体]、[/font][font=Times New Roman]7[/font]……253、[font=Times New Roman]255 [/font]
RP2----0[font=宋体]、[/font][font=Times New Roman]1[/font][font=宋体]、[/font][font=Times New Roman]4[/font][font=宋体]、[/font][font=Times New Roman]5[/font][font=宋体]、[/font][font=Times New Roman]8[/font][font=宋体]、[/font][font=Times New Roman]9[/font]…..252、[font=Times New Roman]253 [/font][font=宋体](处理[/font][font=Times New Roman]2[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],跳过[/font][font=Times New Roman]2[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体])[/font]
RP3---- 2[font=宋体]、[/font][font=Times New Roman]3[/font][font=宋体]、[/font][font=Times New Roman]6[/font][font=宋体]、[/font][font=Times New Roman]7[/font][font=宋体]、[/font][font=Times New Roman]10[/font][font=宋体]、[/font][font=Times New Roman]11[/font]…..254[font=宋体]、[/font][font=Times New Roman]255 [/font][font=宋体](跳过[/font][font=Times New Roman]2[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],处理[/font][font=Times New Roman]2[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体])[/font]
RP4---- 处理[font=Times New Roman]4[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],跳过[/font][font=Times New Roman]4[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体];[/font]
RP5---- [font=宋体]跳过[/font][font=Times New Roman]4[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],处理[/font][font=Times New Roman]4[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体];[/font]
RP6---- 处理[font=Times New Roman]8[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],跳过[/font][font=Times New Roman]8[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font]
RP7---- [font=宋体]跳过[/font][font=Times New Roman]8[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],处理[/font][font=Times New Roman]8[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体];[/font]
RP8---- 处理[font=Times New Roman]16[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],跳过[/font][font=Times New Roman]16[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font]
RP9---- [font=宋体]跳过[/font][font=Times New Roman]16[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],处理[/font][font=Times New Roman]16[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体];[/font]
RP10----处理[font=Times New Roman]32[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],跳过[/font][font=Times New Roman]32[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font]
RP11----[font=宋体]跳过[/font][font=Times New Roman]32[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],处理[/font][font=Times New Roman]32[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体];[/font]
RP12----处理[font=Times New Roman]64[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],跳过[/font][font=Times New Roman]64[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font]
RP13----[font=宋体]跳过[/font][font=Times New Roman]64[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],处理[/font][font=Times New Roman]64[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体];[/font]
RP14----处理[font=Times New Roman]128[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],跳过[/font][font=Times New Roman]128[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font]
RP15----[font=宋体]跳过[/font][font=Times New Roman]128[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体],处理[/font][font=Times New Roman]128[/font][font=宋体]个[/font][font=Times New Roman]Byte[/font][font=宋体];[/font]
可见,RP0 ~ RP15 每个[font=Times New Roman]Bit[/font][font=宋体]位都是[/font][font=Times New Roman]128[/font][font=宋体]个字节(也就是[/font][font=Times New Roman]128[/font][font=宋体]行)即[/font][font=Times New Roman]128*8=1024[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]位求异或的结果。[/font]
综上所述,对[font=Times New Roman]256[/font][font=宋体]字节的数据共生成了[/font][font=Times New Roman]6[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]的列校验结果,[/font][font=Times New Roman]16[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]的行校验结果,共[/font][font=Times New Roman]22[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]。在[/font][font=Times New Roman]Nand[/font][font=宋体]中使用[/font][font=Times New Roman]3[/font][font=宋体]个字节存放校验结果,多余的两个[/font][font=Times New Roman]Bit[/font][font=宋体]位置[/font][font=Times New Roman]1[/font][font=宋体]。存放次序如下表所示:[/font]



以[font=Times New Roman]K9F1208[/font][font=宋体]为例,每个[/font][font=Times New Roman]Page[/font][font=宋体]页包含[/font][font=Times New Roman]512[/font][font=宋体]字节的数据区和[/font][font=Times New Roman]16[/font][font=宋体]字节的[/font][font=Times New Roman]OOB[/font][font=宋体]区。前[/font][font=Times New Roman]256[/font][font=宋体]字节数据生成[/font][font=Times New Roman]3[/font][font=宋体]字节[/font][font=Times New Roman]ECC[/font][font=宋体]校验码,后[/font][font=Times New Roman]256[/font][font=宋体]字节数据生成[/font][font=Times New Roman]3[/font][font=宋体]字节[/font][font=Times New Roman]ECC[/font][font=宋体]校验码,共[/font][font=Times New Roman]6[/font][font=宋体]字节[/font][font=Times New Roman]ECC[/font][font=宋体]校验码存放在[/font][font=Times New Roman]OOB[/font][font=宋体]区中,存放的位置为[/font][font=Times New Roman]OOB[/font][font=宋体]区的第[/font][font=Times New Roman]0[/font][font=宋体]、[/font][font=Times New Roman]1[/font][font=宋体]、[/font][font=Times New Roman]2[/font][font=宋体]和[/font][font=Times New Roman]3[/font][font=宋体]、[/font][font=Times New Roman]6[/font][font=宋体]、[/font][font=Times New Roman]7[/font][font=宋体]字节。[/font]

MakeEccTable.rar



 wwxbei 回复于:2009-06-06 23:08:06

[size=14pt]校验码生成算法的[font=Times New Roman]C[/font][font=仿宋_GB2312]语言实现[/font][/size][size=14pt][/size]
 
[size=10.5pt]在[/size][size=10.5pt]Linux[/size][size=10.5pt]内核中[font=Times New Roman]ECC[/font][font=宋体]校验算法所在的文件为[/font][/size][size=10.5pt]drivers/mtd/nand/nand_ecc.c[/size][size=10.5pt],其实现有新、旧两种,在[/size][size=10.5pt]2.6.27[/size][size=10.5pt]及更早的内核中使用的程序,从[font=Times New Roman]2.6.28[/font][font=宋体]开始已经不再使用,而换成了效率更高的程序。可以在[/font][/size][size=10.5pt]Documentation/mtd/nand_ecc.txt[/size][size=10.5pt] 文件中找到对新程序的详细介绍。[/size][size=10.5pt][/size]

 
[size=10.5pt]首先分析一下[font=Times New Roman]2.6.27[/font][font=宋体]内核中的[/font][font=Times New Roman]ECC[/font][font=宋体]实现,源代码见[/font][font=Times New Roman]:[/font][/size][size=10.5pt][/size]
[size=10.5pt]http://lxr.linux.no/linux+v2.6.27/drivers/mtd/nand/nand_ecc.c[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L43][size=10.5pt]43[/size][size=10.5pt]/*[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L44][size=10.5pt]44[/size][size=10.5pt] * Pre-calculated 256-way 1 byte column parity[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L45][size=10.5pt]45[/size][size=10.5pt] */[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L46][size=10.5pt]46[/size][size=10.5pt]static const [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=u_char][size=10.5pt]u_char[/size]
[url=http://lxr.linux.no/linux+v2.6.27/+code=nand_ecc_precalc_table][size=10.5pt]nand_ecc_precalc_table[/size][size=10.5pt][] = {[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L47][size=10.5pt]47[/size][size=10.5pt]   0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L48][size=10.5pt]48[/size][size=10.5pt]   0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L49][size=10.5pt]49[/size][size=10.5pt]   0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L50][size=10.5pt]50[/size][size=10.5pt]   0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L51][size=10.5pt]51[/size][size=10.5pt]   0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L52][size=10.5pt]52[/size][size=10.5pt]   0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L53][size=10.5pt]53[/size][size=10.5pt]   0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L54][size=10.5pt]54[/size][size=10.5pt]   0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L55][size=10.5pt]55[/size][size=10.5pt]   0x6a, 0x3f, 0x3c, 0x69, 0x33, 0x66, 0x65, 0x30, 0x30, 0x65, 0x66, 0x33, 0x69, 0x3c, 0x3f, 0x6a,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L56][size=10.5pt]56[/size][size=10.5pt]   0x0f, 0x5a, 0x59, 0x0c, 0x56, 0x03, 0x00, 0x55, 0x55, 0x00, 0x03, 0x56, 0x0c, 0x59, 0x5a, 0x0f,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L57][size=10.5pt]57[/size][size=10.5pt]   0x0c, 0x59, 0x5a, 0x0f, 0x55, 0x00, 0x03, 0x56, 0x56, 0x03, 0x00, 0x55, 0x0f, 0x5a, 0x59, 0x0c,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L58][size=10.5pt]58[/size][size=10.5pt]   0x69, 0x3c, 0x3f, 0x6a, 0x30, 0x65, 0x66, 0x33, 0x33, 0x66, 0x65, 0x30, 0x6a, 0x3f, 0x3c, 0x69,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L59][size=10.5pt]59[/size][size=10.5pt]   0x03, 0x56, 0x55, 0x00, 0x5a, 0x0f, 0x0c, 0x59, 0x59, 0x0c, 0x0f, 0x5a, 0x00, 0x55, 0x56, 0x03,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L60][size=10.5pt]60[/size][size=10.5pt]   0x66, 0x33, 0x30, 0x65, 0x3f, 0x6a, 0x69, 0x3c, 0x3c, 0x69, 0x6a, 0x3f, 0x65, 0x30, 0x33, 0x66,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L61][size=10.5pt]61[/size][size=10.5pt]   0x65, 0x30, 0x33, 0x66, 0x3c, 0x69, 0x6a, 0x3f, 0x3f, 0x6a, 0x69, 0x3c, 0x66, 0x33, 0x30, 0x65,[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L62][size=10.5pt]62[/size]

[size=10.5pt]0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00[/size][size=10.5pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L63][size=10.5pt]63[/size][size=10.5pt]};[/size][size=10.5pt][/size]
[size=10.5pt][/size]

 
[size=10.5pt]为了加快计算速度,程序中使用了一个预先计算好的列极性表。这个表中每一个元素都是[/size][size=10.5pt]unsigned char[/size][size=10.5pt]类型,表示[font=Times New Roman]8[/font][font=宋体]位二进制数。[/font][/size][size=10.5pt][/size]
[size=10.5pt]表中[font=Times New Roman]8[/font][font=宋体]位二进制数每位的含义:[/font][/size][size=10.5pt][/size]


[size=10.5pt][/size]

 
[size=10.5pt]这个表的意思是:对[font=Times New Roman]0~255[/font][font=宋体]这[/font][font=Times New Roman]256[/font][font=宋体]个数,计算并存储每个数的列校验值和行校验值,以数作数组下标。比如 [/font][font=Times New Roman]nand_ecc_[/font][/size][size=10.5pt]precalc_table[ [/size][size=10.5pt]13[/size][size=10.5pt] ]  [/size][size=10.5pt]存储[font=Times New Roman]13[/font][font=宋体]的列校验值和行校验值,[/font][font=Times New Roman]13[/font][font=宋体]的二进制表示为 [/font][font=Times New Roman]00001101[/font][font=宋体], 其[/font][font=Times New Roman]CP0 = [/font][/size][size=10.5pt]Bit0^Bit2^Bit4^Bit6[/size][size=10.5pt] = 0[font=宋体];[/font][/size][size=10.5pt][/size]
[size=10.5pt]CP1 = Bit1^Bit3^Bit5^Bit7 = 1[font=宋体];[/font][/size][size=10.5pt][/size]
[size=10.5pt]CP2 = Bit0^Bit1^Bit4^Bit5 = 1;[/size][size=10.5pt][/size]
[size=10.5pt]CP3 = Bit2^Bit3^Bit6^Bit7 = 0;[/size][size=10.5pt][/size]
[size=10.5pt]CP4 = Bit0^Bit1^Bit2^Bit3 = 1;[/size][size=10.5pt][/size]
[size=10.5pt]CP5 = Bit4^Bit5^Bit6^Bit7 = 0;[/size][size=10.5pt][/size]
[size=10.5pt]其行极性[font=Times New Roman]RP = Bit[/font][/size][size=10.5pt]0^Bit1[/size][size=10.5pt]^[/size][size=10.5pt]Bit2^[/size][size=10.5pt]Bit3^[/size][size=10.5pt]Bit4^[/size][size=10.5pt]Bit5^[/size][size=10.5pt]Bit6^[/size][size=10.5pt]Bit7 = [/size][size=10.5pt]1[/size][size=10.5pt];[/size][size=10.5pt][/size]
[size=10.5pt]则[font=Times New Roman]nand_ecc_[/font][/size][size=10.5pt]precalc_table[ [/size][size=10.5pt]13[/size][size=10.5pt] ] [/size][size=10.5pt]处存储的值应该是[/size][size=10.5pt] 0101 0110[/size][size=10.5pt],即[font=Times New Roman]0x[/font][/size][size=10.5pt]56.[/size][size=10.5pt][/size]
[size=10.5pt]注意,数组[font=Times New Roman]nand_ecc_[/font][/size][size=10.5pt]precalc_table[/size][size=10.5pt]的下标其实是我们要校验的一个字节数据。[/size][size=10.5pt][/size]
[size=10.5pt]理解了这个表的含义,也就很容易写个程序生成这个表了。程序见附件中的[/size][size=10.5pt] MakeEccTable.c[/size][size=10.5pt]文件。[/size]

[size=10.5pt][/size] 
[size=10.5pt][/size]
[size=10.5pt]有了这个表,对单字节数据[font=Times New Roman]dat[/font][font=宋体],可以直接查表[/font][/size][size=10.5pt] nand_ecc_precalc_table[ dat ] [/size][size=10.5pt]得到 [font=Times New Roman]dat[/font][font=宋体]的行校验值和列校验值。 但是[/font][font=Times New Roman]ECC[/font][font=宋体]实际要校验的是[/font][font=Times New Roman]256[/font][font=宋体]字节的数据,需要进行[/font][font=Times New Roman]256[/font][font=宋体]次查表,对得到的[/font][font=Times New Roman]256[/font][font=宋体]个查表结果进行按位异或,最终结果的[/font][/size][size=10.5pt] Bit0 ~ Bit5 [/size][size=10.5pt]即是[/size][size=10.5pt]256[/size][size=10.5pt]字节数据的 [font=Times New Roman]CP0 ~ CP5.[/font][/size][size=10.5pt][/size]
[size=10pt]/* Build up column parity */[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L81][size=10pt]  81[/size][size=12pt]        for([/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt] = 0; [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt] < 256; [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt]++) {[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L82][size=10pt]  82[/size]
[size=10pt]/* Get CP0 - CP5 from table */[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L83][size=10pt]  83[/size]
[url=http://lxr.linux.no/linux+v2.6.27/+code=idx][size=10pt]idx[/size][size=12pt] = [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=nand_ecc_precalc_table][size=10pt]nand_ecc_precalc_table[/size][size=12pt][*[/size][url=http://lxr.linux.no/linux+v2.6.27/+code=dat][size=10pt]dat[/size][size=12pt]++];[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L84][size=10pt]  84[/size]
[url=http://lxr.linux.no/linux+v2.6.27/+code=reg1][size=10pt]reg1[/size][size=12pt] ^= ([/size][url=http://lxr.linux.no/linux+v2.6.27/+code=idx][size=10pt]idx[/size][size=12pt] & 0x3f);[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L85][size=10pt]  85[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L86][size=10pt]  86[/size][size=12pt]            //[/size][size=12pt]这里省略了一些,后面会介绍[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L91][size=10pt]  91[/size][size=12pt]        }[/size][size=12pt][/size]
[size=10.5pt][/size]


[size=10.5pt]R[/size][size=10.5pt]eg1[/size][size=10.5pt][/size]


[size=10.5pt][/size]

 
[size=10.5pt]在这里,计算列极性的过程其实是先在一个字节数据的内部计算[/size][size=10.5pt]CP0 ~ CP5, [/size][size=10.5pt]每个字节都计算完后再与其它字节的计算结果求异或。而表[font=Times New Roman]1[/font][font=宋体]中是先对一列[/font][font=Times New Roman]Bit[/font][/size][size=10.5pt]0[/size][size=10.5pt]求异或,再去异或一列[/size][size=10.5pt]Bit2[/size][size=10.5pt]。 这两种只是计算顺序不同,结果是一致的。 因为异或运算的顺序是可交换的。[/size][size=10.5pt][/size]
[size=10.5pt][/size]

 
[size=10.5pt]行极性的计算要复杂一些。[/size][size=10.5pt][/size]
[size=10.5pt]nand_ecc_[/size][size=10.5pt]precalc_table[] [/size][size=10.5pt]表中的 [font=Times New Roman]Bit6 [/font][font=宋体]已经保存了每个单字节数的行极性值。对于待校验的[/font][font=Times New Roman]256[/font][font=宋体]字节数据,分别查表,如果其行极性为[/font][font=Times New Roman]1[/font][font=宋体],则记录该数据所在的行索引(也就是[/font][font=Times New Roman]for[/font][font=宋体]循环的[/font][font=Times New Roman]i[/font][font=宋体]值),这里的行索引是很重要的,因为[/font][font=Times New Roman]RP[/font][/size][size=10.5pt]0 ~ RP15 [/size][size=10.5pt]的计算都是跟行索引紧密相关的,如[font=Times New Roman]RP0[/font][font=宋体]只计算偶数行,[/font][font=Times New Roman]RP1[/font][font=宋体]只计算奇数行,等等。[/font][/size][size=10.5pt][/size]

[size=10pt]/* Build up column parity */[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L81][size=10pt]  81[/size][size=12pt]        for([/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt] = 0; [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt] < 256; [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt]++) {[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L82][size=10pt]  82[/size]
[size=10pt]/* Get CP0 - CP5 from table */[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L83][size=10pt]  83[/size]
[url=http://lxr.linux.no/linux+v2.6.27/+code=idx][size=10pt]idx[/size][size=12pt] = [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=nand_ecc_precalc_table][size=10pt]nand_ecc_precalc_table[/size][size=12pt][*[/size][url=http://lxr.linux.no/linux+v2.6.27/+code=dat][size=10pt]dat[/size][size=12pt]++];[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L84][size=10pt]  84[/size]
[url=http://lxr.linux.no/linux+v2.6.27/+code=reg1][size=10pt]reg1[/size][size=12pt] ^= ([/size][url=http://lxr.linux.no/linux+v2.6.27/+code=idx][size=10pt]idx[/size][size=12pt] & 0x3f);[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L85][size=10pt]  85[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L86][size=10pt]  86[/size]
[size=10pt]/* All bit XOR = 1 ? */[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L87][size=10pt]  87[/size][size=12pt]                if ([/size][url=http://lxr.linux.no/linux+v2.6.27/+code=idx][size=10pt]idx[/size][size=12pt] & 0x40) {[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L88][size=10pt]  88[/size]
[url=http://lxr.linux.no/linux+v2.6.27/+code=reg3][size=10pt]reg3[/size][size=12pt] ^= ([/size][url=http://lxr.linux.no/linux+v2.6.27/+code=uint8_t][size=10pt]uint8_t[/size][size=12pt]) [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt];[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L89][size=10pt]  89[/size]
[url=http://lxr.linux.no/linux+v2.6.27/+code=reg2][size=10pt]reg2[/size][size=12pt] ^= ~(([/size][url=http://lxr.linux.no/linux+v2.6.27/+code=uint8_t][size=10pt]uint8_t[/size][size=12pt]) [/size][url=http://lxr.linux.no/linux+v2.6.27/+code=i][size=10pt]i[/size][size=12pt]);[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L90][size=10pt]  90[/size][size=12pt]                }[/size][size=12pt][/size]
[url=http://control.cublog.cn/article_change.php?id=1957543#L91][size=10pt]  91[/size][size=12pt]        }[/size][size=12pt][/size]

 
[size=10.5pt]这里的关键是理解第[font=Times New Roman]88[/font][font=宋体]和[/font][font=Times New Roman]89[/font][font=宋体]行。[/font][/size][size=10.5pt]Reg3[/size][size=10.5pt]和[/size][size=10.5pt]reg2[/size][size=10.5pt]都是[/size][size=10.5pt]unsigned char [/size][size=10.5pt]型的变量,并都初始化为零。[/size][size=10.5pt][/size]
[size=10.5pt]行索引(也就是[font=Times New Roman]for[/font][font=宋体]循环里的[/font][font=Times New Roman]i[/font][font=宋体])的取值范围为[/font][font=Times New Roman]0~255[/font][font=宋体],根据表[/font][font=Times New Roman]2[/font][font=宋体]可以得出以下规律:[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]RP0[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit0[/size][size=10.5pt]为[font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP1[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit0[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]
[size=10.5pt]RP2[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit[/size][size=10.5pt]1[font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP3[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit1[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]
[size=10.5pt]RP4[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit[/size][size=10.5pt]2[font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP5[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit2[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]
[size=10.5pt]RP6[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit[/size][size=10.5pt]3[font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP7[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit3[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]
[size=10.5pt]RP8[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit[/size][size=10.5pt]4[font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP9[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit4[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]
[size=10.5pt]RP10[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit[/size][size=10.5pt]5[font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP11[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit5[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]
[size=10.5pt]RP12[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit[/size][size=10.5pt]6[font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP13[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit6[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]
[size=10.5pt]RP14[font=宋体]只计算行索引的[/font][/size][size=10.5pt]Bit[/size][size=10.5pt]7[font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行,[/font][font=Times New Roman]RP15[/font][font=宋体]只计算行索引的[/font][font=Times New Roman]Bit7[/font][font=宋体]为[/font][font=Times New Roman]1[/font][font=宋体]的行;[/font][/size][size=10.5pt][/size]


 wwxbei 回复于:2009-06-06 23:10:23

[size=10.5pt]已经知道,异或运算的作用是判断比特位为[font=Times New Roman]1[/font][font=宋体]的个数,跟比特位为[/font][font=Times New Roman]0[/font][font=宋体]的个数没有关系。如果有偶数个[/font][font=Times New Roman]1[/font][font=宋体]则异或的结果为[/font][font=Times New Roman]0[/font][font=宋体],如果有奇数个[/font][font=Times New Roman]1[/font][font=宋体]则异或的结果为[/font][font=Times New Roman]1[/font][font=宋体]。[/font][/size]
[size=10.5pt]那么,程序第[font=Times New Roman]88[/font][font=宋体]行,对所有行校验为[/font][font=Times New Roman]1[/font][font=宋体]的行索引按位异或运算,作用便是:[/font][/size]

[size=10.5pt]判断在所有行校验为[font=Times New Roman]1[/font][font=宋体]的行中,[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP1[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit 0[/font][font=宋体]指示,[/font][font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP[/font][/size][size=10.5pt]3[/size][size=10.5pt]计算范围内的行有多少个[font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]1[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP[/font][/size][size=10.5pt]5[/size][size=10.5pt]计算范围内的行有多少个[font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]2[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP[/font][/size][size=10.5pt]7[/size][size=10.5pt]计算范围内的行有多少个[font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]3[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP[/font][/size][size=10.5pt]9[/size][size=10.5pt]计算范围内的行有多少个[font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]4[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP[/font][/size][size=10.5pt]1[/size][size=10.5pt]1[font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]5[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP1[/font][/size][size=10.5pt]3[/size][size=10.5pt]计算范围内的行有多少个[font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]6[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP1[/font][/size][size=10.5pt]5[/size][size=10.5pt]计算范围内的行有多少个[font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg3[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]7[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]

 
[size=10.5pt]所以,[/size][size=10.5pt]reg3[/size][size=10.5pt]每个[font=Times New Roman]Bit[/font][font=宋体]位的作用如下表所示:[/font][/size]
[size=10.5pt]R[/size][size=10.5pt]eg3[/size]



 
[size=10.5pt]第[font=Times New Roman]89[/font][font=宋体]行,对所有行校验为[/font][font=Times New Roman]1[/font][font=宋体]的行索引按位取反之后,再按位异或,作用就是判断比特位为[/font][font=Times New Roman]0[/font][font=宋体]的个数。比如[/font][font=Times New Roman]reg2[/font][font=宋体]的[/font][font=Times New Roman]Bit0[/font][font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]表示:所有行校验为[/font][font=Times New Roman]1[/font][font=宋体]的行中,行索引的[/font][font=Times New Roman]Bit0[/font][font=宋体]为[/font][font=Times New Roman]0[/font][font=宋体]的行有偶数个,也就是落在[/font][font=Times New Roman]RP0[/font][font=宋体]计算范围内的行有偶数个。所以得到结论:[/font][/size]

 
[size=10.5pt]在所有行校验为[font=Times New Roman]1[/font][font=宋体]的行中,[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP0[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg[/size][size=10.5pt]2[font=宋体]的[/font][font=Times New Roman]Bit 0[/font][font=宋体]指示,[/font][font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP2[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg[/size][size=10.5pt]2[font=宋体]的[/font][font=Times New Roman]Bit [/font][/size][size=10.5pt]1[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP4[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg[/size][size=10.5pt]2[font=宋体]的[/font][font=Times New Roman]Bit [/font][/size][size=10.5pt]2[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP6[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg[/size][size=10.5pt]2[font=宋体]的[/font][font=Times New Roman]Bit [/font][/size][size=10.5pt]3[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP8[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg[/size][size=10.5pt]2[font=宋体]的[/font][font=Times New Roman]Bit [/font][/size][size=10.5pt]4[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP[/font][/size][size=10.5pt]1[/size][size=10.5pt]0[font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]re[/size][size=10.5pt]g2[font=宋体]的[/font][font=Times New Roman]Bit [/font][/size][size=10.5pt]5[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP12[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg2[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]6[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]
[size=10.5pt]属于[font=Times New Roman]RP14[/font][font=宋体]计算范围内的行有多少个[/font][font=Times New Roman]------[/font][font=宋体]由[/font][/size][size=10.5pt]reg2[/size][size=10.5pt]的[font=Times New Roman]Bit [/font][/size][size=10.5pt]7[/size][size=10.5pt]指示,[font=Times New Roman]0[/font][font=宋体]表示有偶数个,[/font][font=Times New Roman]1[/font][font=宋体]表示有奇数个;[/font][/size]

 
[size=10.5pt]所以,[/size][size=10.5pt]reg2[/size][size=10.5pt]每个[font=Times New Roman]Bit[/font][font=宋体]位的作用如下表所示:[/font][/size]
[size=10.5pt]R[/size][size=10.5pt]eg[/size][size=10.5pt]2[/size]


 
[size=10.5pt]至此,只用了一个查找表和一个[font=Times New Roman]for[/font][font=宋体]循环,就把所有的校验位[/font][/size][size=10.5pt]CP0 ~ CP5 [/size][size=10.5pt]和[font=Times New Roman]RP[/font][/size][size=10.5pt]0 ~ RP15[/size][size=10.5pt]全都计算出来了。下面的任务只是按照表[font=Times New Roman]3[/font][font=宋体]的格式,把这些比特位重新排列一下顺序而已。[/font][/size]
[size=10.5pt]从[/size][size=10.5pt]reg2[/size][size=10.5pt]和[/size][size=10.5pt]reg3[/size][size=10.5pt]中抽取出[/size][size=10.5pt] RP8~RP15[/size][size=10.5pt]放在[font=Times New Roman]tmp1[/font][font=宋体]中,抽取出[/font][/size][size=10.5pt]RP0~RP7[/size][size=10.5pt]放在[font=Times New Roman]tmp2[/font][font=宋体]中,[/font][/size]
[size=10.5pt]Reg1[/size][size=10.5pt]左移两位,低两位置[font=Times New Roman]1[/font][font=宋体],[/font][/size]
[size=10.5pt]然后把[/size][size=10.5pt]tmp2, tmp1, reg1 [/size][size=10.5pt]放在 [font=Times New Roman]ECC[/font][font=宋体]码的三个字节中。[/font][/size]
[size=12pt]程序中还有[/size][url=http://lxr.linux.no/linux+v2.6.27/+code=CONFIG_MTD_NAND_ECC_SMC][size=10pt]CONFIG_MTD_NAND_ECC_SMC[/size][size=12pt], 又进行了一次取反操作,暂时还不知为何。[/size]


 wwxbei 回复于:2009-06-06 23:11:40

[size=14pt]ECC[font=仿宋_GB2312]纠错算法[/font][/size][size=14pt][/size]
 
[size=10.5pt]当往[font=Times New Roman]NAND Flash[/font][font=宋体]的[/font][font=Times New Roman]page[/font][font=宋体]中写入数据的时候,每[/font][font=Times New Roman]256[/font][font=宋体]字节我们生成一个[/font][font=Times New Roman]ECC[/font][font=宋体]校验和,称之为原[/font][font=Times New Roman]ECC[/font][font=宋体]校验和,保存到[/font][font=Times New Roman]PAGE[/font][font=宋体]的[/font][font=Times New Roman]OOB[/font][font=宋体]([/font][font=Times New Roman]out-of-band[/font][font=宋体])数据区中。当从[/font][font=Times New Roman]NAND Flash[/font][font=宋体]中读取数据的时候,每[/font][font=Times New Roman]256[/font][font=宋体]字节我们生成一个[/font][font=Times New Roman]ECC[/font][font=宋体]校验和,称之为新[/font][font=Times New Roman]ECC[/font][font=宋体]校验和。[/font][/size]



[size=10.5pt]将从[font=Times New Roman]OOB[/font][font=宋体]区中读出的原[/font][font=Times New Roman]ECC[/font][font=宋体]校验和新[/font][font=Times New Roman]ECC[/font][font=宋体]校验和按位异或,若结果为[/font][font=Times New Roman]0[/font][font=宋体],则表示不存在错(或是出现了 [/font][font=Times New Roman]ECC[/font][font=宋体]无法检测的错误);若[/font][font=Times New Roman]3[/font][font=宋体]个字节异或结果中存在[/font][font=Times New Roman]11[/font][font=宋体]个比特位为[/font][font=Times New Roman]1[/font][font=宋体],表示存在一个比特错误,且可纠正;若[/font][font=Times New Roman]3[/font][font=宋体]个字节异或结果中只存在[/font][font=Times New Roman]1[/font][font=宋体]个比特位为[/font][font=Times New Roman]1[/font][font=宋体],表示 [/font][font=Times New Roman]OOB[/font][font=宋体]区出错;其他情况均表示出现了无法纠正的错误。[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]假设[font=Times New Roman]ecc[/font][/size][size=10.5pt]_code_raw[3] [/size][size=10.5pt]保存原始的[font=Times New Roman]ECC[/font][font=宋体]校验码,[/font][font=Times New Roman]ecc[/font][/size][size=10.5pt]_code_new[3] [/size][size=10.5pt]保存新计算出的[font=Times New Roman]ECC[/font][font=宋体]校验码,其格式如下表所示:[/font][/size][size=10.5pt][/size]

[size=10.5pt][/size]

 
[size=10.5pt]对[font=Times New Roman]ecc[/font][/size][size=10.5pt]_code_raw[3][/size][size=10.5pt] 和 [font=Times New Roman]ecc_code_new[/font][/size][size=10.5pt][3][/size][size=10.5pt] 按位异或,得到的结果三个字节分别保存在[/size][size=10.5pt]s0,s1,s2[/size][size=10.5pt]中,如果[font=Times New Roman]s[/font][/size][size=10.5pt]0s1s2[/size][size=10.5pt]中共有[font=Times New Roman]11[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]位为[/font][font=Times New Roman]1[/font][font=宋体],则表示出现了一个比特位错误,可以修正。定位出错的比特位的方法是,先确定行地址(即哪个字节出错),再确定列地址(即该字节中的哪一个[/font][font=Times New Roman]Bit[/font][font=宋体]位出错)。[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]确定行地址的方法是,设行地址为[/size][size=10.5pt]unsigned char [/size][size=10.5pt]byteoffs[font=宋体],抽取[/font][/size][size=10.5pt]s1[/size][size=10.5pt]中的[/size][size=10.5pt]Bit7,Bit5,Bit3,Bit1[/size][size=10.5pt],作为 [font=Times New Roman]byte[/font][/size][size=10.5pt]offs[/size][size=10.5pt]的高四位, 抽取[/size][size=10.5pt]s[/size][size=10.5pt]0[font=宋体]中的[/font][/size][size=10.5pt]Bit7,Bit5,Bit3,Bit1[/size][size=10.5pt] 作为[/size][size=10.5pt]byteoffs[/size][size=10.5pt]的低四位, 则[/size][size=10.5pt]byteoffs[/size][size=10.5pt]的值就表示出错字节的行地址(范围为[font=Times New Roman]0 ~ 255[/font][font=宋体])。[/font][/size][size=10.5pt][/size]
[size=10.5pt]确定列地址的方法是:抽取[/size][size=10.5pt]s2[/size][size=10.5pt]中的[/size][size=10.5pt]Bit7,Bit5,Bit3 [/size][size=10.5pt]作为 [font=Times New Roman]bitnum [/font][font=宋体]的低三位,[/font][font=Times New Roman]bitnum[/font][font=宋体]其余位置[/font][font=Times New Roman]0[/font][font=宋体],则[/font][font=Times New Roman]bitnum[/font][font=宋体]的表示出错[/font][font=Times New Roman]Bit[/font][font=宋体]位的列地址 (范围为[/font][font=Times New Roman]0 ~ 7[/font][font=宋体])。[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]下面以一个简单的例子探索一下这其中的奥妙。[/size][size=10.5pt][/size]
[size=10.5pt]假设待校验的数据为两个字节,[font=Times New Roman]0x[/font][/size][size=10.5pt]45[/size][size=10.5pt](二进制为[/size][size=10.5pt]0100 0101[/size][size=10.5pt])和[/size][size=10.5pt]0x38[/size][size=10.5pt](二进制为[/size][size=10.5pt]0011 1000[/size][size=10.5pt]),其行列校验码如下表所示:[/size]

[size=10.5pt][/size] 
[size=10.5pt][/size]


 
[size=10.5pt]从表中可以计算出[font=Times New Roman]CP5 ~ CP0[/font][font=宋体]的值,列在下表的第一行(原始数据)。假设现在有一个数据位发生变化,[/font][font=Times New Roman]0x[/font][/size][size=10.5pt]38[/size][size=10.5pt]变为[/size][size=10.5pt]0x3A[/size][size=10.5pt],也就是[/size][size=10.5pt]Byte[/size]
[size=10.5pt]1[/size][size=10.5pt]的[font=Times New Roman]Bit 1[/font][font=宋体]由[/font][font=Times New Roman]0[/font][font=宋体]变成了[/font][font=Times New Roman]1[/font][font=宋体],计算得到新的[/font][font=Times New Roman]CP5 ~ CP[/font][/size][size=10.5pt]0[/size][size=10.5pt]值放在下表第[font=Times New Roman]2[/font][font=宋体]行(变化后数据)。新旧校验码求异或的结果放在下表第三行。[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]可见,当 [font=Times New Roman]Bit[/font][/size]
[size=10.5pt]1[font=宋体]发生变化时,列校验值中只有[/font][font=Times New Roman]CP1[/font][font=宋体],[/font][font=Times New Roman]CP2[/font][font=宋体],[/font][font=Times New Roman]CP4[/font][font=宋体]发生了变化,而[/font][font=Times New Roman]CP0[/font][font=宋体],[/font][font=Times New Roman]CP3[/font][font=宋体],[/font][font=Times New Roman]CP5[/font][font=宋体]没变化,也就是说[/font][font=Times New Roman]6[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]校验码有一半发生变化,则求异或的结果中有一半为[/font][font=Times New Roman]1[/font][font=宋体]。同理,行校验求异或的结果也有一半为[/font][font=Times New Roman]1[/font][font=宋体]。这就是为什么前面说[/font][font=Times New Roman]256[/font][font=宋体]字节数据中的一个[/font][font=Times New Roman]Bit[/font][font=宋体]位发生变化时,新旧[/font][font=Times New Roman]22Bit[/font][font=宋体]校验码求异或的结果中会有[/font][font=Times New Roman]11[/font][font=宋体]个[/font][font=Times New Roman]Bit [/font][font=宋体]位为[/font][font=Times New Roman]1[/font][font=宋体]。[/font][/size][size=10.5pt][/size]
[size=10.5pt][/size]

[size=10.5pt][/size]

 
[size=10.5pt]再来看怎么定位出错的[font=Times New Roman]Bit[/font][font=宋体]位。以列地址为例,若[/font][font=Times New Roman]CP5[/font][font=宋体]发生变化(异或后的[/font][/size][size=10.5pt]CP5=1[/size][size=10.5pt]),则出错处肯定在 [font=Times New Roman]Bit 4 ~ Bit 7[/font][font=宋体]中;若[/font][font=Times New Roman]CP5[/font][font=宋体]无变化(异或后的[/font][/size][size=10.5pt]CP5=0[/size][size=10.5pt])[/size][size=10.5pt],[/size][size=10.5pt]则出错处在 [font=Times New Roman]Bit 0 ~ Bit 3 [/font][font=宋体]中,这样就筛选掉了一半的[/font][font=Times New Roman]Bit[/font][font=宋体]位。剩下的[/font][font=Times New Roman]4[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]位中,再看[/font][font=Times New Roman]CP3[/font][font=宋体]是否发生变化,又选出[/font][font=Times New Roman]2[/font][font=宋体]个[/font][font=Times New Roman]Bit[/font][font=宋体]位。剩下的[/font][font=Times New Roman]2Bit[/font][font=宋体]位中再看[/font][font=Times New Roman]CP1[/font][font=宋体]是否发生变化,则最终可定位[/font][font=Times New Roman]1[/font][font=宋体]个出错的[/font][font=Times New Roman]Bit[/font][font=宋体]位。下面的树形结构更清晰地展示了这个判决过程:[/font][/size][size=10.5pt][/size]
[size=10.5pt][/size]
[align=center][size=10pt]图表 [/size][size=10pt]1[/size][size=10pt]  出错[font=Arial]Bit[/font][font=黑体]列地址定位的判决树[/font][/size][size=10pt][/size][/align]

 
[size=10.5pt]注意:图中的[font=Times New Roman]CP[/font][font=宋体]指的是求异或之后的结果中的[/font][font=Times New Roman]CP[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]为什么只用[font=Times New Roman]CP4[/font][font=宋体],[/font][font=Times New Roman]CP2[/font][font=宋体],[/font][font=Times New Roman]CP0[/font][font=宋体]呢?其实这里面包含冗余信息,因为[/font][font=Times New Roman]CP5=1[/font][font=宋体]则必有[/font][font=Times New Roman]CP4=0[/font][font=宋体],[/font][font=Times New Roman]CP[/font][/size][size=10.5pt]5=0[/size][size=10.5pt]则必有[font=Times New Roman]CP4=1[/font][font=宋体],也就是[/font][font=Times New Roman]CP5[/font][font=宋体]跟[/font][font=Times New Roman]CP4[/font][font=宋体]一定相反,同理,[/font][/size][size=10.5pt]CP3[/size][size=10.5pt]跟[font=Times New Roman]CP2[/font][font=宋体]一定相反,[/font][font=Times New Roman]CP1[/font][font=宋体]跟[/font][font=Times New Roman]CP0[/font][font=宋体]一定相反。所以只需要用一半就行了。[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]这样,我们从异或结果中抽取出[font=Times New Roman]CP5[/font][font=宋体],[/font][font=Times New Roman]CP3[/font][font=宋体],[/font][font=Times New Roman]CP1[/font][font=宋体]位,便可定位出错[/font][font=Times New Roman]Bit[/font][font=宋体]位的列地址。比如上面的例子中[/font][/size][size=10.5pt]CP5/CP3/CP1 = 001[/size][size=10.5pt],表示[font=Times New Roman]Bit 1[/font][font=宋体]出错。[/font][/size][size=10.5pt][/size]

 
[size=10.5pt]同理,行校验[font=Times New Roman]RP1[/font][font=宋体]发生变化,抽取[/font][font=Times New Roman]RP1[/font][font=宋体],可知[/font][font=Times New Roman]Byte 1[/font][font=宋体]发生变化。这样定位出[/font][font=Times New Roman]Byte 1[/font][font=宋体]的[/font][font=Times New Roman]Bit 0[/font][font=宋体]出错。[/font][/size][size=10.5pt][/size]
[size=10.5pt]当数据位[font=Times New Roman]256[/font][font=宋体]字节时,行校验使用[/font][font=Times New Roman]RP0 ~ RP15[/font][font=宋体],抽取异或结果的[/font][/size][size=10.5pt]RP[/size][size=10.5pt]15[font=宋体],[/font][/size][size=10.5pt]RP13[/size][size=10.5pt],[/size][size=10.5pt]RP11[/size][size=10.5pt],[/size][size=10.5pt]RP[/size][size=10.5pt]9[font=宋体],[/font][/size][size=10.5pt]RP[/size][size=10.5pt]7[font=宋体],[/font][/size][size=10.5pt]RP[/size][size=10.5pt]5[font=宋体],[/font][font=Times New Roman]RP3[/font][font=宋体],[/font][font=Times New Roman]RP1[/font][font=宋体]位便可定位出哪个[/font][font=Times New Roman]Byte[/font][font=宋体]出错,再用[/font][font=Times New Roman]CP5,CP3,CP1[/font][font=宋体]定位哪个[/font][font=Times New Roman]Bit[/font][font=宋体]出错。[/font][/size]

[ 本帖最后由 wwxbei 于 2009-6-8 21:41 编辑 ]

TestEcc.rar


 bitmilong 回复于:2009-06-06 23:41:36

感謝wwxbei兄周末放送



ps.wwxbei兄潛水夠深呀,以後有空常來轉轉吧:em02:


 sep 回复于:2009-06-07 00:51:26

强。收藏了。


 unixlinuxsys 回复于:2009-06-07 09:04:37

best


 wwxbei 回复于:2009-06-07 13:59:24

呵呵,这里高手如云,还请指正。 转来转去发现还是ChinaUnix技术氛围最好。


 Siete 回复于:2009-06-07 20:57:42

收藏了


 crifan 回复于:2009-06-08 15:44:32

谢谢了。

不过,还是没理解88行的含义,
你的解释中,
还是没看懂这句“属于RP1计算范围内的行有多少个------由reg3的Bit 0指示”

可否再详细解释一下。

reg3的bit0,只能指示出
行的parity为1的那些i的bit0的异或

还是没看出来这些行i的异或,为何就等于“属于RP1计算范围内的行有多少个”了。。。。


 crifan 回复于:2009-06-08 20:26:36

终于基本看懂了。。。。

下面解释一下,也许可以给和我曾经一样迷茫的人一点帮助:


对于这个,别人总结出来的规则:
RP0只计算行索引的Bit0为0的行,RP1只计算行索引的Bit0为1的行;
RP2只计算行索引的Bit1为0的行,RP3只计算行索引的Bit1为1的行;
RP4只计算行索引的Bit2为0的行,RP5只计算行索引的Bit2为1的行;
RP6只计算行索引的Bit3为0的行,RP7只计算行索引的Bit3为1的行;
RP8只计算行索引的Bit4为0的行,RP9只计算行索引的Bit4为1的行;
RP10只计算行索引的Bit5为0的行,RP11只计算行索引的Bit5为1的行;
RP12只计算行索引的Bit6为0的行,RP13只计算行索引的Bit6为1的行;
RP14只计算行索引的Bit7为0的行,RP15只计算行索引的Bit7为1的行;

在接下来的描述中,称为 行与位的对应关系

另注:
1.上述规则中的RP意思是Row Parity,更多的叫法叫做LP(Line Parity)。为了解释更容易看懂,依旧采用RP的说法。
2.对于第几行,采用Line的说法,比如第1行,其实就是行号为0的Line0.
3.对于行的奇偶性,此处采用Line Parity的说法。

当Line5的Line Parity为1的时候,
首先最简单的理解,也是最直接的理解,那就是,要把所有RP0~RP14中,对应包含着此行的那些最后要计算的值找出来,
我们可以先手动地根据下图:

一点点,掰手指头,慢慢地写出来, 那就是:
RP1,RP2,RP5,RP6,RP8,RP10,RP12,RP14

换句话说,如果Line5的Line Parity为1的时候,
我们应该要计算RP1,RP2,RP5,RP6,RP8,RP10,RP12,RP14。
关于这点,我想大家没有什么好疑问的吧,因为这就是按照其规则的最简单,最通俗的理解。

所以,不论你用什么复杂的算法,反正是要记录并且计算这些RP的值,以便和后面的值进行计算。
但是,程序在此处,并没有将这些RP找出来,而只是直接对行号进行XOR异或:
reg3 ^= (uint8_t) i;

表面上看,这和我们要找出来,并计算的那些RP,并没啥关系,这也是我开始很困惑的问题。
按理来说,应该是找出那些行号,然后计算对应的RP的值,并保存,这样才对。

而此处之所以可以这么处理,主要是有以下原因:
1.        行与位的有如下对应关系:
RP0只计算行索引的Bit0为0的行,RP1只计算行索引的Bit0为1的行;
RP2只计算行索引的Bit1为0的行,RP3只计算行索引的Bit1为1的行;
RP4只计算行索引的Bit2为0的行,RP5只计算行索引的Bit2为1的行;
RP6只计算行索引的Bit3为0的行,RP7只计算行索引的Bit3为1的行;
RP8只计算行索引的Bit4为0的行,RP9只计算行索引的Bit4为1的行;
RP10只计算行索引的Bit5为0的行,RP11只计算行索引的Bit5为1的行;
RP12只计算行索引的Bit6为0的行,RP13只计算行索引的Bit6为1的行;
RP14只计算行索引的Bit7为0的行,RP15只计算行索引的Bit7为1的行;

2.        某一行号的二进制分解的对应bit,对应了所要计算的RP:

比如是第6行,也就是Line5,5的二进制是:
[table][tr][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit7[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit6[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit5[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit4[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit3[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit2[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit1[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit0[/font][/color][/size]
[/td][/tr][tr][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]1[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]1[/font][/color][/size]
[/td][/tr][/table]
5的二进制值
而根据上面别人分析出来的,行与位的对应关系,我们可以找出,此二进制的每一位所对应了哪些RP:
bit为1的位,分别是0,2,对应代表的是RP1,RP5
bit为0的位,分别是1,3,4,5,6,7,对应代表的是RP2,RP6,RP8,RP10,RP12,RP14
用表格表示为:
[table][tr][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit7[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit6[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit5[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit4[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit3[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit2[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit1[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]Bit0[/font][/color][/size]
[/td][/tr][tr][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]1[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]0[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]1[/font][/color][/size]
[/td][/tr][tr][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP14[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP12[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP10[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP8[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP6[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP5[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP2[/font][/color][/size]
[/td][td=1,1,71][size=3][color=#000080][font=Times New Roman]RP1[/font][/color][/size]
[/td][/tr][/table]
5的二进制值和二进制对应的行

上表中,比如bit2是1,而别人说了“RP5只计算行索引的Bit2为1的行”,
所以,此处如果bit2为1,对应着RP5将要被计算,
那么我们可以肯定地得出来的是,
如果此行,Line5,的Line Parity是1的话,RP5是要被计算的。
而仔细观察就会发现,RP5,就包含在我们上面自己手动找出来的那些LP中:
RP1,RP2,RP5,RP6,RP8,RP10,RP12,RP14
而,剩下的bit位,也依次对应着这些LP。比如bit0为1,对应RP1.

这就是我们上面说的“某一行号的二进制分解的对应bit,对应了所要计算的RP”
也是理解如此处理的关键点之一。

同样地,除了bit为1的bit0,bit2,对应的RP1,RP5之外,
剩下的几个bit对应的RP2,RP6,RP8,RP10,RP12,RP14,由于对应位是0,所以,即使拿过来抑或,也还是0,无法记住这些bit的值,所以,采用将其取反,这样,对应这些为0的bit,就变成1了,就可以记住这些对应的bit了:
reg2 ^= ~((uint8_t) i);

这样,当从0到255检测的过程中,如果发现某行的Line Parity是1,
那么就将其行号数值进行抑或,以存储奇数的LP,将行号取反,以保存偶数的LP,
也就是:
Reg3对应的就是RP1,RP3,RP5,。。。,RP15
Reg2对应的就是RP0,RP2,RP4,。。。,RP14

然后再调用函数nand_trans_result(reg2, reg3, ecc_code);去将reg3和reg2中存储的信息,
重新组织到ecc[1]和ecc[2]中去。

最后的感慨是:
此处仅仅是通过对行号的数值抑或,以保存所要求的各个RP的值,之所以让人很难理解:
一是由于我们之前不知道上面的那个规则:“行与位的对应关系”
二是我们不知道,行号按位分解后,对应的bit位对应着所要计算的那些RP,“某一行号的二进制分解的对应bit,对应了所要计算的RP”

最后感谢各位作者和分享其分析过程的朋友。


 coneagoe 回复于:2009-06-12 07:52:33

图文并茂,mark先


 willywang111 回复于:2009-06-15 09:42:33

好文章 ,顶一个


 miniuinx 回复于:2009-07-12 10:05:37

高手呀
先收藏了


 LinuxIsHard 回复于:2009-07-12 13:37:03

略看了一下好像就三星N年前的标准文档里的介绍的汉明码纠错。
实际应用上完全不实用
想不到linux只随便弄了个这么简单的东西来实现这功能,完全没意义啊,只追求功能不求实际的花哨特性。


 dreamice 回复于:2009-07-13 12:17:03

写得不错,以前做这个的时候,资料太少了。呵呵,感谢分享!


 luoqindong 回复于:2009-07-17 13:32:02

好帖!顶了


 myforever 回复于:2009-07-27 10:09:06

不错不错

顶一个




原文链接:http://linux.chinaunix.net/bbs/viewthread.php?tid=1116253
转载请注明作者名及原文出处