2K Page NAND ECC说明

来源:互联网 发布:淘宝客服催单用语 编辑:程序博客网 时间:2024/05/20 20:02

2K Page K9K8G08 WritePage ReadPage  

static U32 WritePage(U32 addr, U8 *buf)

{
 U32 i, mecc, secc;
 U8 stat, tmp[6], value;
 
 addr &= ~0x3f;
 
 InitEcc();   //复位ECC
 MEccUnlock();   //解锁Main区ECC
 NFChipEn();   //打开nandflash片选
 WaitNFBusy();   //等待忙信号
 WrNFCmd(0x80);  //页写命令周期1
 
 WrNFAddr(0x00);  //列地址A0~A7
 WrNFAddr(0x00);  //列地址A8~A11
 WrNFAddr((addr>>0)& 0xFF); //行地址A12~A19
 WrNFAddr((addr>>8)& 0xFF); //行地址A20~A27
 WrNFAddr((addr>>16)& 0xFF); //行地址A28~A30
  
 for(i=0; i<2048; i++)
  WrNFDat(buf[i]); //写一页数据
 
 WaitNFBusy();   //等待忙信号
 MEccLock();   //锁定Main区的ECC校验码
 mecc = RdNFMEcc();  //读取Main区的ECC校验码

 //把Main区的ECC校验码由字型转换成字节型并保存到零时数组里
 tmp[0] = (U8)(mecc&0xff);  
 tmp[1] = (U8)((mecc>>8)&0xff);
 tmp[2] = (U8)((mecc>>16)&0xff);
 tmp[3] = (U8)((mecc>>24)&0xff);
    
 SEccUnlock();   //解锁Spare区的ECC
 
 //把Main区的ECC值写入到Spare区的前四个字节,即第2048~2051地址
 WrNFDat(tmp[0]);
 WrNFDat(tmp[1]);
 WrNFDat(tmp[2]);
 WrNFDat(tmp[3]);
 
 SEccLock();   //锁定Spare区的ECC校验码
 secc = RdNFSEcc();  //读取Spare区的ECC校验码
 
 //把Spare区的ECC校验码由字型转换成字节型并保存到零时数组里
 tmp[4] = (U8)(secc&0xff);
 tmp[5] = (U8)((secc>>8)&0xff);
 
 //把Spare区的ECC值写入到Spare区的第2052~2053地址
 WrNFDat(tmp[4]);
 WrNFDat(tmp[5]);
 
 WrNFCmd(0x10);  //页写命令周期2
 WaitNFBusy();   //等待忙信号
 WrNFCmd(0x70);  //写读状态命令
 WaitNFBusy();   //等待忙信号
 stat = RdNFDat();  //读取状态字
 NFChipDs();   //关闭nandflash片选
 if(stat&0x01)
 {
     MarkBadBlk(addr);  //标注坏块
     puts("WritePage Error!\n"); //写操作失败
     return 0;    //写操作失败
 }
 puts("WritePage No Error!\n"); //写操作成功
 return 1;    //写操作成功  
}

 

static void ReadPage(U32 addr, U8 *buf)
{
 U32 i, mecc, secc;
 
 addr &= ~0x3f;

 InitEcc();   //复位ECC
 MEccUnlock();   //解锁Main区ECC
 NFChipEn();   //打开nandflash片选
 WaitNFBusy();   //等待忙信号 
 WrNFCmd(0x00);  //页读命令周期1

 WrNFAddr(0x00);  //列地址A0~A7
 WrNFAddr(0x00);  //列地址A8~A11
 WrNFAddr((addr>>0)& 0xFF); //行地址A12~A19
 WrNFAddr((addr>>8)& 0xFF); //行地址A20~A27
 WrNFAddr((addr>>16)& 0xFF); //行地址A28~A30
 
 WrNFCmd(0x30);  //页读命令周期2
 WaitNFBusy();   //等待忙信号
 
 for(i=0; i<2048; i++)
  buf[i] = RdNFDat(); //读取一页数据
 WaitNFBusy();   //等待忙信号

 MEccLock();   //锁定main区的ECC值

 SEccUnlock();   //解锁spare区的ECC值
 
 mecc = RdNFDat32();  //读取spare区的前4个地址内容,即2048~2051,这四个字节是main区的ECC值 
 buf[i+1] =  (U8)(mecc & 0xff);  //把读取到的main区的ECC校验码放入到零时数组里
 buf[i+2] =  (U8)((mecc>>8) & 0xff); //把读取到的main区的ECC校验码放入到零时数组里
 buf[i+3] =  (U8)((mecc>>16) & 0xff); //把读取到的main区的ECC校验码放入到零时数组里
 buf[i+4] =  (U8)((mecc>>24) & 0xff); //把读取到的main区的ECC校验码放入到零时数组里

 //把读取到的main区的ECC校验码放入到NFMECCD0/1的相应位置   
 rNFMECCD0 =  ((mecc&0xff00)<<8)|(mecc&0xff);
 rNFMECCD1 =  ((mecc&0xff000000)>>8)|((mecc&0xff0000)>>16);
 
 SEccLock();  //锁定spare区的ECC值
 
 secc = RdNFDat32(); //读取spare区的4个地址内容,即2052~2055,其中前两个字节是spare区的ECC值
 
 buf[i+5] = (U8)(secc & 0xff);   //把读取到的spare区的ECC校验码放入到零时数组里
 buf[i+6] = (U8)((secc>>8) & 0xff);   //把读取到的spare区的ECC校验码放入到零时数组里
 buf[i+7] = (U8)((secc>>16) & 0xff);  //把读取到的spare区的ECC校验码放入到零时数组里
 buf[i+8] = (U8)((secc>>24) & 0xff);  //把读取到的spare区的ECC校验码放入到零时数组里
 rNFSECCD = ((secc&0xff00)<<8)|(secc&0xff); //把读取到的spare区的ECC校验码放入到NFSECCD的相应位置   
 
 NFChipDs();    //关闭nandflash片选
 
 if(((rNFESTAT0)&0x0f)==0)  //判断main data area 和 spear date area 是否有bit位出错
  puts("ECC No Error!\n"); //有ECC错误
 else
  puts("ECC Error!\n"); //没有ECC错误
 puts("0x%8x\n",(rNFESTAT0)); //显示读到的rNFESTAT0寄存器
}

0 0