我相信上一篇文章现已对nand flash的操作有了必定的了解,下面一同看一下程序实例:
#include “include.h”
extern void Uart_Printf(char *fmt,…);
extern void Uart_Init(int baud);
//extern void Uart_Select(int ch);
static void InitNandCfg(void)
{
rGPACON = (rGPACON &~(0x3f<<17)) | (0x3f<<17);//装备芯片引脚,由于GPACON复位后各位的值为1,所以此步也可没有
//TACLS为1个HCLK,TWRPH0为5个HCLK,TWRPH1为2个HCLK,数据宽度8位
rNFCONF = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);
//制止紧闭,软件制止上锁,制止不合法拜访中止,制止RnB 中止,RnB检测上升沿,确定备份ECC,确定主数据区域ECC生成,初始化ECC 编码器/译码器,
//强制nFCE 为高(制止片选),NAND Flash 操控器使能
rNFCONT = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0);
}
static U32 WaitNFBusy(void)// R/B 未接好?
{
U8 stat;
WrNFCmd(QUERYCMD);//0x70,读状况指令
do
{
stat = RdNFDat();//读取NFDATA
}
while (!(stat&0x40));//,第6位,判别是否在忙
WrNFCmd(READCMD0);//写页读指令周期0
return stat&1;//留意0为操作成功
}
static U32 ReadChipId(void)
{
U32 id,k;
NFChipEn();//使能片选
WrNFCmd(RdIDCMD);//读ID指令
WrNFAddr(0);//写入地址0
while(NFIsBusy());//等候不忙
id= RdNFDat()<<8;//应该是只读的厂商ID
for(k=0;k<500;k++);//延时
id |= RdNFDat();//低8位为设备ID
NFChipDs();//封闭片选
return id;//回来ID值
}
static U16 ReadStatus(void)
{
U16 stat;
NFChipEn();//片选使能
WrNFCmd(QUERYCMD);//读状况指令
stat = RdNFDat();//读取状况值
NFChipDs();//封闭片选
return stat;
}
U32 EraseBlock(U32 addr)//输入参数是详细的页数,擦除的是页数地点的块
{
U8 stat;
addr &= ~0x3f;//为了将地址赋给A18~A19
NFChipEn();//片选使能
WrNFCmd(ERASECMD0);//擦除指令周期0
WrNFAddr(addr);//写地址写3个行周期A18~A19
WrNFAddr(addr>>8);//A20~A27
WrNFAddr(addr>>16);//A28
WrNFCmd(ERASECMD1);//擦除指令周期1
stat = WaitNFBusy();//等候不忙
NFChipDs();//封闭片选
return ~stat;//回来1则操作成功
}
void ReadPage(U32 addr, U8 *buf)//并没有运用ECC校验
{
U16 i;
NFChipEn();//片选使能
WrNFCmd(READCMD0);//读指令周期0
WrNFAddr(0);//写列地址A0~A7
WrNFAddr(0);//写列地址A8~A11
WrNFAddr(addr);//行地址A12~A19
WrNFAddr(addr>>8);//行地址A20~A27
WrNFAddr(addr>>16);//行地址A28
WrNFCmd(READCMD1);//读指令周期1
InitEcc();//复位ECC
WaitNFBusy();
for(i=0; i<2048; i++)
buf[i] = RdNFDat();//读取数据存入buf中
NFChipDs();//封闭片选
}
U32 WritePage(U32 addr, U8 *buf)
{
U32 i, mecc;
U8 stat, tmp[7];
NFChipEn();
WrNFCmd(PROGCMD0);//页写指令周期1
WrNFAddr(0);
WrNFAddr(0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
WrNFAddr(addr>>16);
InitEcc();//reset mecc and secc
MEccUnlock();//ECC解锁
for(i=0; i<2048; i++)
WrNFDat(buf[i]);//写数据
MEccLock();//确定ECC值
mecc =RdNFMEcc();//读取ECC码
//把ECC码转化为字节型
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();//解锁spare区ECC
WrNFDat(tmp[0]);//把main区的ECC写入spare区的前4个字节
WrNFDat(tmp[1]);
WrNFDat(tmp[2]);
WrNFDat(tmp[3]);
SEccLock();//确定spare区ECC
WrNFCmd(PROGCMD1);//页写指令周期1
stat = WaitNFBusy();
NFChipDs();
return ~stat;
}
void nandMain(void)
{
U16 ID,i;
U8buf[2048];
U32 NFBlockNO=6;
U32 NFPagesNO = 25; //第6块第25页
U32 status;
U32 BlockPages;
BlockPages =(NFBlockNO<<6)+NFPagesNO; //转化为总页数
Uart_Init(115200);
Uart_Printf(“nthe main is runningn”);
InitNandCfg();//初始化函数
ID=ReadChipId();//ID 我的是现代的FLash,ID为:adda
Uart_Printf(“nnand flash`s ID is:%xn”,ID);
if(EraseBlock(BlockPages)&0x1==TRUE)//由于EraseBlock()的输入参数是页数,所以输入的是BlockPages
{
Uart_Printf(“nblock %d is erasedn”,NFBlockNO);//打印擦除的是那一块
ReadPage(BlockPages,buf);//读取擦除后的数据
Uart_Printf(“nn”);
for(i=0; i<2048; i++)
Uart_Printf(“%4x”, buf[i]); //将读出的数据进行打印
Uart_Printf(“nn”);
for(i=0; i<2048; 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<2048; i++)
buf[i] = 1;//为验证后边数组中的数据是来自flash,实际上适当所以在数组中擦除了flash的数据,由于假如flash擦除时内容就全为1
ReadPage(BlockPages,buf); //将读取的数据存入buf中
Uart_Printf(“nRead data[%d block, %d page].n”, NFBlockNO,NFPagesNO);//输出块号和页号
Uart_Printf(“nn”);
for(i=0; i<2048; i++)
Uart_Printf(“%4x”, buf[i]);//打印所读取的数据
}
else
Uart_Printf(“nblock %4x erased is badn”,NFBlockNO); //否则是坏块,并打印信息
while(1);
}
声明:本文内容来自网络转载或用户投稿,文章版权归原作者和原出处所有。文中观点,不代表本站立场。若有侵权请联系本站删除(kf@86ic.com)https://www.86ic.net/qiche/dianzi/256925.html