原创 我的nandflash读写源码,代码清晰 (原创)

2008-8-29 14:09 9338 9 9 分类: MCU/ 嵌入式

啥也不说了,偶工程中用的源码,奉献给大家参考,觉得不错的兄弟给帮忙推荐下:
代码整齐,使用了MLC3890的nandflash控制器,可以作为你了解nandflash的参考
//----------------------------------------
#define NAND_CMD_READ_A          0x00  
#define NAND_CMD_READ_B          0x01
#define NAND_CMD_READ_C          0x50
#define NAND_CMD_SIGNATURE       0x90
#define NAND_CMD_STATUS          0x70
//Page Program
#define NAND_CMD_PAGE_PROG0      0x80
#define NAND_CMD_PAGE_PROG1      0x10
//Copy Back Program
#define NAND_CMD_COPY_PROG0      0x00
#define NAND_CMD_COPY_PROG1      0x8A
#define NAND_CMD_COPY_PROG2      0x10
#define NAND_CMD_BLOCK_ERASE0    0x60
#define NAND_CMD_BLOCK_ERASE1    0xD0
#define NAND_CMD_RESET           0xFF

//Nand Flash Status
#define NAND_BIT_WP    0x80  // 0:Protected    1: not protected
#define NAND_BIT_BUSY  0x60  // bit5,bit6  0:Busy    1:ready
#define NAND_BIT_ERR   0x01  // 1:Error   0:successful

#define NAND_PAGESIZE       512
#define NAND_SPARESIZE      16
//__align(8)
volatile U8  _NandFlashBakBuffer[NAND_PAGESIZE+NAND_SPARESIZE+1];

#if   0
/*----------------------------------------------------------------*/
/*    NAND FLASH CONTROLLER REGISTERS : 0x00870194                  */
/*----------------------------------------------------------------*/


#define NANDBASE              MCU_NAND_CTRL_BASE
#define MCU_REG_RW_NAND_CTRL        (*(volatile U32 *)(NANDBASE+0x00))
#define MCU_REG_RW_NAND_CMD            (*(volatile U32 *)(NANDBASE+0x04))
#define MCU_REG_RW_NAND_ADR            (*(volatile U32 *)(NANDBASE+0x08))
#define MCU_REG_RW_NAND_DATA        (*(volatile U32 *)(NANDBASE+0x0C))
#define MCU_REG_R_NAND_ECC            (*(volatile U32 *)(NANDBASE+0x10))
#define MCU_REG_RW_NAND_CEBCTRL   (*(volatile U32 *)(NANDBASE+0x14))

#endif
// Enable Nand Controller : 8-Bit slowest

#define NandCtrlEnable()            { MCU_REG_RW_PERI_CLKCON |= dMCU_CLK_ENABLE_NAND;\
                                      MCU_REG_RW_NAND_CTRL  = 0x8004FFFF; \
                                      MCU_REG_RW_NAND_CEBCTRL=0x02;}
#define NandWriteCmd(cmd)           { MCU_REG_RW_NAND_CMD  = (cmd) &0xFF;}
#define NandWriteAddr(addr)         { MCU_REG_RW_NAND_ADR  = (addr)&0xFF;}
#define NandWriteData(data)         { MCU_REG_RW_NAND_DATA = (data)&0xFF;}
#define NandReadData(data)          { data = MCU_REG_RW_NAND_DATA & 0xFF;}



#define NandCtrlIsBusy()    (MCU_REG_RW_NAND_CTRL&0x00040000) //BIT18
#define NandWait()          Delay(10)

//========================================================
#define NAND_CE_ACTIVE(x)    {                                \
                    MCU_REG_RW_PERI_CLKCON |= dMCU_CLK_ENABLE_NAND;    \
                    MCU_REG_RW_NAND_CEBCTRL = (x<<2)|(1<<1)|(0<<0);    \
                    }
#define NAND_CE_INACTIVE(x)    {                                \
                    MCU_REG_RW_NAND_CEBCTRL = (x<<2)|(1<<1)|(1<<0);    \
                    MCU_REG_RW_PERI_CLKCON &= ~dMCU_CLK_ENABLE_NAND;\
                    }

#define pNand_Busy        BITMAP_MCU_GPIO_DATA0.bit13
#define pdNand_Busy       BITMAP_MCU_GPIO_MODE3.bit2
#define poNand_Busy       BITMAP_MCU_GPIO_MODE3.bit3
#define pNand_Busy_In()   {pdNand_Busy=1; poNand_Busy=1;}


