/****************************************************************************** * Function Name : FSMC_NAND_Test * Description : NAND test * Input : None * Output : None * Return : None * Attention : None *******************************************************************************/ void FSMC_NAND_Test(void) { uint16_t index; NAND_ADDRESS WriteReadAddr; //FSMC_NAND_Init(); // already done in main printf("\r\n-------------------- NAND FLASH TEST -------------------------"); /* NAND memory address to write to */ WriteReadAddr.Zone = 0x00; WriteReadAddr.Block = 0x00; WriteReadAddr.Page = 0x00; /* Erase the NAND first Block */ FSMC_NAND_EraseBlock(WriteReadAddr); /* Fill the buffer to send */ for (index = 0; index < NAND_PAGE_SIZE; index++ ) { NAND_TxBuffer[index] = index; } /* Write data to FSMC NAND memory */ FSMC_NAND_WriteSmallPage(NAND_TxBuffer, WriteReadAddr, 1); /* Read back the written data */ FSMC_NAND_ReadSmallPage (NAND_RxBuffer, WriteReadAddr, 1); if( memcmp( (char*)NAND_TxBuffer, (char*)NAND_RxBuffer, NAND_PAGE_SIZE ) == 0 ) { printf("\r\n - Result : Nand Flash is OK"); } else { printf("\r\n - Result : Nand Flash is error"); } }
/******************************************************************************* * Function Name : NAND_Copy * Description : Copy page * Input : None * Output : None * Return : Status *******************************************************************************/ static uint16_t NAND_Copy (NAND_ADDRESS Address_Src, NAND_ADDRESS Address_Dest, uint16_t PageToCopy) { uint8_t Copybuff[2048]; for ( ; PageToCopy > 0 ; PageToCopy-- ) { FSMC_NAND_ReadSmallPage ((uint8_t *)Copybuff, Address_Src , 1 ); FSMC_NAND_WriteSmallPage ((uint8_t *)Copybuff, Address_Dest, 1 ); FSMC_NAND_AddressIncrement(&Address_Src); FSMC_NAND_AddressIncrement(&Address_Dest); } return NAND_OK; }
/** * @brief Main program. * @param None * @retval : None */ int main(void) { /* System Clocks Configuration */ RCC_Configuration(); /* PF.06, PF.07 and PF.08 config to drive LD1, LD2 and LD3 *****************/ /* Enable GPIOF clock */ RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOF, ENABLE); /* Configure PF.06, PF.07 and PF.08 as Output push-pull */ GPIO_InitStructure.GPIO_Pin = GPIO_Pin_6 | GPIO_Pin_7 | GPIO_Pin_8; GPIO_InitStructure.GPIO_Speed = GPIO_Speed_50MHz; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_Out_PP; GPIO_Init(GPIOF, &GPIO_InitStructure); /* Enable the FSMC Clock */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); /* FSMC Initialization */ FSMC_NAND_Init(); /* NAND read ID command */ FSMC_NAND_ReadID(&NAND_ID); /* Verify the NAND ID */ if((NAND_ID.Maker_ID == NAND_ST_MakerID) && (NAND_ID.Device_ID == NAND_ST_DeviceID)) { /* NAND memory address to write to */ WriteReadAddr.Zone = 0x00; WriteReadAddr.Block = 0x00; WriteReadAddr.Page = 0x00; /* Erase the NAND first Block */ status = FSMC_NAND_EraseBlock(WriteReadAddr); /* Write data to FSMC NAND memory */ /* Fill the buffer to send */ Fill_Buffer(TxBuffer, BUFFER_SIZE , 0x66); status = FSMC_NAND_WriteSmallPage(TxBuffer, WriteReadAddr, PageNumber); /* Read back the written data */ status = FSMC_NAND_ReadSmallPage (RxBuffer, WriteReadAddr, PageNumber); /* Verify the written data */ for(j = 0; j < BUFFER_SIZE; j++) { if(TxBuffer[j] != RxBuffer[j]) { WriteReadStatus++; } } if (WriteReadStatus == 0) { /* OK */ /* Turn on LD1 */ GPIO_SetBits(GPIOF, GPIO_Pin_6); } else { /* KO */ /* Turn on LD2 */ GPIO_SetBits(GPIOF, GPIO_Pin_7); } } else { /* Turn on LD3 */ GPIO_SetBits(GPIOF, GPIO_Pin_8); } while(1) { } }
/******************************************************************************* * Function Name : NAND_Write * Description : write one sector by once * Input : None * Output : None * Return : Status *******************************************************************************/ uint16_t NAND_Write(uint32_t Memory_Offset, uint32_t *Writebuff, uint16_t Transfer_Length) { char rdBuff[NAND_PAGE_SIZE]; int index; /* check block status and calculate start and end addreses */ wAddress = NAND_GetAddress(Memory_Offset / NAND_PAGE_SIZE); printf("\r\nwrite ok\r\n"); /*check Zone: if second zone is requested build second LUT*/ if (wAddress.Zone != CurrentZone) { CurrentZone = wAddress.Zone; NAND_BuildLUT(CurrentZone); } phBlock = LUT[wAddress.Block]; /* Block Index + flags */ LogAddress = wAddress.Block ; /* save logical block */ /* IDLE state */ /****************/ if ( Write_State == WRITE_IDLE) {/* Idle state */ if (phBlock & USED_BLOCK) { /* USED BLOCK */ Block_State = OLD_BLOCK; /* Get a free Block for swap */ fAddress.Block = NAND_GetFreeBlock(); fAddress.Zone = wAddress.Zone; Initial_Page = fAddress.Page = wAddress.Page; /* write the new page */ FSMC_NAND_WriteSmallPage((uint8_t *)Writebuff, fAddress, PAGE_TO_WRITE); Written_Pages++; /* get physical block */ wAddress.Block = phBlock & 0x3FF; if (Written_Pages == SCSI_BlkLen) { NAND_Write_Cleanup(); Written_Pages = 0; return NAND_OK; } else { if (wAddress.Page == (NAND_BLOCK_SIZE - 1)) { NAND_Write_Cleanup(); return NAND_OK; } Write_State = WRITE_ONGOING; return NAND_OK; } } else {/* UNUSED BLOCK */ Block_State = UNUSED_BLOCK; /* write the new page */ wAddress.Block = phBlock & 0x3FF; FSMC_NAND_WriteSmallPage( (uint8_t *)Writebuff , wAddress, PAGE_TO_WRITE); Written_Pages++; if (Written_Pages == SCSI_BlkLen) { Written_Pages = 0; NAND_Write_Cleanup(); return NAND_OK; } else { Write_State = WRITE_ONGOING; return NAND_OK; } } } /* WRITE state */ /***************/ if ( Write_State == WRITE_ONGOING) {/* Idle state */ if (phBlock & USED_BLOCK) { /* USED BLOCK */ wAddress.Block = phBlock & 0x3FF; Block_State = OLD_BLOCK; fAddress.Page = wAddress.Page; /* check if next pages are in next block */ if (wAddress.Page == (NAND_BLOCK_SIZE - 1)) { /* write Last page */ FSMC_NAND_WriteSmallPage( (uint8_t *)Writebuff , fAddress, PAGE_TO_WRITE); Written_Pages++; if (Written_Pages == SCSI_BlkLen) { Written_Pages = 0; } /* Clean up and Update the LUT */ NAND_Write_Cleanup(); Write_State = WRITE_IDLE; return NAND_OK; } /* write next page */ FSMC_NAND_WriteSmallPage( (uint8_t *)Writebuff , fAddress, PAGE_TO_WRITE); Written_Pages++; if (Written_Pages == SCSI_BlkLen) { Write_State = WRITE_IDLE; NAND_Write_Cleanup(); Written_Pages = 0; } } else {/* UNUSED BLOCK */ wAddress.Block = phBlock & 0x3FF; /* check if it is the last page in prev block */ if (wAddress.Page == (NAND_BLOCK_SIZE - 1)) { /* write Last page */ FSMC_NAND_WriteSmallPage( (uint8_t *)Writebuff , wAddress, PAGE_TO_WRITE); Written_Pages++; if (Written_Pages == SCSI_BlkLen) { Written_Pages = 0; } /* Clean up and Update the LUT */ NAND_Write_Cleanup(); Write_State = WRITE_IDLE; return NAND_OK; } /* write next page in same block */ FSMC_NAND_WriteSmallPage( (uint8_t *)Writebuff , wAddress, PAGE_TO_WRITE); Written_Pages++; if (Written_Pages == SCSI_BlkLen) { Write_State = WRITE_IDLE; NAND_Write_Cleanup(); Written_Pages = 0; } } } return NAND_OK; }
void Task1 (void *pdata) { NAND_IDTypeDef NAND_ID; NAND_ADDRESS WriteReadAddr; char pStr[64]; u8 nFlag; __IO uint32_t PageNumber = 2; pdata = pdata; /* Prevent compiler warning */ RCC_AHBPeriphClockCmd(RCC_AHBPeriph_FSMC, ENABLE); FSMC_NAND_Init(); /* NAND memory address to write to */ WriteReadAddr.Zone = 0x00; WriteReadAddr.Block = 0x00; WriteReadAddr.Page = 0x00; /* Erase the NAND first Block */ status = FSMC_NAND_EraseBlock(WriteReadAddr); Fill_Buffer(TxBuffer, BUFFER_SIZE , 0x66); status = FSMC_NAND_WriteSmallPage(TxBuffer, WriteReadAddr, PageNumber); status = FSMC_NAND_ReadSmallPage (RxBuffer, WriteReadAddr, PageNumber); for(;;) { FSMC_NAND_ReadID(&NAND_ID); sprintf(pStr, "Nand Flash ID = %02X,%02X,%02X,%02X ", NAND_ID.Maker_ID, NAND_ID.Device_ID, NAND_ID.Third_ID, NAND_ID.Fourth_ID); // UART_Print(pStr); nFlag = 1; if ((NAND_ID.Maker_ID == 0xEC) && (NAND_ID.Device_ID == 0xF1) && (NAND_ID.Third_ID == 0x80) && (NAND_ID.Fourth_ID == 0x15)) { // UART_Print("Type = K9F1G08U0A\n\r"); nFlag = 2; } else if ((NAND_ID.Maker_ID == 0xEC) && (NAND_ID.Device_ID == 0xF1) && (NAND_ID.Third_ID == 0x00) && (NAND_ID.Fourth_ID == 0x95)) { // UART_Print("Type = K9F1G08U0B\n\r"); nFlag = 3; } else if ((NAND_ID.Maker_ID == 0xEC) && (NAND_ID.Device_ID == 0xF1) && (NAND_ID.Fourth_ID == 0x15)) { // UART_Print("Type = K9F1G08U0M\n\r"); nFlag = 6; } else if ((NAND_ID.Maker_ID == 0xAD) && (NAND_ID.Device_ID == 0xF1) && (NAND_ID.Third_ID == 0x80) && (NAND_ID.Fourth_ID == 0x1D)) { // UART_Print("Type = HY27UF081G2A\n\r"); nFlag = 4; } else { // UART_Print("Type = Unknow\n\r"); nFlag = 5; } OSTimeDly(500); } }