共2条
1/1 1 跳转至页
nand,flash,ecc nand flash ecc校验

问
周工或者各路大侠,哪位有nand flash ecc校验的算法? 先谢谢!! 答 1: yaffs就有 答 2: Ecc校验的修复有问题我对于ecc的理解是:
在写nand时,需要计算ecc校验码,并存入空闲区,这样页编程之后不必读出数据校验,
但是执行读操作后,需要再次计算ecc码,如果1位有错误,则可进行修复,不必替换了。但是在修复过程中必须更改1位。如将1 改为0,可以编程一次,如将0 改为1,nandflash怎么修改?一般是通过擦除操作。可能还是需要执行块的替换。
这地方小弟还不明白,大家怎么校验的? 答 3: 看一下yaffs关于ecc的源码就清楚了还是给你贴出来吧
CONST BYTE EccTable[] = {
0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
};
LONG EccCountBits(BYTE x)
{
LONG r = 0;
while(x)
{
if(x & 1) r++;
x >>= 1;
}
return r;
}
/*********************************************************************************************************
** 函数名称: ECCCal
** 功能描述: 产生ecc效验
**
** 输 入: Data : 要效验的数据首地址
** CurEcc : 存放ecc效验的首地址
**
** 输 出: 无
**
** 全局变量: 无
** 调用模块: 无
**
** 日 期: 2006.1.20
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void ECCCal(BYTE *Data,BYTE *CurEcc)
{
LONG i;
BYTE col_parity = 0;
BYTE line_parity = 0;
BYTE line_parity_prime = 0;
BYTE t;
BYTE b;
for(i = 0; i < 256; i++)
{
b = EccTable[*Data++];
col_parity ^= b;
if(b & 0x01)
{
line_parity ^= i;
line_parity_prime ^= ~i;
}
}
CurEcc[2] = (~col_parity) | 0x03;
t = 0;
if(line_parity & 0x80) t |= 0x80;
if(line_parity_prime & 0x80) t |= 0x40;
if(line_parity & 0x40) t |= 0x20;
if(line_parity_prime & 0x40) t |= 0x10;
if(line_parity & 0x20) t |= 0x08;
if(line_parity_prime & 0x20) t |= 0x04;
if(line_parity & 0x10) t |= 0x02;
if(line_parity_prime & 0x10) t |= 0x01;
CurEcc[1] = ~t;
t = 0;
if(line_parity & 0x08) t |= 0x80;
if(line_parity_prime & 0x08) t |= 0x40;
if(line_parity & 0x04) t |= 0x20;
if(line_parity_prime & 0x04) t |= 0x10;
if(line_parity & 0x02) t |= 0x08;
if(line_parity_prime & 0x02) t |= 0x04;
if(line_parity & 0x01) t |= 0x02;
if(line_parity_prime & 0x01) t |= 0x01;
CurEcc[0] = ~t;
t = CurEcc[0];
CurEcc[0] = CurEcc[1];
CurEcc[1] = t;
}
/*********************************************************************************************************
** 函数名称: ECCChk
** 功能描述: ecc检测
**
** 输 入: Data : 检测的数据
** OldEcc : 之前效验的ecc
**
** 输 出: ECC_OK : 正确
** ECC_DATA_FIXED : 数据被修正
** ECC_ECC_ERR : 之前效验的ecc是错误的
** ECC_DATA_UNFIXED : 数据无法恢复
**
** 全局变量: 无
** 调用模块: ECCCal, EccCountBits
**
** 日 期: 2006.1.20
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
BYTE ECCChk(BYTE *Data, BYTE *OldEcc)
{
BYTE d0, d1, d2;
BYTE NewEcc[3];
ECCCal(Data,NewEcc);
d0 = OldEcc[0] ^ NewEcc[0];
d1 = OldEcc[1] ^ NewEcc[1];
d2 = OldEcc[2] ^ NewEcc[2];
if((d0 | d1 | d2) == 0)
{
return ECC_OK;
}
if( ((d0 ^ (d0 >> 1)) & 0x55) == 0x55 )
if( ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 )
if( ((d2 ^ (d2 >> 1)) & 0x54) == 0x54 )
{
unsigned byte;
unsigned bit;
BYTE t;
t = d0;
d0 = d1;
d1 = t;
bit = byte = 0;
if(d1 & 0x80) byte |= 0x80;
if(d1 & 0x20) byte |= 0x40;
if(d1 & 0x08) byte |= 0x20;
if(d1 & 0x02) byte |= 0x10;
if(d0 & 0x80) byte |= 0x08;
if(d0 & 0x20) byte |= 0x04;
if(d0 & 0x08) byte |= 0x02;
if(d0 & 0x02) byte |= 0x01;
if(d2 & 0x80) bit |= 0x04;
if(d2 & 0x20) bit |= 0x02;
if(d2 & 0x08) bit |= 0x01;
Data[byte] ^= (1 << bit);
return ECC_DATA_FIXED;
}
if((EccCountBits(d0)+EccCountBits(d1)+EccCountBits(d2)) == 1)
{
return ECC_ECC_ERR;
}
else
{
return ECC_DATA_UNFIXED;
}
}
答 4: thanks原来是在ram中修改,或是给出报错。谢谢 eleven11。 答 5: 三星的网站上有ecc校验的源码与方法 答 6: eleven11,谢谢你!我正在找ECC的资料! 答 7: 我以前都是用写-读-比较的方式了事。
周工或者各路大侠,哪位有nand flash ecc校验的算法? 先谢谢!! 答 1: yaffs就有 答 2: Ecc校验的修复有问题我对于ecc的理解是:
在写nand时,需要计算ecc校验码,并存入空闲区,这样页编程之后不必读出数据校验,
但是执行读操作后,需要再次计算ecc码,如果1位有错误,则可进行修复,不必替换了。但是在修复过程中必须更改1位。如将1 改为0,可以编程一次,如将0 改为1,nandflash怎么修改?一般是通过擦除操作。可能还是需要执行块的替换。
这地方小弟还不明白,大家怎么校验的? 答 3: 看一下yaffs关于ecc的源码就清楚了还是给你贴出来吧
CONST BYTE EccTable[] = {
0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
0xa9, 0xfc, 0xf0, 0xa5, 0xcc, 0x99, 0x95, 0xc0, 0xc0, 0x95, 0x99, 0xcc, 0xa5, 0xf0, 0xfc, 0xa9,
0x3c, 0x69, 0x65, 0x30, 0x59, 0x0c, 0x00, 0x55, 0x55, 0x00, 0x0c, 0x59, 0x30, 0x65, 0x69, 0x3c,
0x30, 0x65, 0x69, 0x3c, 0x55, 0x00, 0x0c, 0x59, 0x59, 0x0c, 0x00, 0x55, 0x3c, 0x69, 0x65, 0x30,
0xa5, 0xf0, 0xfc, 0xa9, 0xc0, 0x95, 0x99, 0xcc, 0xcc, 0x99, 0x95, 0xc0, 0xa9, 0xfc, 0xf0, 0xa5,
0x0c, 0x59, 0x55, 0x00, 0x69, 0x3c, 0x30, 0x65, 0x65, 0x30, 0x3c, 0x69, 0x00, 0x55, 0x59, 0x0c,
0x99, 0xcc, 0xc0, 0x95, 0xfc, 0xa9, 0xa5, 0xf0, 0xf0, 0xa5, 0xa9, 0xfc, 0x95, 0xc0, 0xcc, 0x99,
0x95, 0xc0, 0xcc, 0x99, 0xf0, 0xa5, 0xa9, 0xfc, 0xfc, 0xa9, 0xa5, 0xf0, 0x99, 0xcc, 0xc0, 0x95,
0x00, 0x55, 0x59, 0x0c, 0x65, 0x30, 0x3c, 0x69, 0x69, 0x3c, 0x30, 0x65, 0x0c, 0x59, 0x55, 0x00,
};
LONG EccCountBits(BYTE x)
{
LONG r = 0;
while(x)
{
if(x & 1) r++;
x >>= 1;
}
return r;
}
/*********************************************************************************************************
** 函数名称: ECCCal
** 功能描述: 产生ecc效验
**
** 输 入: Data : 要效验的数据首地址
** CurEcc : 存放ecc效验的首地址
**
** 输 出: 无
**
** 全局变量: 无
** 调用模块: 无
**
** 日 期: 2006.1.20
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
void ECCCal(BYTE *Data,BYTE *CurEcc)
{
LONG i;
BYTE col_parity = 0;
BYTE line_parity = 0;
BYTE line_parity_prime = 0;
BYTE t;
BYTE b;
for(i = 0; i < 256; i++)
{
b = EccTable[*Data++];
col_parity ^= b;
if(b & 0x01)
{
line_parity ^= i;
line_parity_prime ^= ~i;
}
}
CurEcc[2] = (~col_parity) | 0x03;
t = 0;
if(line_parity & 0x80) t |= 0x80;
if(line_parity_prime & 0x80) t |= 0x40;
if(line_parity & 0x40) t |= 0x20;
if(line_parity_prime & 0x40) t |= 0x10;
if(line_parity & 0x20) t |= 0x08;
if(line_parity_prime & 0x20) t |= 0x04;
if(line_parity & 0x10) t |= 0x02;
if(line_parity_prime & 0x10) t |= 0x01;
CurEcc[1] = ~t;
t = 0;
if(line_parity & 0x08) t |= 0x80;
if(line_parity_prime & 0x08) t |= 0x40;
if(line_parity & 0x04) t |= 0x20;
if(line_parity_prime & 0x04) t |= 0x10;
if(line_parity & 0x02) t |= 0x08;
if(line_parity_prime & 0x02) t |= 0x04;
if(line_parity & 0x01) t |= 0x02;
if(line_parity_prime & 0x01) t |= 0x01;
CurEcc[0] = ~t;
t = CurEcc[0];
CurEcc[0] = CurEcc[1];
CurEcc[1] = t;
}
/*********************************************************************************************************
** 函数名称: ECCChk
** 功能描述: ecc检测
**
** 输 入: Data : 检测的数据
** OldEcc : 之前效验的ecc
**
** 输 出: ECC_OK : 正确
** ECC_DATA_FIXED : 数据被修正
** ECC_ECC_ERR : 之前效验的ecc是错误的
** ECC_DATA_UNFIXED : 数据无法恢复
**
** 全局变量: 无
** 调用模块: ECCCal, EccCountBits
**
** 日 期: 2006.1.20
**-------------------------------------------------------------------------------------------------------
********************************************************************************************************/
BYTE ECCChk(BYTE *Data, BYTE *OldEcc)
{
BYTE d0, d1, d2;
BYTE NewEcc[3];
ECCCal(Data,NewEcc);
d0 = OldEcc[0] ^ NewEcc[0];
d1 = OldEcc[1] ^ NewEcc[1];
d2 = OldEcc[2] ^ NewEcc[2];
if((d0 | d1 | d2) == 0)
{
return ECC_OK;
}
if( ((d0 ^ (d0 >> 1)) & 0x55) == 0x55 )
if( ((d1 ^ (d1 >> 1)) & 0x55) == 0x55 )
if( ((d2 ^ (d2 >> 1)) & 0x54) == 0x54 )
{
unsigned byte;
unsigned bit;
BYTE t;
t = d0;
d0 = d1;
d1 = t;
bit = byte = 0;
if(d1 & 0x80) byte |= 0x80;
if(d1 & 0x20) byte |= 0x40;
if(d1 & 0x08) byte |= 0x20;
if(d1 & 0x02) byte |= 0x10;
if(d0 & 0x80) byte |= 0x08;
if(d0 & 0x20) byte |= 0x04;
if(d0 & 0x08) byte |= 0x02;
if(d0 & 0x02) byte |= 0x01;
if(d2 & 0x80) bit |= 0x04;
if(d2 & 0x20) bit |= 0x02;
if(d2 & 0x08) bit |= 0x01;
Data[byte] ^= (1 << bit);
return ECC_DATA_FIXED;
}
if((EccCountBits(d0)+EccCountBits(d1)+EccCountBits(d2)) == 1)
{
return ECC_ECC_ERR;
}
else
{
return ECC_DATA_UNFIXED;
}
}
答 4: thanks原来是在ram中修改,或是给出报错。谢谢 eleven11。 答 5: 三星的网站上有ecc校验的源码与方法 答 6: eleven11,谢谢你!我正在找ECC的资料! 答 7: 我以前都是用写-读-比较的方式了事。
共2条
1/1 1 跳转至页
回复
打赏帖 | |
---|---|
【STM32F769】AI之与本地deepseek对接被打赏50分 | |
Buck电路工作在CCM模式下电感电流的计算公式是什么?被打赏5分 | |
buck电路工作原理被打赏5分 | |
基于MSPM0L1306的MODBUS-RTU协议通讯实验被打赏100分 | |
我想要一部加热台+多合一调试工具被打赏18分 | |
每周了解几个硬件知识+485硬件知识分享被打赏10分 | |
【换取手持数字示波器】树莓派PICO调试器官方固件本地化部署实践被打赏24分 | |
【换取手持数字示波器】分享一个KEIL无法识别CMSIS-DAP调试器的解决办法被打赏20分 | |
【换取手持数字示波器】分享一个自制的ArduinoNano扩展板底板被打赏23分 | |
【换取手持示波器】树莓派PICOW网页烟花被打赏18分 |