ECC的代码实现
ECC的代碼實現
數據校驗介紹:
????????通俗的說,就是為保證數據的完整性,用一種指定的算法對原始數據計算出的一個校驗值。接收方用同樣的算法計算一次校驗值,如果和隨數據提供的校驗值一樣,就說明數據是完整的。
??????? 如果是時序或者電路方面有什么問題的話,錯誤數據的發生是無法通過數據校驗來進行彌補的,而對于受外界干擾而產生的位翻轉錯誤,則可以一定程度上通過HW或者SW的數據校驗來進行數據的檢測和糾正。
???????常用的數據校驗算法有CRC校驗和ECC校驗等,它們的基本原理很相似。
ECC介紹:
??????? ECC(錯誤檢查和糾正),這種技術也是在原來的數據位上外加校驗位來實現的,具體的原理不再描述,大致的描述可以參照:http://blog.csdn.net/nhczp/archive/2007/07/20/1700031.aspx.
??????? 它有一個規律:數據位每增加一倍,ECC只增加一位檢驗位,也就是說當數據位為16位時ECC位為6位,32位時ECC位為7位,數據位為64位時ECC位為8位,依此類推,數據位每增加一倍,ECC位只增加一位。
附件說明:
附件1:256字節ECC校正1比特錯誤代碼實現
附件2:512字節ECC校正1比特錯誤代碼實現
/*************************************************************************************************************/
附件1:256字節ECC校正1比特錯誤代碼實現
// 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
};
//計算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存入數組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);
?//計算最終的ECC碼
?//此處為什么要做一個求非的操作呢?
?//不取非也行,對結果沒有影響
?ECCCode[0]=~ECCCode[0];
?ECCCode[1]=~ECCCode[1];
?
?ECCCode[2]=(((~reg1)<<2)|0x03);
}
/*
* 參數解釋
* dat[]:實際讀取的數據
* ReadECC[]:保存數據時根據原始數據產生的ECC碼
* CalECC[]:讀取數據的同時產生的ECC碼
*/
int NandCorrectData(unsigned char *dat,unsigned char *ReadECC,unsigned char *CalECC)
{
?unsigned char a,b,c,bit,add,i,d1,d2,d3;
?//計算
?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)
?{
??//無錯誤發生
??printf("無錯誤發生/n");
??return 0;
?}
?else
?{
??a=((d1>>1)^d1)&0x55;
??b=((d2>>1)^d2)&0x55;
??c=((d3>>1)^d3)&0x54;
??//此處的理論依據是:如果發生了1bit的ECC錯誤,那么ECC異或地結果是--每個配對的bit數據相反,即為0&1或者1&0
??if((a == 0x55)&(b == 0x55)&(c == 0x54))
??{
???//可校正的1bit ECC錯誤
???
???//首先計算錯誤的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;
???}
???
???//計算發生錯誤的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;
???}
???//進行數據糾正
??//?printf("開始進行數據糾正/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("計算異或結果d1,d2,d3中1的個數/n");
???//計算異或結果d1,d2,d3中1的個數
???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)
???{
????//發生了ECC錯誤,即存放ECC數據的區域發生了錯誤,正常的情況下,無論多少
????//bit發生了反轉,都不會出現i=1的情況,出現了這種情況的原因只可能是ECC代碼本身有問題
???//?printf("存放ECC數據的區域發生了錯誤/n");
????return 2;
???}
???else
???{
????//不可校正的ECC錯誤,即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("可以校正的錯誤/n");
?//?printf("dat[0]=0x%0x/n",dat[0]);
?}
?else if(temp == -1)
?{
??//printf("不可以校正的錯誤");
?}
?else if(temp == 0)
?{
??//printf("無錯誤");
?}
?else
?{
?//?printf("數據區發生了錯誤");
?}
??//
???/*
?dat[5]=0x02;
?NandCalECC(dat,ReadECC);
?
?temp=NandCorrectData(dat,ReadECC,CalECC);
?if(temp == 1)
?{
??printf("可以校正的錯誤/n");
??printf("dat[0]=0x%0x/n",dat[0]);
?}
?else if(temp == -1)
?{
??printf("不可以校正的錯誤");
?}
?else if(temp == 0)
?{
??printf("無錯誤");
?}
?else
?{
??printf("數據區發生了錯誤");
?}
*/
?//
??}
?}
?printf("rotate times:%5d/n",m);
?return 0;
}
附件2:512字節ECC校正1比特錯誤的代碼實現?
// 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
};
//計算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個bit的數據
???reg2^=(~(j&0x1ff));//同樣的道理取出9的bit數據
??//?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);
?
?//計算最終的ECC碼
?//此處為什么要做一個求非的操作呢??????,如果不做非操作也沒有問題
?/*
?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);
?*/
}
/*
* 參數解釋
* dat[]:實際讀取的數據
* ReadECC[]:保存數據時根據原始數據產生的ECC碼
* CalECC[]:讀取數據的同時產生的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;
?//計算
?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)
?{
??//無錯誤發生
??printf("無錯誤發生/n");
??return 0;
?}
?else
?{
??a=((d1>>1)^d1)&0x55;
??b=((d2>>1)^d2)&0x55;
??//c=((d3>>1)^d3)&0x54;
??c=((d3>>1)^d3)&0x55;
??//此處的理論依據是:如果發生了1bit的ECC錯誤,那么ECC異或地結果是--每個配對的bit數據相反,即為0&1或者1&0
??if((a == 0x55)&(b == 0x55)&(c == 0x55))
??{
???//可校正的1bit ECC錯誤
???
???//首先計算錯誤的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對應位置的值
???if(d3&0x2)
???{
????add|=0x100;
???//?printf("[NandCorrectData] add|=0x100/n");
???}
???//計算發生錯誤的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;
???}
???//進行數據糾正
???//printf("開始進行數據糾正/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("計算異或結果d1,d2,d3中1的個數/n");
???//計算異或結果d1,d2,d3中1的個數
???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)
???{
????//發生了ECC錯誤,即存放ECC數據的區域發生了錯誤,正常的情況下,無論多少
????//bit發生了反轉,都不會出現i=1的情況,出現了這種情況的原因只可能是ECC代碼本身有問題
????//printf("存放ECC數據的區域發生了錯誤/n");
????return 2;
???}
???else
???{
????//不可校正的ECC錯誤,多于1比特的錯誤即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];//記錄下人為修改之前的數據
??
??for(k=0;k<8;k++)
??{
???//m++;//記錄該循環執行的次數
???dat[i]^=j;//改變原始數據的某一個Bit
???j>>=1;??//為改變原始數據的下一個Bit做準備
???NandCalECC(dat,ReadECC);//計算修改過512字節數據的ECC值
?
???temp=NandCorrectData(dat,ReadECC,CalECC);//對數據進行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("可以校正的錯誤/n");
????//?printf("dat[0]=0x%0x/n",dat[0]);
???}
???else if(temp == -1)
???{
????//printf("不可以校正的錯誤");
???}
???else if(temp == 0)
???{
????//printf("無錯誤");
???}
???else
???{
???//?printf("數據區發生了錯誤");
???}
???//printf("/n/n");
??}
?}
?printf("Success times:%5d,failed times:%5d/n",n,m);
?printf("*******************Program end******************/n");
?return 0;
}
??????????????????????????????????????????????????????????????????????????????????????????????????????????????- -20071127晚
/*************************************************************************************************************/
/**********************************************
* 如有疑問,歡迎聯系guopeixin@126.com
***********************************************/
/*************************************************************************************************************/
總結
- 上一篇: 上线四集13万人评价!9.4高分国漫《中
- 下一篇: WinCE电源管理的简单介绍