打印
[应用相关]

STM32 ECC校验的一些心得

[复制链接]
1833|10
手机看帖
扫描二维码
随时随地手机跟帖
跳转到指定楼层
楼主
litengg|  楼主 | 2016-10-25 19:08 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
比如我要使用ECC功能,每512个字节产生一个ECC数据,这样,当这512字节里出错有一位错误的时候,可以通过ECC来纠正。当然,如果错了几个位,就无法纠错了。虽然当两个位有错,也知道,但不知道是哪两个位出错,也纠正不了。所以,只要关心怎么找出错误,通过ECC怎么纠错。
FSMC的ECC支持每256字节,512字节,1024,。。。8192字节产生一个ECC数据。
调试时使用每512字节产生一个ECC功能。
当写入512个字节时,产生一个ECC数据,然后,再读512个字节的时候,也会产生一个ECC数据,通过这两个数据相异或,产生一个ECC校验结果,通过这个判断结果,就可以分析出有没有错,错在哪里,是错哪一位。当然,知道哪一位错了,也就可以纠正了。

现在具体以实际的NAND_FLASH为例。
K9F2G08U0C这个芯片虽然是每页2048个字节,也就是4 个512字节。按理说直接使用每2048字节产生一个ECC即可校验,这样也方便一些。但因为实际使用中,是把这FLASH当作U盘来使用,并使用了fat32文件系统,将其作扇区处理了。一般扇区单位为512个字节。因此,这里就使用每512个字节产生一个ECC。

FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND;
  FSMC_NANDInitStructure.FSMC_Waitfeature =FSMC_Waitfeature_Enable;
  FSMC_NANDInitStructure.FSMC_MemoryDataWidth =FSMC_MemoryDataWidth_8b;
  FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable;
FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;
  FSMC_NANDInitStructure.FSMC_AddressLowMapping= FSMC_AddressLowMapping_Direct;
  FSMC_NANDInitStructure.FSMC_TCLRSetupTime =0x00;
  FSMC_NANDInitStructure.FSMC_TARSetupTime =0x00;
FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
  FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct= &p;

  FSMC_NANDInit(&FSMC_NANDInitStructure);

  /* FSMC NAND Bank Cmd Test */
  FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);

  初始化主要为上述几句指令:
FSMC_NANDInitStructure.FSMC_ECC =FSMC_ECC_Enable;
FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;

  然后在读写NAND_FLASH,即可读到ECC数据。

u32 write_ecc;
u32 read_ecc;
for(i=0;i<512;i++)
{
    buffer[i]=i%256;
}

    FSMC_NANDECCCmd(FSMC_Bank2_NAND,ENABLE);
    FSMC_NAND_WritePage(buffer,0,512);
  while(FSMC_GetFlagStatus(FSMC_Bank2_NAND,FSMC_FLAG_FEMPT)==Bit_RESET);
   write_ecc = FSMC_GetECC(FSMC_Bank2_NAND);
   FSMC_NANDECCCmd(FSMC_Bank2_NAND,DISABLE);
//这是写入512个字节时候读ECC.

    FSMC_NANDECCCmd(FSMC_Bank2_NAND,ENABLE);
         FSMC_NAND_ReadPage(read,0,512);
   while(FSMC_GetFlagStatus(FSMC_Bank2_NAND,FSMC_FLAG_FEMPT)==Bit_RESET);
    read_ecc = FSMC_GetECC(FSMC_Bank2_NAND);
    FSMC_NANDECCCmd(FSMC_Bank2_NAND,DISABLE);
//这是读512个时候读取ECC
  
要保证读取到正确的ECC数据,要在读之前先失能下ECC功能,把ECC数据清零,再使用ECC,然后再读或写NAND_FLASH。再读到相应的ECC。读ECC后记得把ECC失能,以清空ECC数据。
   这样就可以读到write_ecc了。当然,这个数据会读到的是0,为什么呢,所以很多时候我们测试数据,都是用比较有规律的数据去测试,下面通过几组数据,来解读下这个ECC的数据分析
for(i=0;i<512;i++)
  {
    buffer[i]=0x11;
  }
ECC: 0


512个字节里,都是0x11的话,ECC数据是0。然后改变其中某个字节的某个位,再去读ECC看。
for(i=0;i<512;i++)
  {
    buffer[i]=0x11;
  }
buffer [0]=0x10;
ECC: 0x55555555
这是改了第一个字节的第一个位。(但习惯上从0开始比较习惯,改了第0个字节第0个位)
for(i=0;i<512;i++)
  {
    buffer[i]=0x11;
  }
buffer [0]=0x13;
ECC:0x55555556
改了第1个位


for(i=0;i<2048;i++)
  {
    buffer[i]=0x11;
  }
buffer [0]=0x15;
ECC:0x55555559
改了第2个位


for(i=0;i<2048;i++)
  {
    buffer[i]=0x11;
  }
buffer [0]=0x19;
ECC:0x5555555a




for(i=0;i<512;i++)
  {
    buffer[i]=0x11;
  }
buffer [511]=0x91;
ECC:0x55aaaaaa;
这里改了第4095个位,也就是(第511个字节的最高位,也就是512个字节里的最高一个位)

好了,有了以上这里数据,就可以开始解读了,就算找不到例子,只要你的NAND_FLASH读写正常了,能把这些看懂了,也就可以使用ECC功能了。

下面对这几个ECC数据进行解读。

解读前先看一下ECC结果寄存器。

   因为我们设置的是512个字节产生一个ECC。那么有效位是0到23。
