您的位置:控制工程论坛网论坛 » 嵌入式系统 » nandflash读写源码,代码清晰

xilinxue

xilinxue   |   当前状态:在线

总积分:16186  2024年可用积分:0

注册时间: 2008-06-26

最后登录时间: 2020-03-22

空间 发短消息加为好友

nandflash读写源码,代码清晰

xilinxue  发表于 2009/1/13 13:04:57      1069 查看 0 回复  [上一主题]  [下一主题]

手机阅读

啥也不说了,偶工程中用的源码,奉献给大家参考,觉得不错的兄弟给帮忙推荐下:
代码整齐,使用了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;
}

1楼 0 0 回复