nand flash 控制

来源:互联网 发布:javs编程思想pdf百度云 编辑:程序博客网 时间:2024/06/07 12:58

 

 

 

 

 

 

 

NAND FLASH 模式配置

1. 通过NFCONF 寄存器配置NAND Flash;

2. 写NAND Flash 命令到NFCMMD 寄存器;

3. 写NAND Flash 地址到NFADDR 寄存器;

4. 在读写数据时,通过NFSTAT 寄存器来获得NAND Flash 的状态信息。应该在读操作前

或写入之后检查R/nB 信号(准备好/忙信号)。

管脚配置

D[7:0] : 数据/命令/地址/的输入/输出口(与数据总线共享)

CLE : 命令锁存使能(输出)

ALE : 地址锁存使能(输出)

nFCE : NAND Flash 片选使能(输出)

nFRE : NAND Flash 读使能(输出)

nFWE : NAND Flash 写使能(输出)

R/nB : NAND Flash 准备好/繁忙(输入)

#include"include.h"

//#include"uart.c"

extern void Uart_Printf(char *fmt,...);

extern void Uart_Init(int baud);

//extern void Uart_Select(int ch);

/*

****************************************************************

*函数名称:InitNandCfg

*功能描述: 配置 Nandflash

*参    数: void

*返 回 值: void

****************************************************************

*/

static void InitNandCfg(void)

{

    /*命令、地址锁存持续时间HCLK,8位总线宽度*/

    rNFCONF  = (TACLS<<12)|(TWRPH0<<8)|(TWRPH1<<4)|(0<<0);

    /*不加锁,不加软锁,禁止非法访问中断,关闭忙信号变化中断,检测忙信号的上升沿

    给空余的区域ecc枷锁,*/

    rNFCONT  = (0<<13)|(0<<12)|(0<<10)|(0<<9)|(0<<8)|(1<<6)|(1<<5)|(1<<4)|(1<<1)|(0<<1);

}

static U32 WaitNFBusy(void)

{

    U8 stat;

    

    WrNFCmd(QUERYCMD);//nand flash command value

    do {

        stat = RdNFDat(); 

    }

    while (!(stat&0x40));

    WrNFCmd(READCMD0);

    return stat&1;

}

static U32 ReadChipId(void)

{

    U32 id,k;

    

    NFChipEn();//片选使能

  

    WrNFCmd(RdIDCMD);  //get the command set register's value

WrNFAddr(0);       //nand flash address register = 0

while(NFIsBusy()); //如果忙,则等待

id  = RdNFDat()<<8;//获得rNFDATA8的数据,

    id |= RdNFDat();   //获得rNFDATA8的数据,并得到16位数据

NFChipDs();    //nand flash controller disable

return id;        

}

static  U16 ReadStatus(void)

{

    U16 stat;

    

    NFChipEn();

    

    WrNFCmd(QUERYCMD);

    stat = RdNFDat(); // get the rNFDATA8's value

NFChipDs();       // nand flash controller disable

return stat;

}

/*------------------------------------------------------------/

函数名称: EraseBlock

功能描述: 擦除 FLASH

传    参: U32 addr

返 回 值: U32 ~stat

-------------------------------------------------------------*/

U32 EraseBlock(U32 addr)

{

U8 stat;

addr &= ~0x3f;

NFChipEn();

WrNFCmd(ERASECMD0);

WrNFAddr(addr);

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);

WrNFAddr(0);

WrNFAddr(addr);

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 nand_Main(void) 

U16 ID,i; 

U8 buf[512]; 

U32 NFBlockNO=6; 

U32 NFPagesNO = 25; 

U32 status; 

U32 BlockPages;

BlockPages =(NFBlockNO<<6)+NFPagesNO; 

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); 

}

再给主程序命名的时候一定不能够带 "_" 不然会找不到入口的main函数,以为是语法错误,结果才是文件名不对。