#define    pNand_Busy_OUT()    {MCU_REG_RW8_IOMODE3 = ((MCU_REG_RW8_IOMODE3 & 0xF3)|(dMLCIO_OUTPUT_MODE<<2));}
#define    pNand_Busy_IN()        {MCU_REG_RW8_IOMODE3 = ((MCU_REG_RW8_IOMODE3 & 0xF3)|(dMLCIO_INPUT_MODE<<2));}


void NandFlashDrvInit(void)
{
    MCU_REG_RW_PERI_CLKCON |= dMCU_CLK_ENABLE_NAND;
    NandCtrlEnable();
   
    MCU_REG_RW8_IOMODE0 = ((MCU_REG_RW8_IOMODE0&0x03)
                          |(dMLCIO_OUTPUT_MODE<<2)    // GP01 : lcd reset
                          |(dMLCIO_ALTER_MODE<<4)    // GP02 : Nand_CS0
                          |(dMLCIO_ALTER_MODE<<6)); // GP03 : Nand_CS1
     
 MCU_REG_RW8_IOMODE1 = (dMLCIO_ALTER_MODE<<0)    // GP04 
            |(dMLCIO_ALTER_MODE<<2)    // GP05 : Nand_ALE
            |(dMLCIO_ALTER_MODE<<4)    // GP06 : Nand_REN
            |(dMLCIO_ALTER_MODE<<6);  // GP07 : Nand_WEN                                                                          
}

void NandFlashICReset(void)
{
    NandCtrlEnable();
    NandWait();
    NandWriteCmd(NAND_CMD_RESET);
}

void NandFlashEraseBlock (U32 block_addr)
{
    U32 temp =0;
    U8 addr1;
    U8 addr2;
    U8 addr3;

    NandCtrlEnable();
    NAND_CE_ACTIVE(0);

    addr1 = (U8) (block_addr >> 9);
    addr2 = (U8) (block_addr >> 17);
    addr3 = (U8) (block_addr >> 25);  
    
    NandWriteCmd(NAND_CMD_BLOCK_ERASE0);
    NandWait();
    NandWriteAddr(addr1); 
    NandWait();
    NandWriteAddr(addr2); 
    NandWait();
    NandWriteAddr(addr3); 
    NandWait();
    NandWriteCmd(NAND_CMD_BLOCK_ERASE1);
   
#if 1
    pNand_Busy_IN();
    for(temp=0;temp<40;temp++);
    for(temp=0;temp<5000;temp++)
    {
        if(pNand_Busy)
            break;
    }
#endif

    do
    {
        NandWriteCmd(NAND_CMD_STATUS);
        NandReadData(temp);
    }while (NAND_BIT_BUSY != (temp & NAND_BIT_BUSY));      

    NAND_CE_INACTIVE(0);
}

U8 NandFlashGetIndex (U16 index)
{
    if(index>NAND_PAGESIZE)
        index = 0;

    return _NandFlashBakBuffer[index];
}

U8 NandFlashGetPage(U8* rdBuf)
{
    U16 index;
   
    for(index=0;index<NAND_PAGESIZE;index++)
    {
        rdBuf[index] = _NandFlashBakBuffer[index];
    }
    return 0;
}

U8 NandFlashReadPage (U32 page_addr)
{
    U32 temp,idx;
    U8 addr0;
    U8 addr1;
    U8 addr2;
    U8 addr3;

    NandCtrlEnable();
    NAND_CE_ACTIVE(0);
 
    addr0 = (U8)  page_addr;
    addr1 = (U8) (page_addr >> 9);
    addr2 = (U8) (page_addr >> 17);
    addr3 = (U8) (page_addr >> 25);
   
    NandWriteCmd(NAND_CMD_READ_A);
    NandWait();
    NandWriteAddr(addr0);
    NandWait();        
    NandWriteAddr(addr1);
    NandWait();         
    NandWriteAddr(addr2);
    NandWait();        
    NandWriteAddr(addr3);          

    pNand_Busy_IN();
    for(temp=0;temp<40;temp++);
    for(temp=0;temp<5000;temp++)
    {
        if(pNand_Busy)
            break;
    }

    for (idx=0; idx<NAND_PAGESIZE; idx++)
    {
        NandReadData(temp);
        _NandFlashBakBuffer[idx] = (U8)(temp&0xFF);
    }

    NAND_CE_INACTIVE(0);
    return 0;
}

