转自http://autoelec.blog.sohu.com/75529864.html
nand flash芯片是k9f1208,它的读写操作、包括块擦除函数如下所示:
//addr = page address 参数addr是页对齐的地址,每个页是512个字节
U32 EraseBlock(U32 addr)
{
U8 stat;
addr &= ~0x1f;
NFChipEn();
WrNFCmd(ERASECMD0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
WrNFCmd(ERASECMD1);
stat = WaitNFBusy();
NFChipDs();
#ifdef ER_BAD_BLK_TEST
if(!((addr+0xe0)&0xff)) stat = 1; //just for test bad block
#endif
//printf("Erase block 0x%x %s\n", addr, stat?"fail":"ok");
putch('.');
return stat;
}
//addr = page address
void ReadPage(U32 addr, U8*buf)
{
U16 i;
//printf("read page %x",addr);
NFChipEn();
WrNFCmd(READCMD0);
WrNFAddr(0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
InitEcc();
WaitNFBusy();
for(i=0; i<512; i++)
buf = RdNFDat();
NFChipDs();
}
void ReadSpare(U32 addr, U8*buf)
{
//U8 dat;
U8 i;
//printf("read spare %x",addr);
//addr &= ~0x1f;
NFChipEn();
WrNFCmd(READCMD2); //point to area c
WrNFAddr(0); //mark offset 0~15
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
WaitNFBusy();
for(i=0;i<16;i++){
buf = RdNFDat();
}
WrNFCmd(READCMD0); //point to area a
NFChipDs();
//return (dat!=0xff);
}
写页内容的函数,除了对512个字节操作以外,还对于16个spare的字节做了操作,可以根据自己的要求决定是否包含对spare的操作。
U32 WritePage(U32 addr, const U8 *buf, U16 blk_idx)
{
U16 i;
U8 stat;
U8 ecc_code[3];
U8 oob_info[16];
//printf("write page %x",addr);
for(i=0; i<sizeof(oob_info); i++)
oob_info = 0xff;
nand_calculate_ecc(buf, ecc_code);
oob_info[eccpos[0]] = ecc_code[0];
oob_info[eccpos[1]] = ecc_code[1];
oob_info[eccpos[2]] = ecc_code[2];
nand_calculate_ecc(buf+256, ecc_code);
oob_info[eccpos[3]] = ecc_code[0];
oob_info[eccpos[4]] = ecc_code[1];
oob_info[eccpos[5]] = ecc_code[2];
oob_info[BLK_IDXL] = blk_idx;
oob_info[BLK_IDXH] = blk_idx>>8;
oob_info[FMT_TAG] = format_tags[addr&0x1f];
NFChipEn();
WrNFCmd(PROGCMD0);
WrNFAddr(0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
// InitEcc();
for(i=0; i<512; i++)
WrNFDat(buf);
/*if(!addr) {
WrNFDat('b');
WrNFDat('o');
WrNFDat('o');
WrNFDat('t');
} else {
for(i=0; i<sizeof(oob_info); i++)
WrNFDat(oob_info);
}*/
/* tmp[0] = rNFECC0;
tmp[1] = rNFECC1;
tmp[2] = rNFECC2;
WrNFDat(tmp[0]);
WrNFDat(tmp[1]);
WrNFDat(tmp[2]);
*/
WrNFCmd(PROGCMD1);
stat = WaitNFBusy();
NFChipDs();
#ifdef WR_BAD_BLK_TEST
if((addr&0xff)==0x17) stat = 1; //just for test bad block
#endif
if(stat)
printf("Write nand flash 0x%x fail\n", addr);
else {
U8 RdDat[512];
ReadPage(addr, RdDat);
for(i=0; i<512; i++)
if(RdDat!=buf) {
printf("Check data at page 0x%x, offset 0x%x fail\n", addr, i);
stat = 1;
break;
}
}
return stat;
}
void WriteSpare(U32 addr,const U8* buf)
{
int i;
//addr &= ~0x1f;
//printf("write spare %x",addr);
NFChipEn();
WrNFCmd(READCMD2); //point to area c
WrNFCmd(PROGCMD0);
WrNFAddr(0); //mark offset 0
WrNFAddr(addr);
WrNFAddr(addr>>8);
if(NandAddr)
WrNFAddr(addr>>16);
for(i=0;i<16;i++){
WrNFDat(buf);
}
//WrNFDat(0); //mark with 0
//WrNFDat(0);
//WrNFDat(0); //mark with 0
//WrNFDat(0);
WrNFCmd(PROGCMD1);
WaitNFBusy(); //needn't check return status
WrNFCmd(READCMD0); //point to area a
NFChipDs();
}
有关READDCMD0等的定义,可以参考k9f1208的用户手册。
文章评论(0条评论)
登录后参与讨论