也就是前面读到的ECC数据呢,只要低24位就可以了。
当然,从这里还能看出其它数据。最高是8192字节,占了32位,
4096字节占了30位。
这个规律就是从256字节开始,每增一倍字节数,ECC就多占用两个位。
按常理说,只要多一个位,就可以表示多一倍的数据了。但是要表示多一个数据,需要到两个位,那,这里就有点玄机了。
甚至不需要去理解或弄明白它使用是汉明码,什么BCH码,只要看明白下这里,一直可以纠错。因为,不要管它是什么纠错码,就跟着这个规律去理解。
512个字节的ECC用了24位,512个字节共有512*8=4096个位。要表示到4096个数,也就是刚好12位就可以了。所以,因此这里的玄机就是ECC数据里,用了2个位来表示一个位的数据。
这时,再看一下关于STM32 ECC的介绍。
When an erroroccurs during the write operation, this error is either correctable or
uncorrectabledepending on the ECC XOR operation:
● Case of acorrectable error
The ECC XORoperation contains 11-bit data at 1. And each pair parity is 0x10 or
0x01.

忘了说,我们这些测试数据呢,是以写入0x11为主,然后故意改错某一个位,再读出ECC。因为写入全部的是0x11,因此写入时产生的ECC是0x0。那么再将读出来的ECC与0x0异或,得到的,也就是ECC校验结果了。
当错第0个位的时候,校验结果是0x55555555。取低24位,也就是0x555555。

对应24位就是
010101010101010101010101
当错第1个位的时候,校验结果是0x555556(取低24位)
对应24位就是
010101010101010101010110
当错第2个位对应的24位是:
010101010101010101011001
当错第3个位对应的24位是:
010101010101010101011010
…………
当错第4095个位(也就是第511个字节的最高位) 校验结果:0xaaaaaa。
对应24位是:
101010101010101010101010

看到这里,大家估计很容易看出来规律了。
第0个位错误的24位数据解码出来12位就是:0000 00000000,也就是0x0,就是第0个位错误.
第1个位错误的24位数据解码出来12位就是:0000 00000001,也就是0x1,就是第1个位错误.
第2个位错误的24位数据解码出来12位就是:0000 00000010,也就是0x2,就是第2个位错误.
第3个位错误的24位数据解码出来12位就是:0000 00000011,也就是0x3,就是第3个错误.
第4095个位错误的24位数据解码出来12位就是:1111 11111111,也就是0xfff,就是第4095个位错误.

到了这一步,不知道有没有明白纠正原理呢。当知道是哪一个是错误的了,剩下的就简单了,就把错误的那一位把0变成1,或者把1变成0就行了。
可以写成一个函数,ecc_data为校验结果。

intcheck_ecc(u32 ecc_data)
{
  u32 temp;
  int i;
  u8 data4;
  u32 location=0;
  temp=ecc_data&0xffffff;//只要24位


  for(i=0;i<24/2;i++)
    {
     data4=(temp>>(i*2))&0x3;
     if(data4==0x01)
        {
        // 如果两位是0x01,则判断是0
        }
     else if(data4==0x02)
        {
         // 1 如果两个是0x10,则判断是1
         location|=(1<<i);
        }
     else
        {
        // 如果不是两种其一,刚说明无法纠错
                   // 既然无法纠错,其它的,就暂时不关心了
         return -1;
        }
     printf("location:%d..\r\n",location);

    }
  return location;

}
沙发
qiangweii| | 2016-10-25 19:08 | 只看该作者
如果校验结果为0x00的时候,说明读出来的数据是对的。不需要调用这个函数了。调用这个函数时,就可以返回错误的位置。

使用特权

评论回复
板凳
shashaa| | 2016-10-25 19:14 | 只看该作者
ECC的功能的调试感觉还算比好容易理解。

使用特权

评论回复
地板
wanglaojii| | 2016-10-25 19:15 | 只看该作者
ECC功能调试好了,剩下的,就是把那一位纠错出来就好了。

使用特权

评论回复
5
laozhongyi| | 2016-10-25 19:35 | 只看该作者
重要的ECC校验结果出来了,知道是哪一位错误了,剩下的还不好办了啊。

使用特权

评论回复
6
Edisons| | 2016-10-25 19:37 | 只看该作者
只要在写入的时候,把ECC相应地存入到OOB区,然后在读NAND_FLASH的时候,再读新的ECC数据,和之前写入到OOB里的ECC进行异或,得到ECC校验结果。

使用特权

评论回复
7
_gege| | 2016-10-25 19:44 | 只看该作者
一些心得

STM32 ECC调试及心得.zip

385.02 KB

使用特权

评论回复
8
Mozarts| | 2016-10-25 19:45 | 只看该作者
STM32 ECC校验的一些心得,多谢分享。

使用特权

评论回复
9
litengg|  楼主 | 2016-10-25 19:59 | 只看该作者
shashaa 发表于 2016-10-25 19:14
ECC的功能的调试感觉还算比好容易理解。

STM32的FSMC功能支持SRAM,NOR FLASH,NAND FLASH,是非常方便的。
当然,要STM32F103VC及以上的芯片才支持FSMC功能的。

使用特权

评论回复
10
Listate| | 2016-10-25 20:00 | 只看该作者
ECC校验的一些心得,大家一起交流学习。

使用特权

评论回复
11
heisexingqisi| | 2016-10-25 23:07 | 只看该作者
ECC是“Error Correcting Code”的简写,中文名称是“错误检查和纠正”。

使用特权

评论回复
发新帖 我要提问
您需要登录后才可以回帖 登录 | 注册

本版积分规则

51

主题

1597

帖子

4

粉丝