最近一个多礼拜都在搞这方面的东西,买了一块深圳英贝特的开发板,不过里面的例程是对小页的nandflsh的操作,所以与K9F1G08多少有点不同,网上也有很多版本,比如圈圈的K9F1G08驱动很是详细,但改动比较大,所以整合到我的程序里很费劲,还有一些其他的改进的版本,但经过试验,感觉能实现部分的操作,但不是很完整,比如读写多页的操作,就会出现bug,今天在网上搜到了红牛的开发板的例程,试了一下很是不错,根据他的例子和本人的例子相结合,整理如下:
fsmc_nand.h中应该改动的代码:(注释没有及时更新)
/* Exported constants --------------------------------------------------------*/
/* NAND Area definition for STM3210E-EVAL Board RevD */
#define CMD_AREA (u32)(1<<16) /* A16 = CLE high */
#define ADDR_AREA (u32)(1<<17) /* A17 = ALE high */
#define DATA_AREA ((u32)0x00000000)
/* FSMC NAND memory command */
#define NAND_CMD_READ_1 ((u8)0x00)
#define NAND_CMD_READ_TRUE ((u8)0x30)
#define NAND_CMD_RDCOPYBACK ((u8)0x00)
#define NAND_CMD_RDCOPYBACK_TRUE ((u8)0x35)
#define NAND_CMD_PAGEPROGRAM ((u8)0x80)
#define NAND_CMD_PAGEPROGRAM_TRUE ((u8)0x10)
#define NAND_CMD_COPYBACKPGM ((u8)0x85)
#define NAND_CMD_COPYBACKPGM_TRUE ((u8)0x10)
#define NAND_CMD_ERASE0 ((u8)0x60)
#define NAND_CMD_ERASE1 ((u8)0xD0)
#define NAND_CMD_READID ((u8)0x90)
#define NAND_CMD_STATUS ((u8)0x70)
#define NAND_CMD_RESET ((u8)0xFF)
#define NAND_CMD_CACHEPGM ((u8)0x80)
#define NAND_CMD_CACHEPGM_TRUE ((u8)0x15)
#define NAND_CMD_RANDOMIN ((u8)0x85)
#define NAND_CMD_RANDOMOUT ((u8)0x05)
#define NAND_CMD_RANDOMOUT_TRUE ((u8)0xE0)
#define NAND_CMD_CACHERD_START ((u8)0x00)
#define NAND_CMD_CACHERD_START2 ((u8)0x31)
#define NAND_CMD_CACHERD_EXIT ((u8)0x34)
/* NAND memory status */
#define NAND_VALID_ADDRESS ((u32)0x00000100)
#define NAND_INVALID_ADDRESS ((u32)0x00000200)
#define NAND_TIMEOUT_ERROR ((u32)0x00000400)
#define NAND_BUSY ((u32)0x00000000)
#define NAND_ERROR ((u32)0x00000001)
#define NAND_READY ((u32)0x00000040)
/* FSMC NAND memory parameters */
#define NAND_PAGE_SIZE ((u16)0x0800) /* 512 bytes per page w/o Spare Area */
#define NAND_BLOCK_SIZE ((u16)0x0040) /* 32x512 bytes pages per block */
#define NAND_ZONE_SIZE ((u16)0x0400) /* 1024 Block per zone */
#define NAND_SPARE_AREA_SIZE ((u16)0x0040) /* last 16 bytes as spare area */
#define NAND_MAX_ZONE ((u16)0x0001) /* 4 zones of 1024 block */
fsmc_nand.c 中应该改动的地方:
u32 FSMC_NAND_WriteSmallPage(u8 *pBuffer, NAND_ADDRESS Address, u32 NumPageToWrite)
{ // 要写入的数 页地址 要写入多少页
u32 index = 0x00, numpagewritten = 0x00, addressstatus = NAND_VALID_ADDRESS;
u32 status = NAND_READY, size = 0;
while((NumPageToWrite != 0x00) && (addressstatus == NAND_VALID_ADDRESS) && (status == NAND_READY))
{
/* Page write command and address */
*(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM;
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = 0X00;
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
/* *(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);//ADDR_3rd_CYCLE(ROW_ADDRESS); //更改
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);//ADDR_4th_CYCLE(ROW_ADDRESS); //
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS);
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(ROW_ADDRESS); */
/* Calculate the size */
size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpagewritten);
/* Write data */
for(; index < size; index++)
{
*(vu8 *)(Bank_NAND_ADDR | DATA_AREA) = pBuffer[index];
printf(" 0x%x\n",pBuffer[index]);
}
*(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM_TRUE;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
/* Check status for successful operation */
status = FSMC_NAND_GetStatus();
if(status == NAND_READY)
{
numpagewritten++;
NumPageToWrite--;
/* Calculate Next small page Address */
addressstatus = FSMC_NAND_AddressIncrement(&Address);
}
}
return (status | addressstatus);
}
u32 FSMC_NAND_ReadSmallPage(u8 *pBuffer, NAND_ADDRESS Address, u32 NumPageToRead)
{
u32 index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS;
u32 status = NAND_READY, size = 0, i = 0,temp = 0;
while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS))
{
/* Page Read command and page address */
/* Page Read command and page address */
*(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ_1;
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = 0x00;
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = 0X00;
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
/*
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);//ADDR_3rd_CYCLE(ROW_ADDRESS); //更改
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);//ADDR_4th_CYCLE(ROW_ADDRESS); //
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_3rd_CYCLE(ROW_ADDRESS);
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_4th_CYCLE(ROW_ADDRESS); */
*(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_READ_TRUE;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
/* Calculate the size */
size = NAND_PAGE_SIZE + (NAND_PAGE_SIZE * numpageread);
// for(i = 0; i <= 10000; i++);
/* Get Data into Buffer */
for(; index < size; index++)
{
pBuffer[index]= *(vu8 *)(Bank_NAND_ADDR | DATA_AREA);
printf(" 0x%x\n",pBuffer[index]);
}
numpageread++;
NumPageToRead--;
/* Calculate page address */
addressstatus = FSMC_NAND_AddressIncrement(&Address);
}
status = FSMC_NAND_GetStatus();
return (status | addressstatus);
}
对块的擦出,注意:只对前两个周期进行操作
u32 FSMC_NAND_EraseBlock(NAND_ADDRESS Address)
{
*(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE0;
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
*(vu8 *)(Bank_NAND_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
*(vu8 *)(Bank_NAND_ADDR | CMD_AREA) = NAND_CMD_ERASE1;
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
return (FSMC_NAND_GetStatus());
}
附件为工程文件。
潜龙思瑞 2015-6-21 07:45
用户377235 2015-5-12 11:28
用户1773720 2014-7-15 10:30
用户263532 2013-7-3 15:29
用户512436 2011-11-10 10:56
用户290136 2010-6-22 09:34
用户9190 2008-1-23 17:23
想看关于第8项的详细解释