📄 nand_flash_write.c
字号:
#include "./include/nand_flash_write.h"
#include "./include/led.h"
#include "./include/myout.h"
///////// flag bad block
static U32 NF_MarkBadBlock(U32 block)
{
int i;
char seBuf[6]={0};
U32 blockPage=(block<<5);
seBuf[0]=0xff;
seBuf[1]=0xff;
seBuf[2]=0xff;
seBuf[5]=0x44; // set bad block flag
NF_EN(); //nand chip select enable
NF_CMD(0x50); //from C feild start write
NF_CMD(0x80); //send program CMD
NF_ADDR(0x0); // A0~A7 (column address)
NF_ADDR(blockPage&0xff); // A9~A16 (page address and block address)
NF_ADDR((blockPage>>8)&0xff); // A17~a24 (block address)
NF_ADDR((blockPage>>16)&0xff); //A25 (block address)
// write OOB data block
for(i=0;i<16;i++)
{
NF_WRDATA(seBuf[i]);
}
NF_CMD(0x10); //end write CMD
// wait NandFlash ready ok
for(i=0;i<10;i++); // wait tWB=100ns
NF_WAITRB(); // busy wait
// read NandFlash's wtite status
NF_CMD(0x70);
for(i=0;i<3;i++); //twhr=60ns
if(NF_RDDATA()&0x1)
{
NF_DI(); // Nand Flash disable
return 0;
}else{
NF_DI(); // Nand Flash disable
}
return 1;
}
//////////check if bad block, if bad return 1, else return 0
U32 NF_IsBadBlock(U32 block)
{
int i;
U32 blockPage;
U8 data;
blockPage=(block<<5);
NF_EN(); //nand chip select enable
NF_CMD(0x50); // read OOB data block
NF_ADDR(517&0xf); // A0~A7 (column adrress)
NF_ADDR(blockPage&0xff); // A9~A16 (page address and block address)
NF_ADDR((blockPage>>8)&0xff); // A17~a24 (block address)
NF_ADDR((blockPage>>16)&0xff); //A25 (block address)
// wait nandflash readyok
for(i=0;i<10;i++); //wait tWB(100ns)
NF_WAITRB();
// get already read value
data=NF_RDDATA();
NF_DI(); // Nand Flash disable
// if data no 0xff , confirmation is bad block
if(data!=0xff)
return 1;
else
return 0;
}
/////////////// erase block return 0: erase error, flag 0 and return 0////
U32 NF_EraseBlock(U32 block)
{
U32 blockPage=(block<<5);
int i;
// if is bad block return 0
if(NF_IsBadBlock(block))
return 0;
NF_EN(); // Nand Flash enable
NF_CMD(0x60); // set erase mode
NF_ADDR(blockPage&0xff); //A9~A16, (Page Address), is erase block
NF_ADDR((blockPage>>8)&0xff); //A17~A24, (Page Address)
NF_ADDR((blockPage>>16)&0xff); //A25, (Page Address)
NF_CMD(0xd0); //send erase CMD ,start erase
/// wait NandFlash ready ok
for(i=0;i<10;i++); //tWB(100ns)
NF_WAITRB();
// read operat status
NF_CMD(0x70);
if (NF_RDDATA()&0x1)
{
NF_DI(); // Nand Flash disable
MyOut("\n\r erase error");
NF_MarkBadBlock(block); // flag bad block
return 0;
}else{
NF_DI(); // Nand Flash disable
return 1;
}
}
//////////////////////////// nandflash write/////////
U32 NF_WritePage(U32 block, U32 page, U8 *buffer)
{
int i;
U8 seBuf[6]={0};
U32 blockPage = (block<<5)+page, status;
U8 *bufPt = buffer;
NF_RSTECC(); // init ECC
//////////////// I modified here/////////////////////////
NFCONF |= 0x8000;
NF_EN();
NFCONF |=(NFCONF & ~0x777) | 0x33;
///////////////////////////////////////////////////////////
NF_CMD(0x0); // from A feild start write
NF_CMD(0x80); // write first CMD
NF_ADDR(0); // A0~A7 bit(Column Address)
NF_ADDR(blockPage&0xff); // A9~A16, (Page Address)
NF_ADDR((blockPage>>8)&0xff); //A17~A24, (Page Address)
NF_ADDR((blockPage>>16)&0xff); //A25,(Page Address)
NF_WAITRB();
for(i=0;i<512;i++)
{
NF_WRDATA(*bufPt++); // write one page(512 bytes) to Nand Flash
}
// OOB 一共 16 Bytes, 每一个字节存放什么由程序员自己定义, 通常,
// 我们在 Byte0Byte2 存 ECC 检验码. Byte6 存放坏块标志.
seBuf[0]=NFECC0; // get ECC check code 0
seBuf[1]=NFECC1; // get ECC check code 1
seBuf[2]=NFECC2; // get ECC check code 2
seBuf[5]=0xff; // negation bad block flag
for(i=0;i<16;i++)
{
NF_WRDATA(seBuf[i]); // write the page OOB data block
}
NF_CMD(0x10); // end write CMD
// wait Nand Flash, busy status
for(i=0;i<10;i++);
NF_WAITRB();
// send read status CMD to Nand Flash
NF_CMD(0x70);
for(i=0;i<3;i++);
if ((status=NF_RDDATA())&0x1)
{ // if write error ,flag bad block
NF_DI(); // Nand Flash disable
NF_MarkBadBlock(block);
return 0;
}else{ // exit
NF_DI(); // Nand Flash disable
return 1;
}
}
/////////////////////////////
void nand_write(U32 block, U32 fileSize, U8 *srcAddress)
{
int i;
int programError=0;
U32 blockIndex;
U8 *srcPt, *saveSrcPt;
srcPt=srcAddress; // file start address
blockIndex = block;
InitLed();
LedPlay(0x18);
while(1)
{
saveSrcPt=srcPt;
// if current block is bad block, jump current block
if(NF_IsBadBlock(blockIndex))
{
blockIndex++; // to next block
continue;
}
// before write, have to erase, if erase failed to jump current block
if(!NF_EraseBlock(blockIndex))
{
blockIndex++; // to next block
continue;
}
// write one block(totall 32 pages)
for(i=0;i<32;i++)
{
// write one page, if error to stop write current block
if(!NF_WritePage(blockIndex,i,srcPt))
{
programError=1;
break;
}
srcPt += 512;
if(srcPt>=(srcAddress+fileSize))
break;
}
// 如果写一个块时, 其中某一页写失败, 则把写地址恢复写该块之前, 并跳过当前块
if(programError==1)
{
blockIndex++;
srcPt=saveSrcPt;
programError=0;
continue;
}
// if write address smaller than file len, continue; or, stop write
if(srcPt >= (srcAddress + fileSize))
break;
// if write success , continue next block
blockIndex++;
}
while(1)
{
LedPlay(i++);
Delay(10);
}
}
//////////////////////////////////
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -