对NAND FLASH 读写操作代码地址问题的注释解读

时间:2021-08-06 17:29:25
/*
本实验接口说明
*/
#include "include.h"

/*-----------------------函数声明----------------------------*/
void InitNandFlash(int info);
void cpy_bpage(void);
void add_bpage(unsigned int seq);

extern void Uart_Printf(char *fmt,...);
extern void Uart_Init(int baud);
extern void Uart_Select(int ch);

/*------------------------------------------------------------/
函数名称:InitNandCfg
功能描述:配置flash
传 参:无
返 回 值:无
-------------------------------------------------------------*/
static void InitNandCfg(void)
{

rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
}

/*------------------------------------------------------------/
函数名称:WaitNFBusy
功能描述:
传 参:无
返 回 值:static U32 stat&1
-------------------------------------------------------------*/
static U32 WaitNFBusy(void)// R/B 未接好?
{
U8 stat;

WrNFCmd(QUERYCMD);
do
{
stat = RdNFDat();
}
while (!(stat&0x40));
WrNFCmd(READCMD0);
return stat&1; //注意0为操作成功
}

/*------------------------------------------------------------/
函数名称:ReadChipId
功能描述:读flash ID
传 参:无
返 回 值:static U32 id
-------------------------------------------------------------*/
static U32 ReadChipId(void)
{
U32 id,k;

NFChipEn();//使能片选
WrNFCmd(RdIDCMD);//存储器命令值0x09 (1001)
WrNFAddr(0);//NAND Flash 存储器地址值 写0
while(NFIsBusy());//NAND Flash 运行状态寄存器 若忙碌 则等待
id = RdNFDat()<<8;//字节访问 8位
for(k=0;k<500;k++);
id |= RdNFDat();
NFChipDs();//失能片选

return id;
}

/*------------------------------------------------------------/
函数名称:ReadStatus
功能描述:读FLASH状态
传 参:无
返 回 值:static U16 stat
-------------------------------------------------------------*/
static U16 ReadStatus(void)
{
U16 stat;

NFChipEn();
WrNFCmd(QUERYCMD);
stat = RdNFDat();
NFChipDs();

return stat;
}

/*------------------------------------------------------------/
函数名称:EraseBlock
功能描述:擦除 FLASH
传 参:U32 addr
返 回 值:U32 ~stat
-------------------------------------------------------------*/
U32 EraseBlock(U32 addr)
{
U8 stat;

addr &= ~0x3f;//找出需要擦除页所在块的起始页 擦除整个块block

NFChipEn();
WrNFCmd(ERASECMD0);//写地址命令需要写两次命令 ERASECMD0\ERASECMD1 见NAND FLASH DATASHEET
WrNFAddr(addr); //这两行写地址代码,传送地址数据,本应该是 5个cycle 这里只用了前两个cycle 足以。
WrNFAddr(addr>>8);

WrNFCmd(ERASECMD1);
stat = WaitNFBusy();
NFChipDs();

return ~stat;
}

/*------------------------------------------------------------/
函数名称:ReadPage
功能描述:
传 参:U32 addr, U8 *buf
返 回 值:无
-------------------------------------------------------------*/
void ReadPage(U32 addr, U8 *buf)
{
U16 i;

NFChipEn();
WrNFCmd(READCMD0);
WrNFAddr(0);//前两个周期行地址cloumn写0
WrNFAddr(0);
WrNFAddr(addr);//后三个周期列地址row写页码(页码就是列地址)
WrNFAddr(addr>>8);
WrNFCmd(READCMD1);
InitEcc();
WaitNFBusy();
for(i=0; i<2048; i++)
buf[i] = RdNFDat();
NFChipDs();
}

/*------------------------------------------------------------/
函数名称:WritePage
功能描述:
传 参:U32 addr, U8 *buf
返 回 值:U32 ~stat
-------------------------------------------------------------*/
U32 WritePage(U32 addr, U8 *buf)
{
U32 i, mecc;
U8 stat, tmp[7];


NFChipEn();
WrNFCmd(PROGCMD0);
WrNFAddr(0);
WrNFAddr(0);
WrNFAddr(addr);
WrNFAddr(addr>>8);

InitEcc();//reset mecc and secc
MEccUnlock();
for(i=0; i<512; i++)
WrNFDat(buf[i]);
MEccLock();

mecc = RdNFMEcc());

tmp[0] = mecc&0xff;
tmp[1] = (mecc>>8)&0xff;
tmp[2] = (mecc>>16)&0xff;
tmp[3] = (mecc>>24)&0xff;
tmp[5] = 0xff;//mark good block



WrNFDat(0xff);//2048,坏块标志
SEccUnlock();
WrNFDat(tmp[0]);//ECC校验码
WrNFDat(tmp[1]);
WrNFDat(tmp[2]);
WrNFDat(tmp[3]);
SEccLock();


WrNFCmd(PROGCMD1);
stat = WaitNFBusy();
NFChipDs();

return ~stat;


}

/*------------------------------------------------------------/
函数名称:nandMain
功能描述:入口函数
传 参:无
返 回 值:无
-------------------------------------------------------------*/
void nandMain(void)
{
U16 ID,i;
U8 buf[512];
U32 NFBlockNO=6;
U32 NFPagesNO = 25;
U32 status;
U32 BlockPages; //页码就是列地址 row

BlockPages =(NFBlockNO<<6)+NFPagesNO; //1 Block = 64 Pages 2^6=64 第409pages

Uart_Init(115200);
Uart_Printf("\nthe main is running\n");

InitNandCfg(); //初始化函数
ID=ReadChipId();//ID=ECf1
Uart_Printf("\nnand flash`s ID is:%x\n",ID);


if(EraseBlock(BlockPages)&0x1==TRUE)
{
Uart_Printf("\nblock %d is erased\n",NFBlockNO);

ReadPage(BlockPages,buf);

Uart_Printf("\n/***********************擦除之后flash中的数据 ****************/\n");
for(i=0; i<512; i++)
Uart_Printf("%4x", buf[i]);


Uart_Printf("\n/***********************应写入数据****************/\n");
for(i=0; i<512; i++)
{
buf[i] = i;
Uart_Printf("%4x", buf[i]);
}

Uart_Printf("\nWrite data[%d block, %d page].\n", NFBlockNO,NFPagesNO);
status = WritePage(BlockPages,buf);

if(status&0x1==TRUE )
Uart_Printf("\nWrite OK.\n");
else
Uart_Printf("\nWrite Error.\n");

for(i=0; i<512; i++)
buf[i] = 1; //为验证后边数组中的数据是来自flash


ReadPage(BlockPages,buf);
Uart_Printf("\nRead data[%d block, %d page].\n", NFBlockNO,NFPagesNO);

Uart_Printf("\n/*********************** 读出的数据 ****************/\n");
for(i=0; i<512; i++)
Uart_Printf("%4x", buf[i]);
}

else
Uart_Printf("\nblock %4x erased is bad\n",NFBlockNO);

while(1);
}