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