关闭

裸奔程序7(四)-NAND芯片的读写及ECC检验软硬件实现

944人阅读 评论(1) 收藏 举报

 ECC检验码

 

从结果可以看出,三次读取页数据,其检验码只有在第一次读取0页时正确,第二次读取1页时错误,第三次重读0页时生成的竞是第1页的ECC码,当时差点让人崩溃。

为了找到问题的症结所在,决定在读取页数据前先查看一下NFMECC0寄存器的值,重启系统调试发现,三次读取页数据前,其值如下:

NFMECC0=0xf0ffffff

NFMECC0=0x50969569

NFMECC0=0xf0c3fc33

经过分析发现当读取页数据结束并锁定ECC值时,NFMECC0的值为

NFMECC0=NFMECC0^(~页ECC码)

第一次读取为0XF0FFFFFF^(~0X50969569[页0ECC码])=0X50969569

第二次读取为0X50969569 ^(~0X50AA96A5[页1ECC码])=0XF0C3FC33

第三次赢取为0XF0C3FC33^(~0X50969569[页0ECC码])=0x50aa96a5

通过分析,我们得知,要想得到正确的页ECC码,显然,NFMECC0寄存器其值必须保持为0XF0FFFFFF

找到了问题的症结所在,并在对NFMECC0赋值无效的情况下,查找资料发现。


好了,在解开ECC寄存器之后,重新对NFCONT[4]位置1,NFMECC0寄存恢复原值0XF0FFFFFF,这样读取任意页均可得到正确的ECC码。

       在得到页ECC码的情况下,我们读取[2048~2051]得到写页数据时生成的ECC码

并将该值放入NFMECCD0/1两个寄存器的相关位置,这样S3C2440将自动对两个ECC码进行异或,并根据结果设置NFESTAT0寄存器。我们可以根据该寄存器的值来判断我们读取页数据是否成功。

       经程序调试发现,对NFMECCD0/1寄存器赋值必须一次完成,否则检验结果不正确。

NFESTAT0[1~0]位表示如下:

0 没有错误 1 一位错误可纠下 2不可纠下错误,3,ECC码错误

NFESTAT0[6~4]位表示错误字节错误位的列数

NFESTAT0[17~7]位表示错误字节的位置。

经过调试发现,其保存值均为反码,也就是说我们得到该位的值必须将其取反。
读取页数据其主要核心代码如下:
UN_MAINECC();
NF_RESTECC();                 //使NFMECC0寄存器值复原

       for(i=0;i<512;i++)             //pData为32位,一次读取4字节

       {

           pData=NF_DATA();

       }

       LOCK_MAINECC();

       Ecc_Data=NF_DATA();        //得到写生成时的ECC码        

       NF_nFCE_H();

       //对寄存器赋值必须一次写完,否则检验结果将不正确

       NF_MECCD0()=((Ecc_Data)&0xff)|((Ecc_Data<<8)&0xff0000);                  

       NF_MECCD1() =((Ecc_Data>>16)&0xff)|((Ecc_Data>>8)xff0000);      

       Ecc_Stat=NF_STAT0();

       if((Ecc_Stat&0x3)==0) return true;         //数据没有错误

       if((Ecc_Stat&0x3)==1)                   //一位数据错误,纠正该错误位

       {

              row=~((unsigned int)(Ecc_Stat>>7));  //取反

              row&=0x7ff;

              arr=~((unsigned int)(Ecc_Stat>>4));

              arr&=0x7;

              

              temp=((unsigned char *)pData)[row];

              if(((temp>>arr)&0x1)==1)

              {

                     temp&=(unsigned char)(~(1<<arr));

              }

              else {

                     temp|=(unsigned char)(1<<arr);

              }

              ((unsigned char *)pData)[row]=temp;            

              return true;

       }

体会:在对处围设置相关寄存器不同位赋值时,最好一次性完成,否则可能导致无法预测的结果。

0
0

查看评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
    个人资料
    • 访问:10006次
    • 积分:179
    • 等级:
    • 排名:千里之外
    • 原创:7篇
    • 转载:0篇
    • 译文:0篇
    • 评论:3条
    文章分类
    文章存档
    最新评论