#define NANDFLASH_RW_PAGE_SIZE 2048
#define NANDFLASH_SPARE_SIZE 64
#define NANDFLASH_PAGE_PER_BLOCK 64
#define NANDFLASH_PAGE_FSIZE (NANDFLASH_RW_PAGE_SIZE + NANDFLASH_SPARE_SIZE)
#define NANDFLASH_BLOCK_FSIZE (NANDFLASH_PAGE_FSIZE * NANDFLASH_PAGE_PER_BLOCK)
#define NANDFLASH_INVALIDBLOCK_CHECK_COLUMM (1024)
#define NANDFLASH_NUMOF_BLOCK 1024
ht_uint8_t InvalidBlockTable[NANDFLASH_NUMOF_BLOCK];
ht_int32_t NandFlash_PageReadFromAddr(ht_uint32_t blockNum, ht_uint32_t pageNum, ht_uint32_t addrInPage, ht_uint8_t* bufPtr, ht_uint32_t size);
ht_int32_t NandFlash_ReadFromAddr(ht_uint32_t addrInWholeNand, ht_uint8_t* bufPtr, ht_uint32_t size);
ht_int32_t NandFlash_PageReadFromBeginning(ht_uint32_t blockNum, ht_uint32_t pageNum, ht_uint8_t* bufPtr);
/**********************************************************************************************************
*
* 函数名:NAND_Init
* 功 能:
* 参 数:
* 返回值:
* 版 本:
*
**********************************************************************************************************/
void NAND_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NANDInitTypeDef FSMC_NANDInitStructure;
FSMC_NAND_PCCARDTimingInitTypeDef p;
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
RCC_APB2PeriphClockCmd( RCC_APB2Periph_GPIOD |
RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOF |
RCC_APB2Periph_GPIOG, ENABLE);
// CLE, ALE, D0->D3, NOE, NWE and NCE2 NAND pin configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_11 | // PD.11(A16->CLE)
GPIO_Pin_12 | // PD.12(A17->ALE)
GPIO_Pin_14 | // PD.14(D0)
GPIO_Pin_15 | // PD.15(D1)
GPIO_Pin_0 | // PD.00(D2)
GPIO_Pin_1 | // PD.01(D3)
GPIO_Pin_4 | // PD.04(NOE)
GPIO_Pin_5 | // PD.05(NWE)
GPIO_Pin_7; // PD.07(NCE2)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
// D4->D7 NAND pin configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_7 | // PE.07(D4)
GPIO_Pin_8 | // PE.08(D5)
GPIO_Pin_9 | // PE.09(D6)
GPIO_Pin_10; // PE.10(D7)
GPIO_Init(GPIOE, &GPIO_InitStructure);
//NWAIT NAND pin configuration
// GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6;
// GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
// GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
// GPIO_Init(GPIOD, &GPIO_InitStructure);
// INT2 NAND pin configuration
GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6; // PG.06(R/B)
GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
//-- FSMC Configuration --
p.FSMC_SetupTime = 0x1;
p.FSMC_WaitSetupTime = 0x3;
p.FSMC_HoldSetupTime = 0x2;
p.FSMC_HiZSetupTime = 0x1;
FSMC_NANDInitStructure.FSMC_Bank = FSMC_Bank2_NAND;
FSMC_NANDInitStructure.FSMC_Waitfeature = FSMC_Waitfeature_Enable;
FSMC_NANDInitStructure.FSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
FSMC_NANDInitStructure.FSMC_ECC = FSMC_ECC_Enable;
FSMC_NANDInitStructure.FSMC_ECCPageSize = FSMC_ECCPageSize_2048Bytes;
FSMC_NANDInitStructure.FSMC_TCLRSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_TARSetupTime = 0x00;
FSMC_NANDInitStructure.FSMC_CommonSpaceTimingStruct = &p;
FSMC_NANDInitStructure.FSMC_AttributeSpaceTimingStruct = &p;
FSMC_NANDInit(&FSMC_NANDInitStructure);
FSMC_NANDCmd(FSMC_Bank2_NAND, ENABLE);
}
/**********************************************************************************************************
*
* 函数名:NAND_Reset
* 功 能:
* 参 数:
* 返回值:
* 版 本:
*
**********************************************************************************************************/
ht_uint32_t NAND_Reset(void)
{
NAND_WriteCmd(0xFF);
return (NAND_READY);
}
/**********************************************************************************************************
*
* 函数名:NAND_GetStatus
* 功 能:
* 参 数:
* 返回值:
* 版 本:
*
**********************************************************************************************************/
ht_uint32_t NAND_GetStatus(void)
{
ht_uint32_t timeout = 0x10000, status = NAND_READY;
status = NAND_ReadStatus();
while ((status != NAND_READY) &&( timeout != 0x00))
{
status = NAND_ReadStatus();
timeout --;
}
if(timeout == 0x00)
{
status = NAND_TIMEOUT_ERROR;
}
return (status);
}
/**********************************************************************************************************
*
* 函数名:NAND_ReadStatus
* 功 能:
* 参 数:
* 返回值:
* 版 本:
*
**********************************************************************************************************/
ht_uint32_t NAND_ReadStatus(void)
{
ht_uint32_t data = 0x00, status = NAND_BUSY;
NAND_WriteCmd(0x70);
data = NAND_ReadDat();
if((data & NAND_ERROR) == NAND_ERROR)
{
status = NAND_ERROR;
}
else
if((data & NAND_READY) == NAND_READY)
{
status = NAND_READY;
}
else
{
status = NAND_BUSY;
}
return (status);
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_ReadId
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_uint32_t NandFlash_ReadId(void)
{
ht_uint32_t a,b,c,d;
NAND_WriteCmd(0x90);
NAND_WriteAddr(0x00);
a = NAND_ReadDat();
b = NAND_ReadDat();
c = NAND_ReadDat();
d = NAND_ReadDat();
return ((a << 24) | (b << 16) | (c << 8) | d);
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_BlockErase
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_bool_t NandFlash_BlockErase( ht_uint32_t blockNum )
{
ht_uint32_t rowAddr;
ht_int32_t iResult=1;
rowAddr = blockNum * NANDFLASH_PAGE_PER_BLOCK;
NAND_WriteCmd(0x60);
NAND_WriteAddr((ht_uint8_t)(rowAddr&0xFF));
NAND_WriteAddr((ht_uint8_t)((rowAddr&0xFF00) >> 8));
NAND_WriteCmd(0xD0);
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
iResult= (NAND_GetStatus());
if(iResult==NAND_TIMEOUT_ERROR)
iResult=e_FALSE;
else
iResult=e_TRUE;
return iResult;
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_ValidBlockCheck
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_bool_t NandFlash_ValidBlockCheck( void )
{
ht_int32_t block, page;
ht_bool_t retValue = e_TRUE;
ht_int8_t data = 0;
for ( block = 0; block < NANDFLASH_NUMOF_BLOCK; block++ )
{
for ( page = 0; page < 2; page++ )
{
NandFlash_PageReadFromAddr(block, page, NANDFLASH_INVALIDBLOCK_CHECK_COLUMM, &data, 1);
if(data != 0xFF)
{
// found invalid block number, mark block number in the invalid
// block table
InvalidBlockTable[block] = 0;
//At least one block is invalid
retValue = e_FALSE;
}else{
InvalidBlockTable[block] = 1;
}
}
}
return(retValue);
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_PageRead
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t NandFlash_PageRead( ht_uint32_t pageNum, ht_uint32_t blockNum, ht_uint8_t *bufPtr )
{
return (NandFlash_PageReadFromBeginning(pageNum, blockNum, bufPtr) != 0);
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_PageReadFromBeginning
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t NandFlash_PageReadFromBeginning(ht_uint32_t blockNum, ht_uint32_t pageNum, ht_uint8_t* bufPtr)
{
return (NandFlash_PageReadFromAddr(blockNum, pageNum, 0, bufPtr, NANDFLASH_PAGE_FSIZE));// 鎿嶄綔鐨勬槸fsize
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_PageReadFromAddr
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t NandFlash_PageReadFromAddr(ht_uint32_t blockNum, ht_uint32_t pageNum, ht_uint32_t addrInPage, ht_uint8_t* bufPtr, ht_uint32_t size)
{
ht_uint32_t curAddr = 0;
curAddr += blockNum * NANDFLASH_BLOCK_FSIZE; // 鎿嶄綔鐨勬槸fsize
curAddr += pageNum * NANDFLASH_PAGE_FSIZE; // 鎿嶄綔鐨勬槸fsize
curAddr += addrInPage;
return (NandFlash_ReadFromAddr(curAddr, bufPtr, size));
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_ReadFromAddr
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t NandFlash_ReadFromAddr(ht_uint32_t addrInWholeNand, ht_uint8_t* bufPtr, ht_uint32_t size)
{
volatile ht_uint8_t nand_buf;
ht_uint32_t i, curColumm, curRow;
ht_int32_t iResult=1;
i = 0;
curColumm = addrInWholeNand % NANDFLASH_PAGE_FSIZE; // 鎿嶄綔鐨勬槸fsize
curRow = addrInWholeNand / NANDFLASH_PAGE_FSIZE; // 鎿嶄綔鐨勬槸fsize
NAND_WriteCmd(0x00);
NAND_WriteCmd( (ht_uint8_t)(curColumm & 0x000000FF)); /* column address low */
NAND_WriteCmd( (ht_uint8_t)((curColumm & 0x00000F00) >> 8)); /* column address high */
NAND_WriteCmd( (ht_uint8_t)(curRow & 0x000000FF)); /* row address low */
NAND_WriteCmd( (ht_uint8_t)((curRow & 0x0000FF00) >> 8));
NAND_WriteCmd(0x30);
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
//Get data from the current address in the page til the end of the page
for ( i = 0; i < (NANDFLASH_PAGE_FSIZE - curColumm); i++ )
{
*bufPtr = NAND_ReadDat();
if((i + 1) >= size)
break;
bufPtr++;
}
iResult= NAND_GetStatus();
if(iResult==NAND_TIMEOUT_ERROR)
iResult=0;
else
iResult=i;
return iResult;
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細NandFlash_SectorRead
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t NandFlash_SectorRead(ht_uint32_t sectorNum, ht_uint8_t* bufPtr)
{
ht_uint32_t curAddr = 0;
curAddr += sectorNum * 512;
curAddr +=(sectorNum/4)*NANDFLASH_SPARE_SIZE;
return (NandFlash_ReadFromAddr(curAddr, bufPtr, 512));
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細Nand_EraseBlockLarge
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t Nand_EraseBlockLarge(ht_int32_t BlockAddr)
{
ht_uint32_t rowAddr;
ht_int32_t iResult=1;
rowAddr = BlockAddr * NANDFLASH_PAGE_PER_BLOCK;
NAND_WriteCmd(0x60);
NAND_WriteAddr((ht_uint8_t)(rowAddr&0xFF));
NAND_WriteAddr((ht_uint8_t)((rowAddr&0xFF00) >> 8));
NAND_WriteCmd(0xD0);
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
iResult= (NAND_GetStatus());
if(iResult==NAND_TIMEOUT_ERROR)
iResult=0;
else
iResult=1;
return iResult;
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細Nand_WritePageWithSpare2048
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t Nand_WritePageWithSpare2048(ht_int32_t PageNum,const ht_uint8_t * DataBuf,const ht_uint8_t *Spare)
{
ht_int32_t iResult=1;
volatile ht_uint32_t i, curAddr, curColumm,curRow,k;
if(DataBuf == NULL)
curColumm = NANDFLASH_RW_PAGE_SIZE;
else
curColumm = 0;
curRow = PageNum;
NAND_WriteCmd(0x80);
NAND_WriteAddr( (ht_uint8_t)(curColumm & 0x000000FF)); /* column address low */
NAND_WriteAddr( (ht_uint8_t)((curColumm & 0x00000F00) >> 8)); /* column address high */
NAND_WriteAddr((ht_uint8_t)(curRow & 0x000000FF)); /* row address low */
NAND_WriteAddr((ht_uint8_t)((curRow & 0x0000FF00) >> 8));
if(DataBuf != NULL)
{
for ( i = 0; i < NANDFLASH_RW_PAGE_SIZE; i++ )
{
NAND_WriteDat( DataBuf[i]);
}
}
if(Spare != NULL)
{
for ( i = 0; i < NANDFLASH_SPARE_SIZE; i++ ) // 娣诲姞鍐檚pare
{
NAND_WriteDat( Spare[i]);
}
}
NAND_WriteCmd(0x10);
k=10000;
while( (GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 )&&(k>0))
{
k--;
}
iResult= (NAND_GetStatus());
if(iResult==NAND_ERROR)
iResult=0;
else
iResult=1;
}
/**********************************************************************************************************
*
* 鍑芥暟鍚嶏細Nand_ReadPageWithSpare2048
* 鍔熴€€鑳斤細
* 鍙? 鏁帮細
* 杩斿洖鍊硷細
* 鐗堛€€鏈細REV1.0.0 2016/04/27 Create
*
**********************************************************************************************************/
ht_int32_t Nand_ReadPageWithSpare2048(ht_int32_t PageNum,ht_uint8_t *const DataBuf, ht_uint8_t *const Spare)
{
volatile ht_uint8_t nand_buf;
ht_uint32_t i, curColumm, curRow;
volatile ht_uint8_t j;
ht_int32_t iResult=1;
i = 0;
/*if(DataBuf == NULL)
curColumm = NANDFLASH_RW_PAGE_SIZE;
else
curColumm = 0;*/
curColumm = 0;
curRow = PageNum;
NAND_WriteCmd(0x00);
NAND_WriteAddr((ht_uint8_t)(curColumm & 0x000000FF)); /* column address low */
NAND_WriteAddr((ht_uint8_t)((curColumm & 0x00000F00) >> 8)); /* column address high */
NAND_WriteAddr((ht_uint8_t)(curRow & 0x000000FF)); /* row address low */
NAND_WriteAddr((ht_uint8_t)((curRow & 0x0000FF00) >> 8));
NAND_WriteCmd(0x30);
while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
if(DataBuf != NULL)
{
for(i=0;i
int yflash2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags);
int yflash2_EraseBlockInNAND(yaffs_Device *dev, int blockNumber);
int yflash2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags);
int yflash2_GetNumberOfBlocks();
int yflash2_WriteChunkWithTagsToNAND(yaffs_Device *dev,int chunkInNAND,const __u8 *data, const yaffs_ExtendedTags *tags)
{
yaffs_PackedTags2 *pkt;
__u8 tmp[64]={'\0'};
int result;
pkt=(yaffs_PackedTags2*)tmp;
yaffs_PackTags2(pkt,tags);
result = Nand_WritePageWithSpare2048(chunkInNAND,data,tmp);// 返回1时表示写成功
if(result)
{
return YAFFS_OK;
}
return YAFFS_FAIL;
}
int yflash2_ReadChunkWithTagsFromNAND(yaffs_Device *dev,int chunkInNAND, __u8 *data, yaffs_ExtendedTags *tags)
{
yaffs_PackedTags2 *upt;
__u8 tmp[64]={'\0'};
int result;
result = Nand_ReadPageWithSpare2048(chunkInNAND,data,tmp);// 返回1时表示读成功
upt = (yaffs_PackedTags2*)tmp;
if(result)
{
yaffs_UnpackTags2(tags,upt);
return YAFFS_OK;
}
return YAFFS_FAIL;
}
void *yaffs_malloc(size_t size)
{
return (void *)cmMalloc(size);
}
void yaffs_free(void *ptr)
{
cmFree(ptr);
}
int yaffs_StartUp(void)
{
memset(&flashDev,0,sizeof(flashDev));
flashDev.name="yaffs2";
flashDev.totalBytesPerChunk = 1024;
flashDev.nDataBytesPerChunk =2048;
flashDev.spareBytesPerChunk = 64;
flashDev.nChunksPerBlock = 64;
flashDev.nReservedBlocks = 5;
flashDev.inbandTags = 0;
flashDev.startBlock = 0;
flashDev.endBlock = yflash2_GetNumberOfBlocks()-1;
flashDev.isYaffs2 = 1;
flashDev.wideTnodesDisabled=0;
flashDev.nShortOpCaches = 4; // Use caches
flashDev.genericDevice = (void *) 2; // Used to identify the device in fstat.
flashDev.writeChunkWithTagsToNAND = yflash2_WriteChunkWithTagsToNAND;
flashDev.readChunkWithTagsFromNAND = yflash2_ReadChunkWithTagsFromNAND;
flashDev.eraseBlockInNAND = yflash2_EraseBlockInNAND;
flashDev.initialiseNAND = yflash2_InitialiseNAND;
flashDev.markNANDBlockBad = yflash2_MarkNANDBlockBad;
flashDev.queryNANDBlock = yflash2_QueryNANDBlock;
yaffs_initialise(yaffsfs_config);
return 0;
}
void fstest(void)
{
int32_t i,file;
uint32_t FlashID;
uint8_t BufToRead[256];
uint8_t BufWriteTo[256];
for(i=0;i<256;i++)
{
BufToRead[i]=0;
BufWriteTo[i]=i;
}
yaffs_StartUp();
ht_printk("yaffs start up\r\n");
i=yaffs_mount("//");
if(i != 0)
{
ht_printk("yaffs mount error\r\n");
}
else
{
ht_printk("yaffs mount finsh\r\n");
}
i=yaffs_mkdir("/test",S_IFDIR);
if(i != 0)
{
ht_printk("yaffs mkdir error\r\n");
}
else
{
ht_printk("yaffs mkdir finsh\r\n");
}
// 返回的是handle
file= yaffs_open("/test/23.txt", O_CREAT | O_RDWR | O_APPEND, S_IREAD | S_IWRITE);
ht_printk("yaffs open finsh\r\n");
ht_printk("yaffs write\r\n");
i=yaffs_write(file,BufWriteTo,256);
ht_printk("yaffs read\r\n");
i=yaffs_pread(file,BufToRead,256,0);
ht_printk("yaffs_pread: ");
for(i=0;i<256;i++)
ht_printk("%02x ",BufToRead[i]);
ht_printk("\r\n");
yaffs_close(file);
}