先初始化FSMC
void FSMC_NAND_Init(void)
{
GPIO_InitTypeDef GPIO_InitStructure;
FSMC_NANDInitTypeDef FSMC_NANDInitStructure;
FSMC_NAND_PCCARDTimingInitTypeDef p;
/ Enable FSMC, GPIOD, GPIOE and AFIO clocks /
RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE);
RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOD | RCC_APB2Periph_GPIOE |
RCC_APB2Periph_GPIOG | RCC_APB2Periph_AFIO , ENABLE);
/-- GPIO Configuration ------------------------------------------------------/
/ CLE, ALE, D0->D3, NOE, NWE and NCE2 NAND pin configuration /
GPIO_InitStructureGPIO_Pin = GPIO_Pin_11 | GPIO_Pin_12 | GPIO_Pin_14 | GPIO_Pin_15 |
GPIO_Pin_0 | GPIO_Pin_1 | GPIO_Pin_4 | GPIO_Pin_5;
GPIO_InitStructureGPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructureGPIO_Mode = GPIO_Mode_AF_PP;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/ D4->D7 NAND pin configuration /
GPIO_InitStructureGPIO_Pin = GPIO_Pin_7 | GPIO_Pin_8 | GPIO_Pin_9 | GPIO_Pin_10;
GPIO_Init(GPIOE, &GPIO_InitStructure);
/ CS NAND pin configuration /
GPIO_InitStructureGPIO_Pin = GPIO_Pin_9;
GPIO_Init(GPIOG, &GPIO_InitStructure);
/ NWAIT NAND pin configuration /
GPIO_InitStructureGPIO_Pin = GPIO_Pin_6;
GPIO_InitStructureGPIO_Speed = GPIO_Speed_50MHz;
GPIO_InitStructureGPIO_Mode = GPIO_Mode_IPU;
GPIO_Init(GPIOD, &GPIO_InitStructure);
/-- FSMC Configuration ------------------------------------------------------/
pFSMC_SetupTime = 0x1;
pFSMC_WaitSetupTime = 0x3;
pFSMC_HoldSetupTime = 0x2;
pFSMC_HiZSetupTime = 0x1;
FSMC_NANDInitStructureFSMC_Bank = FSMC_Bank3_NAND;
FSMC_NANDInitStructureFSMC_Waitfeature = FSMC_Waitfeature_Enable;
FSMC_NANDInitStructureFSMC_MemoryDataWidth = FSMC_MemoryDataWidth_8b;
FSMC_NANDInitStructureFSMC_ECC = FSMC_ECC_Enable;
FSMC_NANDInitStructureFSMC_ECCPageSize = FSMC_ECCPageSize_512Bytes;
FSMC_NANDInitStructureFSMC_TCLRSetupTime = 0x00;
FSMC_NANDInitStructureFSMC_TARSetupTime = 0x00;
FSMC_NANDInitStructureFSMC_CommonSpaceTimingStruct = &p;
FSMC_NANDInitStructureFSMC_AttributeSpaceTimingStruct = &p;
FSMC_NANDInit(&FSMC_NANDInitStructure);
/ FSMC NAND Bank Cmd Test /
FSMC_NANDCmd(FSMC_Bank3_NAND, ENABLE);
}
定义一个写函数
uint32_t FSMC_NAND_WriteSmallPage(uint8_t pBuffer, NAND_ADDRESS Address, uint32_t NumPageToWrite)
{
uint32_t index = 0x00, numpagewritten = 0x00, addressstatus = NAND_VALID_ADDRESS;
uint32_t status = NAND_READY, size = 0x00;
uint8_t Page = 0x37;
while((NumPageToWrite != 0x00) && (addressstatus == NAND_VALID_ADDRESS) && (status == NAND_READY))
{
/ Page write command and address /
(vu8 )(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM;
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = 0x00;
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = 0X00;
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
/ Calculate the size /
size = Page + (Page numpagewritten);
/ Write data /
for(; index < size; index++)
{
(vu8 )(NAND_FLASH_START_ADDR | DATA_AREA) = pBuffer[index];
}
(vu8 )(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_PAGEPROGRAM_TRUE;
/ 读忙脚 /
// while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
// while( GPIO_ReadInputDataBit(GPIOD, 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);
}
定义一个数组TxBuffer,然后将数组写入flash
FSMC_NAND_WriteSmallPage(TxBuffer, WriteAddr, 1);
读的过程相反,定义读取函数
uint32_t FSMC_NAND_ReadSmallPage(uint8_t pBuffer, NAND_ADDRESS Address, uint32_t NumPageToRead)
{
uint32_t index = 0x00, numpageread = 0x00, addressstatus = NAND_VALID_ADDRESS;
uint32_t status = NAND_READY, size = 0x00;
uint8_t Page = 0x37;
while((NumPageToRead != 0x0) && (addressstatus == NAND_VALID_ADDRESS))
{
/ Page Read command and page address /
(vu8 )(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_READ_1;
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = 0x00;
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = 0X00;
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_1st_CYCLE(ROW_ADDRESS);
(vu8 )(NAND_FLASH_START_ADDR | ADDR_AREA) = ADDR_2nd_CYCLE(ROW_ADDRESS);
(vu8 )(NAND_FLASH_START_ADDR | CMD_AREA) = NAND_CMD_READ_TRUE;
/ 读忙脚 /
// while( GPIO_ReadInputDataBit(GPIOG, GPIO_Pin_6) == 0 );
// while( GPIO_ReadInputDataBit(GPIOD, GPIO_Pin_6) == 0 );
/ Calculate the size /
size = Page + (Page numpageread);
/ Get Data into Buffer /
for(; index < size; index++)
{
pBuffer[index]= (vu8 )(NAND_FLASH_START_ADDR | DATA_AREA);
}
numpageread++;
NumPageToRead--;
/ Calculate page address /
addressstatus = FSMC_NAND_AddressIncrement(&Address);
}
status = FSMC_NAND_GetStatus();
return (status | addressstatus);
}
首先调用erase,将NAND全部擦除一遍,然后执行如下检测操作,
如果页大于512字节,
badblockpos = 0;
badblockbytes = 2;
如果页小于512字节,
badblockpos = 5;
badblockbytes = 1;
读取每个block的前两页OOB区域的第badblockpos开始的后badblockbytes字节是否为0xff,
如果是,那么说明该block是好的,否则该block是坏块[gliethttp_20080523]!
UINT_T create_bbt(FlashBootType_T fbt)
{
UINT_T Retval;
P_FlashProperties_T pFlashP = GetFlashProperties(fbt);
UINT_T BlkSize,BlkNum;
UINT_T flash_addr;
#define page_size (2048)
#define page_spare_size (64)
#define block_size (64page_size)
#define tmp_buffer_addr (0x80200000 - page_size - page_spare_size)
#define tmp_spare_buffer_addr (tmp_buffer_addr + page_size)
int i,j;
char bbpos;
bbpos = (char)(tmp_spare_buffer_addr + 0);
BlkSize = pFlashP->BlockSize;
BlkNum = pFlashP->NumBlocks;
for(i = 0;i < BlkNum;i++)
{
flash_addr = i BlkSize;
for(j = 0;j < 2;j++)
{
Retval = xdfc_read((UINT_T )tmp_buffer_addr, flash_addr + jpage_size, page_size, (UINT_T )tmp_spare_buffer_addr, GetNANDProperties());
if(Retval)
{
goto __create_bbt_mark;
}
if(bbpos[0] != 0xff)goto __create_bbt_mark;
if(bbpos[1] != 0xff)goto __create_bbt_mark;
}
continue;
__create_bbt_mark:
RelocateBlock( i, &GetFMProperties()->BBT, fbt );
}
}
欢迎分享,转载请注明来源:品搜搜测评网