最近一个多礼拜都在搞这方面的东西,买了一块深圳英贝特的开发板,不过里面的例程是对小页的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()); }
附件为工程文件。
|