ECC的代码实现
ECC的代碼實(shí)現(xiàn)
數(shù)據(jù)校驗(yàn)介紹:
????????通俗的說,就是為保證數(shù)據(jù)的完整性,用一種指定的算法對原始數(shù)據(jù)計(jì)算出的一個(gè)校驗(yàn)值。接收方用同樣的算法計(jì)算一次校驗(yàn)值,如果和隨數(shù)據(jù)提供的校驗(yàn)值一樣,就說明數(shù)據(jù)是完整的。
??????? 如果是時(shí)序或者電路方面有什么問題的話,錯(cuò)誤數(shù)據(jù)的發(fā)生是無法通過數(shù)據(jù)校驗(yàn)來進(jìn)行彌補(bǔ)的,而對于受外界干擾而產(chǎn)生的位翻轉(zhuǎn)錯(cuò)誤,則可以一定程度上通過HW或者SW的數(shù)據(jù)校驗(yàn)來進(jìn)行數(shù)據(jù)的檢測和糾正。
???????常用的數(shù)據(jù)校驗(yàn)算法有CRC校驗(yàn)和ECC校驗(yàn)等,它們的基本原理很相似。
ECC介紹:
??????? ECC(錯(cuò)誤檢查和糾正),這種技術(shù)也是在原來的數(shù)據(jù)位上外加校驗(yàn)位來實(shí)現(xiàn)的,具體的原理不再描述,大致的描述可以參照:http://blog.csdn.net/nhczp/archive/2007/07/20/1700031.aspx.
??????? 它有一個(gè)規(guī)律:數(shù)據(jù)位每增加一倍,ECC只增加一位檢驗(yàn)位,也就是說當(dāng)數(shù)據(jù)位為16位時(shí)ECC位為6位,32位時(shí)ECC位為7位,數(shù)據(jù)位為64位時(shí)ECC位為8位,依此類推,數(shù)據(jù)位每增加一倍,ECC位只增加一位。
附件說明:
附件1:256字節(jié)ECC校正1比特錯(cuò)誤代碼實(shí)現(xiàn)
附件2:512字節(jié)ECC校正1比特錯(cuò)誤代碼實(shí)現(xiàn)
/*************************************************************************************************************/
附件1:256字節(jié)ECC校正1比特錯(cuò)誤代碼實(shí)現(xiàn)
// 256ByteECC071123.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
//071126
unsigned char dat[]={
0x0? ,0x0 ,0x0 ,0x0? ,0x0 ,0x0? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0? ,
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 ,0x33 ,0x66 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
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 ,0x3c ,0x3f ,0x6a ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
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 ,0x66 ,0x33 ,0x30 ,0x65 ,
0x0? ,0x55 ,0x56 ,0x3? ,0x59 ,0xc? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0
};
//071123
unsigned char ECCTable[]={
0x0? ,0x55 ,0x56 ,0x3? ,0x59 ,0xc? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0? ,
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 ,0x33 ,0x66 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
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 ,0x3c ,0x3f ,0x6a ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
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 ,0x66 ,0x33 ,0x30 ,0x65 ,
0x0? ,0x55 ,0x56 ,0x3? ,0x59 ,0xc? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0
};
//計(jì)算ECC代碼
void NandTranResult(unsigned char reg2,unsigned char reg3,unsigned char *ECCCode)
{
?unsigned char temp1,temp2,i,a,b;
?temp1=temp2=0;
?a=b=0x80;
?for(i=0;i<4;i++)
?{
??if(reg3&a)
???temp1|=b;
??b>>=1;
??if(reg2&a)
???temp1|=b;
??b>>=1;
??a>>=1;
?}
?b=0x80;
?for(i=0;i<4;i++)
?{
??if(reg3&a)
???temp2|=b;
??b>>=1;
??if(reg2&a)
???temp2|=b;
??b>>=1;
??a>>=1;
?}
?
?//將最終的ECC存入數(shù)組ECCCode
?ECCCode[0]=temp1;//存放高8bit
?ECCCode[1]=temp2;//存放中間的8bit
}
void NandCalECC(const unsigned char *dat,unsigned char *ECCCode)
{
?unsigned char reg1,reg2,reg3,temp;
?int j;
?reg1=reg2=reg3=0;
?for(j=0;j<256;j++)
?{
??temp=ECCTable[dat[j]];
??reg1^=(temp&0x3f);
??if(temp&0x40)
??{
???reg3^=(unsigned char)j;
???reg2^=(~((unsigned char)j));
??}
?}
?NandTranResult(reg2,reg3,ECCCode);
?//計(jì)算最終的ECC碼
?//此處為什么要做一個(gè)求非的操作呢?
?//不取非也行,對結(jié)果沒有影響
?ECCCode[0]=~ECCCode[0];
?ECCCode[1]=~ECCCode[1];
?
?ECCCode[2]=(((~reg1)<<2)|0x03);
}
/*
* 參數(shù)解釋
* dat[]:實(shí)際讀取的數(shù)據(jù)
* ReadECC[]:保存數(shù)據(jù)時(shí)根據(jù)原始數(shù)據(jù)產(chǎn)生的ECC碼
* CalECC[]:讀取數(shù)據(jù)的同時(shí)產(chǎn)生的ECC碼
*/
int NandCorrectData(unsigned char *dat,unsigned char *ReadECC,unsigned char *CalECC)
{
?unsigned char a,b,c,bit,add,i,d1,d2,d3;
?//計(jì)算
?d1=ReadECC[0]^CalECC[0];
?d2=ReadECC[1]^CalECC[1];
?d3=ReadECC[2]^CalECC[2];
?//printf("d1=0x%0x,d2=0x%0x,d3=0x%0x/n",d1,d2,d3);
?if((d1|d2|d3) == 0)
?{
??//無錯(cuò)誤發(fā)生
??printf("無錯(cuò)誤發(fā)生/n");
??return 0;
?}
?else
?{
??a=((d1>>1)^d1)&0x55;
??b=((d2>>1)^d2)&0x55;
??c=((d3>>1)^d3)&0x54;
??//此處的理論依據(jù)是:如果發(fā)生了1bit的ECC錯(cuò)誤,那么ECC異或地結(jié)果是--每個(gè)配對的bit數(shù)據(jù)相反,即為0&1或者1&0
??if((a == 0x55)&(b == 0x55)&(c == 0x54))
??{
???//可校正的1bit ECC錯(cuò)誤
???
???//首先計(jì)算錯(cuò)誤的Byte
???
???a=b=c=0x80;
???add=0;
???for(i=0;i<4;i++)
???{
????if(d1&a)
?????add|=b;
????a>>=2;
????b>>=1;
???}
???
???for(i=0;i<4;i++)
???{
????if(d2&c)
?????add|=b;
????c>>=2;
????b>>=1;
???}
???
???//計(jì)算發(fā)生錯(cuò)誤的Bit
???bit=0;
???a=0x80;
???b=0x04;
???
??//?printf("d3 = 0x%0x/n",d3);
???for(i=0;i<3;i++)
???{
????if(d3&a)
????{
?????bit|=b;
??//???printf("Detected!/n");
????}
????else
????{
?????//printf("d3=0x%0x,a=0x%0x,d3&a=0x%0x/n",d3,a,d3&a);
??//???printf("Not Detected!/n");
????}
????a>>=2;
????b>>=1;
???}
???//進(jìn)行數(shù)據(jù)糾正
??//?printf("開始進(jìn)行數(shù)據(jù)糾正/n");
??//?printf("Error byte: %2d,Error bit: %2d/n",add,bit);
???b=0x01;
???b<<=bit;
???a=dat[add];
???a^=b;
???dat[add]=a;
???return 1;
??}
??else
??{
???i=0;
??//?printf("計(jì)算異或結(jié)果d1,d2,d3中1的個(gè)數(shù)/n");
???//計(jì)算異或結(jié)果d1,d2,d3中1的個(gè)數(shù)
???while(d1)
???{
????if(d1&0x01)
?????i++;
????d1>>=1;
???}
???while(d2)
???{
????if(d2&0x01)
?????i++;
????d3>>=1;
???}
???while(d3)
???{
????if(d3&0x01)
?????i++;
????d3>>=1;
???}
???if(i == 1)
???{
????//發(fā)生了ECC錯(cuò)誤,即存放ECC數(shù)據(jù)的區(qū)域發(fā)生了錯(cuò)誤,正常的情況下,無論多少
????//bit發(fā)生了反轉(zhuǎn),都不會(huì)出現(xiàn)i=1的情況,出現(xiàn)了這種情況的原因只可能是ECC代碼本身有問題
???//?printf("存放ECC數(shù)據(jù)的區(qū)域發(fā)生了錯(cuò)誤/n");
????return 2;
???}
???else
???{
????//不可校正的ECC錯(cuò)誤,即Uncorrectable Error
???//?printf("Uncorrectable Error/n");
????return -1;
???}
??}
?}
?return -1;
}
int main(int argc, char* argv[])
{
?int temp,i,j,k,l,m=0;
?unsigned char ReadECC[3]={0,0,0},CalECC[3]={0,0,0};
?NandCalECC(dat,CalECC);
?for(i=0;i<256;i++)
?{
??j=0x80;
??l=dat[i];
??for(k=0;k<8;k++)
??{
???m++;
?dat[i]^=j;
?j>>=1;
?NandCalECC(dat,ReadECC);
?
?temp=NandCorrectData(dat,ReadECC,CalECC);
?if(temp == 1)
?{
??if(dat[i]==l)
???printf("Success/n");???
??else
???printf("Failed/n");
?//?printf("可以校正的錯(cuò)誤/n");
?//?printf("dat[0]=0x%0x/n",dat[0]);
?}
?else if(temp == -1)
?{
??//printf("不可以校正的錯(cuò)誤");
?}
?else if(temp == 0)
?{
??//printf("無錯(cuò)誤");
?}
?else
?{
?//?printf("數(shù)據(jù)區(qū)發(fā)生了錯(cuò)誤");
?}
??//
???/*
?dat[5]=0x02;
?NandCalECC(dat,ReadECC);
?
?temp=NandCorrectData(dat,ReadECC,CalECC);
?if(temp == 1)
?{
??printf("可以校正的錯(cuò)誤/n");
??printf("dat[0]=0x%0x/n",dat[0]);
?}
?else if(temp == -1)
?{
??printf("不可以校正的錯(cuò)誤");
?}
?else if(temp == 0)
?{
??printf("無錯(cuò)誤");
?}
?else
?{
??printf("數(shù)據(jù)區(qū)發(fā)生了錯(cuò)誤");
?}
*/
?//
??}
?}
?printf("rotate times:%5d/n",m);
?return 0;
}
附件2:512字節(jié)ECC校正1比特錯(cuò)誤的代碼實(shí)現(xiàn)?
// 512ByteECC071127.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "stdio.h"
// 256ByteECC071123.cpp : Defines the entry point for the console application.
//
//071127
unsigned char dat[]={
0x0? ,0x0 ,0x0 ,0x0? ,0x0 ,0x0? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0? ,
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 ,0x33 ,0x66 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
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 ,0x3c ,0x3f ,0x6a ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
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 ,0x66 ,0x33 ,0x30 ,0x65 ,
0x0? ,0x55 ,0x56 ,0x3? ,0x59 ,0xc? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0? ,
0x0? ,0x0 ,0x0 ,0x0? ,0x0 ,0x0? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0? ,
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 ,0x33 ,0x66 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
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 ,0x3c ,0x3f ,0x6a ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
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 ,0x66 ,0x33 ,0x30 ,0x65 ,
0x0? ,0x55 ,0x56 ,0x3? ,0x59 ,0xc? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0
};
//071123
unsigned char ECCTable[]={
0x0? ,0x55 ,0x56 ,0x3? ,0x59 ,0xc? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0? ,
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 ,0x33 ,0x66 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
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 ,0x3c ,0x3f ,0x6a ,
0xf? ,0x5a ,0x59 ,0xc? ,0x56 ,0x3? ,0x0? ,0x55 ,0x55 ,0x0? ,0x3? ,0x56 ,0xc? ,0x59 ,0x5a ,0xf? ,
0xc? ,0x59 ,0x5a ,0xf? ,0x55 ,0x0? ,0x3? ,0x56 ,0x56 ,0x3? ,0x0? ,0x55 ,0xf? ,0x5a ,0x59 ,0xc? ,
0x69 ,0x3c ,0x3f ,0x6a ,0x30 ,0x65 ,0x66 ,0x33 ,0x33 ,0x66 ,0x65 ,0x30 ,0x6a ,0x3f ,0x3c ,0x69 ,
0x3? ,0x56 ,0x55 ,0x0? ,0x5a ,0xf? ,0xc? ,0x59 ,0x59 ,0xc? ,0xf? ,0x5a ,0x0? ,0x55 ,0x56 ,0x3? ,
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 ,0x66 ,0x33 ,0x30 ,0x65 ,
0x0? ,0x55 ,0x56 ,0x3? ,0x59 ,0xc? ,0xf? ,0x5a ,0x5a ,0xf? ,0xc? ,0x59 ,0x3? ,0x56 ,0x55 ,0x0
};
//計(jì)算ECC代碼
void NandTranResult(unsigned int *reg1,unsigned int *reg2,unsigned int *reg3)
{
?unsigned char i,a,b;
?unsigned int temp1,temp2,temp3;
?temp1=temp2=temp3=0;
?a=b=0x80;
?for(i=0;i<4;i++)
?{
??if((*reg3)&a)
???temp1|=b;
??b>>=1;
??if((*reg2)&a)
???temp1|=b;
??b>>=1;
??a>>=1;
?}
?b=0x80;
?for(i=0;i<4;i++)
?{
??if((*reg3)&a)
???temp2|=b;
??b>>=1;
??if((*reg2)&a)
???temp2|=b;
??b>>=1;
??a>>=1;
?}
?temp3|=((*reg1)&0x3f);
?temp3<<=2;
?if((*reg3)&0x100)
??temp3|=0x2;
?if((*reg2)&0x100)
??temp3|=0x1;
?*reg1=temp1;
?*reg2=temp2;
?*reg3=temp3;
}
void NandCalECC(const unsigned char *dat,unsigned char *ECCCode)
{
?unsigned int reg1,reg2,reg3,temp;
?unsigned int j;
?reg1=reg2=reg3=0;
?for(j=0;j<512;j++)
?{
??temp=ECCTable[dat[j]];
??reg1^=(temp&0x3f);
??if(temp&0x40)
??{????
???reg3^=(j&0x1ff);???//取出變量j低9個(gè)bit的數(shù)據(jù)
???reg2^=(~(j&0x1ff));//同樣的道理取出9的bit數(shù)據(jù)
??//?if(j==0||j==256)
??//??printf("[NandCalECC] Byte:%3d,reg3:0x%0x,reg2:0x%0x/n",j,reg3,reg2);
??}
?}
?//printf("[NandCalECC] reg1=0x%0x,reg2=0x%0x,reg3=0x%0x/n",reg1,reg2,reg3);
?NandTranResult(®1,®2,®3);
?//?printf("[NandCalECC] reg1=0x%0x,reg2=0x%0x,reg3=0x%0x/n",reg1,reg2,reg3);
?ECCCode[0]=~((unsigned char)reg1);
?ECCCode[1]=~((unsigned char)reg2);?
?ECCCode[2]=~((unsigned char)reg3);
?
?//計(jì)算最終的ECC碼
?//此處為什么要做一個(gè)求非的操作呢??????,如果不做非操作也沒有問題
?/*
?ECCCode[0]=~ECCCode[0];
?ECCCode[1]=~ECCCode[1];
?
?ECCCode[2]=(((~reg1)<<2)|0x03);
?*/
?/*
?ECCCode[0]=ECCCode[0];
?ECCCode[1]=ECCCode[1];
?
?ECCCode[2]=(((reg1)<<2)|0x03);
?*/
}
/*
* 參數(shù)解釋
* dat[]:實(shí)際讀取的數(shù)據(jù)
* ReadECC[]:保存數(shù)據(jù)時(shí)根據(jù)原始數(shù)據(jù)產(chǎn)生的ECC碼
* CalECC[]:讀取數(shù)據(jù)的同時(shí)產(chǎn)生的ECC碼
*/
int NandCorrectData(unsigned char *dat,unsigned char *ReadECC,unsigned char *CalECC)
{
?unsigned char bit,i;
?unsigned int add,a,b,c,d1,d2,d3;
?add=a=b=c=d1=d3=d2=0;
?//計(jì)算
?d1=ReadECC[0]^CalECC[0];
?d2=ReadECC[1]^CalECC[1];
?d3=ReadECC[2]^CalECC[2];
?//printf("[NandCorrectData] d1=0x%0x,d2=0x%0x,d3=0x%0x/n",d1,d2,d3);
?if((d1|d2|d3) == 0)
?{
??//無錯(cuò)誤發(fā)生
??printf("無錯(cuò)誤發(fā)生/n");
??return 0;
?}
?else
?{
??a=((d1>>1)^d1)&0x55;
??b=((d2>>1)^d2)&0x55;
??//c=((d3>>1)^d3)&0x54;
??c=((d3>>1)^d3)&0x55;
??//此處的理論依據(jù)是:如果發(fā)生了1bit的ECC錯(cuò)誤,那么ECC異或地結(jié)果是--每個(gè)配對的bit數(shù)據(jù)相反,即為0&1或者1&0
??if((a == 0x55)&(b == 0x55)&(c == 0x55))
??{
???//可校正的1bit ECC錯(cuò)誤
???
???//首先計(jì)算錯(cuò)誤的Byte
???
???a=b=c=0x80;
???add=0;
???for(i=0;i<4;i++)
???{
????if(d1&a)
?????add|=b;
????a>>=2;
????b>>=1;
???}
???
???for(i=0;i<4;i++)
???{
????if(d2&c)
?????add|=b;
????c>>=2;
????b>>=1;
???}
???
???//檢查P2048對應(yīng)位置的值
???if(d3&0x2)
???{
????add|=0x100;
???//?printf("[NandCorrectData] add|=0x100/n");
???}
???//計(jì)算發(fā)生錯(cuò)誤的Bit
???bit=0;
???a=0x80;
???b=0x04;
???
??//?printf("d3 = 0x%0x/n",d3);
???for(i=0;i<3;i++)
???{
????if(d3&a)
????{
?????bit|=b;
??//???printf("Detected!/n");
????}
????else
????{
?????//printf("d3=0x%0x,a=0x%0x,d3&a=0x%0x/n",d3,a,d3&a);
??//???printf("Not Detected!/n");
????}
????a>>=2;
????b>>=1;
???}
???//進(jìn)行數(shù)據(jù)糾正
???//printf("開始進(jìn)行數(shù)據(jù)糾正/n");
???//printf("[NandCorrectData] Error byte: %5d,Error bit: %5d/n",add,bit);
???b=0x01;
???b<<=bit;
???a=dat[add];
???a^=b;
???dat[add]=a;
???return 1;
??}
??else
??{
???i=0;
???//printf("計(jì)算異或結(jié)果d1,d2,d3中1的個(gè)數(shù)/n");
???//計(jì)算異或結(jié)果d1,d2,d3中1的個(gè)數(shù)
???while(d1)
???{
????if(d1&0x01)
?????i++;
????d1>>=1;
???}
???while(d2)
???{
????if(d2&0x01)
?????i++;
????d3>>=1;
???}
???while(d3)
???{
????if(d3&0x01)
?????i++;
????d3>>=1;
???}
???if(i == 1)
???{
????//發(fā)生了ECC錯(cuò)誤,即存放ECC數(shù)據(jù)的區(qū)域發(fā)生了錯(cuò)誤,正常的情況下,無論多少
????//bit發(fā)生了反轉(zhuǎn),都不會(huì)出現(xiàn)i=1的情況,出現(xiàn)了這種情況的原因只可能是ECC代碼本身有問題
????//printf("存放ECC數(shù)據(jù)的區(qū)域發(fā)生了錯(cuò)誤/n");
????return 2;
???}
???else
???{
????//不可校正的ECC錯(cuò)誤,多于1比特的錯(cuò)誤即Uncorrectable Error
????//printf("Uncorrectable Error/n");
????return -1;
???}
??}
?}
?return -1;
}
int main(int argc, char* argv[])
{
?int temp,i,j,k,l,m=0,n=0;
?unsigned char ReadECC[3]={0,0,0},CalECC[3]={0,0,0};
?printf("*****************Program start******************/n");
?NandCalECC(dat,CalECC);
?printf("/n/n");
?for(i=0;i<512;i++)
?{
??j=0x80;
??l=dat[i];//記錄下人為修改之前的數(shù)據(jù)
??
??for(k=0;k<8;k++)
??{
???//m++;//記錄該循環(huán)執(zhí)行的次數(shù)
???dat[i]^=j;//改變原始數(shù)據(jù)的某一個(gè)Bit
???j>>=1;??//為改變原始數(shù)據(jù)的下一個(gè)Bit做準(zhǔn)備
???NandCalECC(dat,ReadECC);//計(jì)算修改過512字節(jié)數(shù)據(jù)的ECC值
?
???temp=NandCorrectData(dat,ReadECC,CalECC);//對數(shù)據(jù)進(jìn)行ECC
???if(temp == 1)
???{
????if(dat[i]==l)
????//?printf("Success/n");???
?????n++;
????else
????{
?????m++;
?????printf("Failed at byte:%5d,bit:%5d/n",i,k);
????}
????//?printf("可以校正的錯(cuò)誤/n");
????//?printf("dat[0]=0x%0x/n",dat[0]);
???}
???else if(temp == -1)
???{
????//printf("不可以校正的錯(cuò)誤");
???}
???else if(temp == 0)
???{
????//printf("無錯(cuò)誤");
???}
???else
???{
???//?printf("數(shù)據(jù)區(qū)發(fā)生了錯(cuò)誤");
???}
???//printf("/n/n");
??}
?}
?printf("Success times:%5d,failed times:%5d/n",n,m);
?printf("*******************Program end******************/n");
?return 0;
}
??????????????????????????????????????????????????????????????????????????????????????????????????????????????- -20071127晚
/*************************************************************************************************************/
/**********************************************
* 如有疑問,歡迎聯(lián)系guopeixin@126.com
***********************************************/
/*************************************************************************************************************/
總結(jié)
- 上一篇: 上线四集13万人评价!9.4高分国漫《中
- 下一篇: 转载:Windows CE内存管理