全部博文(9)
分类: LINUX
2008-07-02 11:20:45
首先感谢www.mcuos.com的wonder sky对我的指导.本帖主要是对话记录.
文件:
NAND_ECC_Algoritalm.PDF
大小:
166KB
下载:
下载
代码中的ECC_CODE顺序和文中的ECC图示并不相同,
代码中的ECC_CODE[0]对应的是P1024~P128',
ECC_CODE[1]对应的是P64~P8'。
检验代码如下:
#include
#include
typedef unsigned char u_char;
u_char ecc_code[3];
u_char nand_ecc_precalc_table[] =
{
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, 0x33, 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, 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, 0x3c, 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, 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, 0x66, 0x33, 0x30, 0x65,
0x00, 0x55, 0x56, 0x03, 0x59, 0x0c, 0x0f, 0x5a, 0x5a, 0x0f, 0x0c, 0x59, 0x03, 0x56, 0x55, 0x00
};
void nand_trans_result(u_char reg2,u_char reg3,u_char *ecc_code)
{
u_char a,b,i,tmp1,tmp2;
a=b=0x80;
tmp1=tmp2=0;
for(i = 0;i < 4;i++)
{
if(reg3&a)
tmp1|=b;
b>>=1;
if(reg2&a)
tmp1|=b;
b>>=1;
a>>=1;
}
b=0x80;
for(i = 0;i < 4;i++)
{
if(reg3&a)
tmp2|=b;
b>>=1;
if(reg2&a)
tmp2|=b;
b>>=1;
a>>=1;
}
ecc_code[0]=tmp1;
ecc_code[1]=tmp2;
}
void nand_calculate_ecc(u_char *dat,u_char*ecc_code)
{
u_char idx,reg1,reg2,reg3;
int j;
reg1=reg2=reg3=0;
ecc_code[0]=ecc_code[1]=ecc_code[2]=0;
for(j=0;j<256;j++)
{
idx=nand_ecc_precalc_table[dat[j]];
reg1^=(idx&0x3f);
if(idx&0x40)
{
reg3^=(u_char)j;
reg2 ^=~((u_char)j);
}
}
ecc_code[2]=reg1;
nand_trans_result(reg2,reg3,ecc_code);
cout<<"Org_Cal -> Ecc_code are :\n"
<<(int)ecc_code[0]<
}
void hard_cal(u_char *dat,u_char*ecc_code)
{
u_char idx,reg1,reg2,reg3;
int j;
reg1=reg2=reg3=0;
ecc_code[0]=ecc_code[1]=ecc_code[2]=0;
for(j=0;j<256;j++)
{
idx=nand_ecc_precalc_table[dat[j]];
reg1^=(idx&0x3f);
}
ecc_code[2]=reg1;
u_char cal1=0,cal2=0;
int Move=0,count=1;
while(count<=128)
{
int i=0;
cal1=0;
cal2=0;
while(i<256)
{
for(int j=0;j
if(nand_ecc_precalc_table[dat[i+j]]&0x40)
cal1^=1;//P'
if(nand_ecc_precalc_table[dat[i+count+j]]&0x40)
cal2^=1;//P
}
i+=2*count;
}
if(Move<8)
{
ecc_code[0]|=cal1<<(Move);
ecc_code[0]|=cal2<<(Move+1);
}
else
{
ecc_code[1]|=cal1<<(Move-8);
ecc_code[1]|=cal2<<((Move-8)+1);
}
count*=2;
Move+=2;
}
cout<<"hard cal -> Ecc_code are :\n"
<<(int)ecc_code[0]<
/*
ECC_CODE[0]
ECC_CODE[1]保存的是P64,P64',P32,P32',P16,P16',P8,P8'
*/
int main()
{
u_char dat[256];
for(int i=0;i<256;i++)
dat = rand()%256;
hard_cal(dat,ecc_code);
nand_calculate_ecc(dat,ecc_code);
return 1;
}
在VC6下编译通过,其中的hard_cal是按照图示的顺序摆放ECC,按照定义来进行计算的,结果两者的ECC_CODE颠倒,可以证明之前的结论正确。
这样的Reg3中从高位到地位摆放的是P1024~P8的值。
为什么这些位的值可以表示P1024~P8的值呢,看看之前的
if(idx&0x40)
{
reg3^=(u_char)j;
reg2 ^=~((u_char)j);
}
idx&0x40,因为行校验初始为0,所以只有在idx&0x40=1的情况,即某行的行校验为1的时候,进行异或才能使行校验的值发生改变。
reg3^=(u_char)j,这句代码可以记住这些行校验的值,
首先,8,16,32……1024对应的字节数为1,2,4……128,
对于P8,进行计算的行号为1,3,5,……,即所有的奇数号,这些数字的二进制表示的特征是第一位一定为1,
对于P16,计算的行号为2,3,6,7……,这些数字的二机制表示的特征是第二位一定为1,
以此类推,每个行校验的P都有一个对应的二进制位,暂时叫做特征位吧,
结合前面所说的“某行的行校验为1的时候,进行异或才能使行校验的值发生改变”,
可以得到reg3各位就是对应的行校验。
reg3保存的是p1024 ~ p8 的值
reg2保存的是p1024' ~ p8'的值
j是原始data的下标,也就是原始数据的行号,reg3 ^= (uchar) j;取的就是第几行的如果2,3行对应的是P16那么 对2,3取反 就是0,1 也就是P16' 呵呵,非常感谢了,经过你耐心指导~算法这块儿是明白一些了. 然后对照1BIT校验的其他的yaffs_ecc与wince ecc都是一样的.
然后在其余的一些时间里,看了S3C2410A的手册(中文第6章)关于nandflash控制器后,它的硬件ECC是512b校验1次,共3个字节, wince ecc是硬件ECC 算法是判断那几种情况就可以,比linux ecc要简单些.揭过不提.
nand_ecc 与 yaffs_ecc 从根本上就是一样的(个人认为)