U8 NandFlashProgPage(U32 page_addr, U8* dataAddr)
{
    U8 *rp;
    U16 temp;
    U8 addr0;
    U8 addr1;
    U8 addr2;
    U8 addr3;
  
    rp = (U8*)dataAddr;

    NandCtrlEnable();
    NAND_CE_ACTIVE(0);
    addr0 = (U8)  page_addr;
    addr1 = (U8) (page_addr >> 9);
    addr2 = (U8) (page_addr >> 17);
    addr3 = (U8) (page_addr >> 25);
   
    NandWriteCmd(NAND_CMD_READ_A);
    NandWait();
    NandWriteCmd(NAND_CMD_PAGE_PROG0);
    NandWait();
    NandWriteAddr(addr0);
    NandWait();         
    NandWriteAddr(addr1);
    NandWait();          
    NandWriteAddr(addr2);
    NandWait();         
    NandWriteAddr(addr3);

    for (temp=0; temp<NAND_PAGESIZE; temp++ )
    {
        NandWriteData(*rp);
        NandWait();     
        rp++;
    }
    NandWriteCmd(NAND_CMD_PAGE_PROG1);  
 #if 1
    pNand_Busy_IN();
    for(temp=0;temp<40;temp++);
    for(temp=0;temp<5000;temp++)
    {
        if(pNand_Busy)
            break;
    }
#endif
    do
    {
        NandWriteCmd(NAND_CMD_STATUS);
        NandReadData(temp);
    }while (NAND_BIT_BUSY != (temp & NAND_BIT_BUSY));
   
    NAND_CE_INACTIVE(0);
    return 0;   
}

U16 NandGetSignature (void)
{
    U16 temp ;
    U16 sign =0;
   
    NandCtrlEnable();
    NAND_CE_ACTIVE(0);
   
    NandWriteCmd(NAND_CMD_SIGNATURE);
    NandWait();
    NandWriteAddr(0x00);
    NandWait();
    NandReadData(temp);   
    NandWait();
    sign = temp;
    NandReadData(temp);
    sign <<= 8;
    sign += temp;

    NAND_CE_INACTIVE(0);
    return sign;
}

文章评论4条评论)

登录后参与讨论

托尼杰克马 2022-10-29 14:44

写的不错

用户377235 2013-4-16 11:56

恩 不错 。确实清晰明了

用户499141 2009-7-10 14:25

写的不错,以后常来

walnutcy_696810119 2008-8-30 01:36

谢谢关注. 个人认为当程序较简洁时,名称也较清晰时,从名称基本可以看出注释.
相关推荐阅读
walnutcy_696810119 2012-11-21 08:37
Linux下使用smartCOM调试串口
在Windows下的串口调试一直使用sscom,在Linux下只找到一个cutecom,用了几次,很不喜欢,就着手开发了一款自己的串口调试工具,smartCOM。 smartCOM介绍:http...
walnutcy_696810119 2012-03-29 18:12
【博客大赛】原创--测量基础:什么是测量
写在正文之前: 适逢EDNChina搞活动,而我本人也算在测量业工作,就一起作下笔记吧。若有错误,请大家一起斧正。笔者写本文一方面是梳理知识,另一方面也希望与大家探讨有关测量的知识、应用等,希...
walnutcy_696810119 2011-12-20 18:29
GLONASS 15年来,首次实现24颗星在轨可用
  EDN的博客改版后,不太好用,在SINA重开一个,不过重点改为关注GNSS行业新闻 http://blog.sina.com.cn/s/blog_7420cd1701012en9....
walnutcy_696810119 2011-12-20 17:49
逆向工程第一步:通信协议分析
工程中常有这样的事,想分析下其他知名公司产品中的通信协议,以便生产设计兼容产品。 1) 逆向工程,首先要了解产品,知己知彼,百战不怠;     去年受命想仿一款GARMIN的导航盒,但无法...
walnutcy_696810119 2011-11-14 11:30
通用代码调试方法 (Keil, VCC)
调试代码一般需要定位问题,这里给出一个解决方案, 一般的编译器均支持这些宏指令。   #define DEBUG_WALT_1113     1 extern void log_t...
我要评论
4
9
关闭 站长推荐上一条 /2 下一条