|
本帖最后由 吕氏春秋8266 于 2011-1-13 21:12 编辑
行检验码的生成过程:
根据异或规则,当一个数的ECC码第bit6位(En=1)时,将改变11位行检验码,显然,问题的关键是如何判断这11位行检验码。
当我们用i来表示字节在2048个字节中的位置时,由于2^11=2048,即i只取11位。
考虑如下:
2048个字节中第i个字节,其值ECC码第6位为1
再让我们考虑一下行检验码的生成规则
将其进行2平分后异或
P8912_1=E1024+E1025+……+E2047(显然,i[10]=1)
P8912_0=E0 + E1…… +E1023(显然,i[10]=0)
从以上规则可知:当i[10]=1时,即i在1024~2047之间,将改变p8912_1的值
当i[10]=0时,即i在0~1024 之间,将改变p8192_0的值
将其进行4平分后交差取值异或
P4196_1=E512+…+E1023+E1536+…+E2047
P4196_0= E0+…+ E511+E1024+…+E1535
显然,对512~1023而言,i[10,9]=01 1536~2047而言 i[10,9]=11
对0~511 而言, i[10,9]=00 1024~1535而言i[10,9]=10
从以上分析可以得知:我们只管i[9]而不用管i[10](用以判断P8192_0/1的值)
当i[9]=1时,即i在512~1023、1536~2047之间,将改变p4196_1的值
当i[9]=0时,即i在0~511、 1024~1535之间,将改变p4196_0的值
同理,我们根据位置i每一位的值为0/1来判断要改变的行检验码。
通过以上分析,我们知道,i取值范围为0~2047共2048个字节,i为11位。正好对应需要改变的11位行检验码。程序描述如下:
for(i=0;i<2048;i++)
{
j=pData; //得到要检验的数值
byte=Ecc_Table[j]; //查表得到ECC结果
list^=(byte&0x3f); //得到列检验码bit6位清零
if(byte&0x40) //判断第6位行检验码是否为1
{
If(bit0(i)==1) p8_1^=1;
Else p8_0^=1;
……………………………
If(bit10(i)==1) p8192_1^=1;
Else p8192_0^=1;
}
}
显然,通过一次循环及查表,我们就得到了6位列检验码和22位行检验码,我们将其按S3C2440内部定义的格式排列好就行了。
算法优化:
仔细观察第1109字节行校验码生成表示如下:
显然,我们可以定义两个标志Pn_0/1分别表示如上图:
Pn_0[0]=p8_0, Pn_0[1]=p16_0……pn_0[10]=p8192_0
Pn_1[0]=p8_1, Pn_0[1]=p16_1……pn_0[10]=p8192_1
根据异或规则,对0异或不改变其值,因此,要改变p8_1\p32_1\p128_1\p512_1\p8192_1
我们可以用i和Pn_1进行异或即可,同理,要改变其它行检验码的值,我们将i取反后与pn_0异或即可,故程度优化如下:
for(i=0;i<2048;i++)
{
j=pData;//得到要检验的数值
byte=Ecc_Table[j];//查表得到ECC结果
list^=(byte&0x3f);//得到列检验码
if(byte&0x40)//判断第6位为行检验码
{
row0^=((~i)&0x7ff);//取值11位pn_0
row1^=(i&0x7ff);//pn_1
}
}
好了,我们已经彻底了解了ECC校验算法的原理及实现,下面,我们再进行一个关键问题的研究,即ECC纠码错误位置确定。
ECC纠码错误
nandflash的每一页有两区:main区和spare区,main区用于存储正常的数据,spare区用于存储其他附加信息,其中就包括ECC校验码。当我们在写入数据的时候,我们就计算这一页数据的ECC校验码,然后把校验码存储到spare区的特定位置中,在下次读取这一页数据的时候,同样我们也计算ECC校验码,然后与spare区中的ECC校验码进行异或,结果全为0则说明读取的数据正确,如果为14个1位则表示有一位数据错误 |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|