这是本人基于三星的S3C2451的miniARM开发板写的有关nand flash的一下代码,包括了初始化、忙判断、读取ID、读取状态、清除块、对页的读写、以及一个测试函数。提供给大家参考。
/*typedef.h*/
#ifndef _TYPEDEF_H_
#define _TYPEDEF_H_
#define U32 unsigned int
#define U16 unsigned short
#define S32 int
#define S16 short int
#define U8 unsigned char
#define S8 char
#define TRUE 1
#define FALSE 0
#endif
/*nand*/
#define rNFCONF (*(volatile unsigned *)0x4E000000)
#define rNFCONT (*(volatile unsigned *)0x4E000004)
#define rNFCMD (*(volatile unsigned *)0x4E000008)
#define rNFADDR (*(volatile unsigned *)0x4E00000C)
#define rNFCMMD (*(volatile unsigned *)0x4E000008)
#define rNFDATA (*(volatile unsigned *)0x4E000010)
#define rNFDATA8 (*(volatile unsigned char *)0x4E000010)
#define rNFMECC0 (*(volatile unsigned *)0x4E00002c
#define rNFSTAT (*(volatile unsigned *)0x4E000028)
#define rNFESTAT0 (*(volatile unsigned *)0x4E000024)
/* 初始化Nand flash */
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);
}
/* nand flash的忙判断 */
static U32 WaitNFBusy(void) //
{
U8 stat;
WrNFCmd(QUERYCMD);
do
{
stat = RdNFDat();
}
while (!(stat&0x40));
WrNFCmd(READCMD0);
return stat&1; //
}
/* 读nand flash ID */
static U32 ReadChipId(void)
{
U32 id,k;
NFChipEn();
WrNFCmd(RdIDCMD);
WrNFAddr(0);
while ( NFIsBusy() )
{
;
}
id = RdNFDat()<<8;
for (k=0;k<500;k++)
{
;
}
id |= RdNFDat();
NFChipDs();
return id;
}
/* 读nand flash 状态 */
U16 ReadStatus(void)
{
U16 stat;
NFChipEn();
WrNFCmd(QUERYCMD);
stat = RdNFDat();
NFChipDs();
return stat;
}
/*清楚块区域、addr是要清除的页地址,清除的是操作页的整个块*/
U32 EraseBlock(U32 addr)
{
U8 stat;
addr &= ~0x3f;
NFChipEn();
WrNFCmd(ERASECMD0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
WrNFAddr(addr>>16);
WrNFCmd(ERASECMD1);
stat = WaitNFBusy();
NFChipDs();
return ~stat;
}
/*对页进行读操作,addr是要读的页地址,buf存放的是读入数据*/
void ReadPage(U32 addr, U8 *buf)
{
U16 i;
NFChipEn();
WrNFCmd(READCMD0);
WrNFAddr(0);
WrNFAddr(0);
WrNFAddr(addr);
WrNFAddr(addr>>8);
WrNFAddr(addr>>16);
WrNFCmd(READCMD1);
InitEcc();
WaitNFBusy();
for(i=0; i<2048; i++)
{
buf[i] = RdNFDat();
}
NFChipDs();
}
/*对页进行写操作,addr是要写入的页地址,buf存放的是写入数据*/
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);
WrNFAddr(addr>>16);
InitEcc(); //reset mecc and secc
MEccUnlock();
for(i=0; i<2048; 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);
SEccUnlock();
WrNFDat(tmp[0]);
WrNFDat(tmp[1]);
WrNFDat(tmp[2]);
WrNFDat(tmp[3]);
SEccLock();
WrNFCmd(PROGCMD1);
stat = WaitNFBusy();
NFChipDs();
return ~stat;
}
/*nand flash 测试程序,通过串口发送给电脑,在电脑上接收数据*/
void Nand_Test(void)
{
U32 BlackNum = 2;
U32 PageNum = 10;
U32 TotalPageNum = BlackNum * 64 + PageNum;
U32 i = 0;
U8 pagbuf[2048] = {0};
U32 NandFlashID;
NandFlashID = ReadChipId();
Uart_Printf("Nand from ID: %4X\n", NandFlashID);
Uart_Printf("\n-------------开始清除-------------\n");
if ((EraseBlock(TotalPageNum)& 1) == TRUE)
{
Uart_Printf("\n-------------清除完成-------------\n");
ReadPage(TotalPageNum, pagbuf);
for (i = 0; i < 2048; i++)
{
Uart_Printf("%2x ", pagbuf[i]);
}
Uart_Printf("\n----写入2048个数据-----\n");
for (i = 0; i < 2048; i++)
{
pagbuf[i] = (U8)i;
}
Uart_Printf("\n------------写入2048个数据已完成-----------\n");
WritePage(TotalPageNum, pagbuf);
Uart_Printf("\n------------读出2048个数据------------\n");
ReadPage(TotalPageNum, pagbuf);
for (i = 0; i < 2048; i++)
{
Uart_Printf("%2x ", pagbuf[i]);
}
}
}
/*更多详细的S3C2451_uart代码请看本人博客S3c2451UART篇
http://blog.csdn.net/zxnsirius/article/details/50988437
*/
void Uart_Printf(char *fmt, ...)
{
va_list ap;
char string[2014];
va_start(ap, fmt);
vsprintf(string, fmt, ap);
va_end(ap);
Uart_SendStr(string);
}
void Main()
{
uart_init(UART0, 115200,DATA_WIDTH_8BIT, STOP_BIT0);
InitNandCfg();
Nand_Test();
while(1)
{
;
}
}
有问题大家可以留言谢谢!!!