S3C2451_nand flash_ARM操作读写源码

这是本人基于三星的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)
    {
        ;
    }
}

有问题大家可以留言谢谢!!!

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zxnsirius

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值