📄 nandflash_k9f1g08u0a.c
字号:
/**********************************************************************
* $Id$ nandflash_k9f1g08u0a.c 2011-06-02
*//**
* @file nandflash_k9f1g08u0a.c
* @brief This c file contains all functions support for Nand Flash
* SamSung K9F1G08U0A
* @version 1.0
* @date 02. June. 2011
* @author NXP MCU SW Application Team
*
* Copyright(C) 2011, NXP Semiconductor
* All rights reserved.
*
***********************************************************************
* Software that is described herein is for illustrative purposes only
* which provides customers with programming information regarding the
* products. This software is supplied "AS IS" without any warranties.
* NXP Semiconductors assumes no responsibility or liability for the
* use of the software, conveys no license or title under any patent,
* copyright, or mask work right to the product. NXP Semiconductors
* reserves the right to make changes in the software without
* notification. NXP Semiconductors also make no representation or
* warranty that such application will be suitable for the specified
* use without further testing or modification.
**********************************************************************/
#include "nandflash_k9f1g08u0a.h"
#include "lpc177x_8x_emc.h"
#include "lpc177x_8x_clkpwr.h"
#include "lpc177x_8x_pinsel.h"
#include "lpc177x_8x_timer.h"
uint8_t InvalidBlockTable[NANDFLASH_NUMOF_BLOCK];
/*********************************************************************//**
* @brief Ready/Busy check, no timeout, basically, R/B bit should
* once to bail out from this routine
* @param[in] None
* @return None
**********************************************************************/
void NandFlash_WaitForReady( void )
{
uint8_t i;
while( FIO0PIN & (1 << 16) ); /* from high to low once */
while( !(FIO0PIN & (1 << 16)) ); /* from low to high once */
return;
}
/*********************************************************************//**
* @brief Initialize external NAND FLASH memory
* @param[in] None
* @return None
**********************************************************************/
void NandFlash_Init( void )
{
uint32_t i;
TIM_TIMERCFG_Type TIM_ConfigStruct;
/**************************************************************************
* Initialize EMC for NAND FLASH
**************************************************************************/
EMC_Init();
LPC_EMC->Control = EMC_Control_E|(1<<1);
EMC_StaMemConfigMW (2,EMC_StaticConfig_MW_8BITS);
EMC_StaMemConfigPB(2,EMC_StaticConfig_PB);
EMC_SetStaMemoryParameter(2, EMC_STA_MEM_WAITWEN, EMC_StaticWaitWen_WAITWEN(2));
EMC_SetStaMemoryParameter(2, EMC_STA_MEM_WAITOEN, EMC_StaticWaitOen_WAITOEN(2));
EMC_SetStaMemoryParameter(2, EMC_STA_MEM_WAITWR, EMC_StaticWaitwr_WAITWR(0x1f));
EMC_SetStaMemoryParameter(2, EMC_STA_MEM_WAITPAGE, EMC_StaticwaitPage_WAITPAGE(0x1f));
EMC_SetStaMemoryParameter(2, EMC_STA_MEM_WAITWR, EMC_StaticWaitwr_WAITWR(0x1f));
EMC_SetStaMemoryParameter(2, EMC_STA_MEM_WAITTURN, EMC_StaticWaitTurn_WAITTURN(0x1f));
// init timer
TIM_ConfigStruct.PrescaleOption = TIM_PRESCALE_USVAL;
TIM_ConfigStruct.PrescaleValue = 1;
// Set configuration for Tim_config and Tim_MatchConfig
TIM_Init(LPC_TIM0, TIM_TIMER_MODE,&TIM_ConfigStruct);
// wait 2ms
TIM_Waitms(2);
/* assume all blocks are valid to begin with */
for ( i = 0; i < NANDFLASH_NUMOF_BLOCK; i++ )
{
InvalidBlockTable[i] = 0;
}
return;
}
/*********************************************************************//**
* @brief Issue Reset command to NAND FLASH memory
* @param[in] None
* @return None
**********************************************************************/
void NandFlash_Reset( void )
{
volatile uint8_t *pCLE;
/* Reset NAND FLASH through NAND FLASH command */
pCLE = K9F1G_CLE;
*pCLE = K9FXX_RESET;
TIM_Waitms(2);
return;
}
/*********************************************************************//**
* @brief Read status from NAND FLASH memory
* @param[in] Cmd command for read operation, should be:
* - K9FXX_BLOCK_PROGRAM_1
* - K9FXX_BLOCK_ERASE_1
* - K9FXX_READ_1
* @return Status, could be:
* - TRUE: pass
* - FALSE: Failure
**********************************************************************/
Bool NandFlash_ReadStatus(uint32_t Cmd)
{
volatile uint8_t *pCLE;
volatile uint8_t *pDATA;
uint8_t StatusData;
pCLE = K9F1G_CLE;
pDATA = K9F1G_DATA;
*pCLE = K9FXX_READ_STATUS;
#if (_CUR_USING_NANDFLASH == _RUNNING_NANDFLASH_K9F1G08U0C)
while ( (*pDATA & 0xC0) != 0xC0 );
#else
/* Wait until bit 5 and 6 are 1, READY, bit 7 should be 1 too, not protected */
/* if ready bit not set, it gets stuck here */
while ( (*pDATA & 0xE0) != 0xE0 );
#endif
StatusData = *pDATA;
switch (Cmd)
{
case K9FXX_BLOCK_PROGRAM_1:
case K9FXX_BLOCK_ERASE_1:
if (StatusData & 0x01) /* Erase/Program failure(1) or pass(0) */
return(FALSE);
else
return(TRUE);
case K9FXX_READ_1: /* bit 5 and 6, Read busy(0) or ready(1) */
return(TRUE);
default:
break;
}
return(FALSE);
}
/*********************************************************************//**
* @brief Read ID from external NAND FLASH memory
* @param[in] None
* @return ID value
**********************************************************************/
uint32_t NandFlash_ReadId( void )
{
uint8_t a, b, c, d;
volatile uint8_t *pCLE;
volatile uint8_t *pALE;
volatile uint8_t *pDATA;
pCLE = K9F1G_CLE;
pALE = K9F1G_ALE;
pDATA = K9F1G_DATA;
*pCLE = K9FXX_READ_ID;
*pALE = 0;
a = *pDATA;
b = *pDATA;
d = *pDATA;
c = *pDATA;
return ((a << 24) | (b << 16) | (c << 8) | d);
}
/*********************************************************************//**
* @brief Erase the whole NAND FLASH memory block based on the
* block number
* @param[in] blockNum number of block that will be erased, should
* be in range: 0 .. 1023
* @return Erase status, could be:
* - TRUE: pass
* - FALSE: failure
**********************************************************************/
Bool NandFlash_BlockErase( uint32_t blockNum )
{
volatile uint8_t *pCLE;
volatile uint8_t *pALE;
uint32_t rowAddr;
pCLE = K9F1G_CLE;
pALE = K9F1G_ALE;
rowAddr = (NANDFLASH_BASE_ADDR + blockNum * NANDFLASH_BLOCK_FSIZE);
rowAddr = rowAddr - (rowAddr % NANDFLASH_BLOCK_FSIZE);
*pCLE = K9FXX_BLOCK_ERASE_1;
*pALE = (uint8_t)(rowAddr & 0x00FF); /* column address low */
*pALE = (uint8_t)((rowAddr & 0xFF00) >> 8); /* column address high */
*pCLE = K9FXX_BLOCK_ERASE_2;
NandFlash_WaitForReady();
return(NandFlash_ReadStatus(K9FXX_BLOCK_ERASE_1));
}
/*********************************************************************//**
* @brief This routine is used to check if the block is valid or
* not.
* @param[in] None
* @return Checking status, could be:
* - TRUE: all blocks are valid
* - FALSE: invalid block is found, an initial invalid
* table will be created
**********************************************************************/
Bool NandFlash_ValidBlockCheck( void )
{
volatile uint8_t *pCLE;
volatile uint8_t *pALE;
volatile uint8_t *pDATA;
uint32_t block, page;
Bool retValue = TRUE;
uint32_t curAddr, tmp;
uint8_t data = 0;
pCLE = K9F1G_CLE;
pALE = K9F1G_ALE;
pDATA = K9F1G_DATA;
for ( block = 0; block < NANDFLASH_NUMOF_BLOCK; block++ )
{
for ( page = 0; page < 2; page++ )
{
/* Check column address 2048 at first page and second 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] = 1;
//At least one block is invalid
retValue = FALSE;
}
}
}
return(retValue);
}
/*********************************************************************//**
* @brief Write a full page of program into NAND flash based on the
* page number, write up to 2112 bytes of data at a time.
* @param[in] pageNum number of page that will be programmed, should
* be in range: 0..63
* @param[in] blockNum number of block that will be programmed, should
* be in range: 0..1023
* @param[in] bufPtr pointer to the buffer that contain data will be
* programmed in flash memory
* @return Program status, could be:
* - TRUE: success
* - FALSE: fail
**********************************************************************/
Bool NandFlash_PageProgram( uint32_t pageNum, uint32_t blockNum, uint8_t *bufPtr )
{
volatile uint8_t *pCLE;
volatile uint8_t *pALE;
volatile uint8_t *pDATA;
uint32_t i, curAddr, curColumm;
pCLE = K9F1G_CLE;
pALE = K9F1G_ALE;
pDATA = K9F1G_DATA;
curAddr = NANDFLASH_BASE_ADDR + blockNum * NANDFLASH_BLOCK_FSIZE
+ pageNum * NANDFLASH_PAGE_FSIZE;
curColumm = curAddr % NANDFLASH_PAGE_FSIZE;
curAddr -= curColumm;
*pCLE = K9FXX_BLOCK_PROGRAM_1;
*pALE = (uint8_t)(curColumm & 0x000000FF); /* column address low */
*pALE = (uint8_t)((curColumm & 0x00000F00) >> 8); /* column address high */
*pALE = (uint8_t)((curAddr & 0x00FF0000) >> 16); /* row address low */
*pALE = (uint8_t)((curAddr & 0xFF000000) >> 24); /* row address high */
//Not write to spare area for the NandFlash valid block checking
for ( i = 0; i < NANDFLASH_RW_PAGE_SIZE; i++ )
{
*pDATA = *bufPtr++;
}
*pCLE = K9FXX_BLOCK_PROGRAM_2;
NandFlash_WaitForReady();
return( NandFlash_ReadStatus( K9FXX_BLOCK_PROGRAM_1 ) );
}
/*********************************************************************//**
* @brief Read the whole NAND FLASH memory page based on the
* page number, the data will be stored in the pointer
* to the buffer.
* @param[in] pageNum number of page that will be read, should
* be in range: 0..63
* @param[in] blockNum number of block that will be read, should
* be in range: 0..1023
* @param[in] bufPtr pointer to the buffer that contain data will be
* read from flash memory
* @return Read status, could be:
* - TRUE: success
* - FALSE: fail
**********************************************************************/
Bool NandFlash_PageRead( uint32_t pageNum, uint32_t blockNum, uint8_t *bufPtr )
{
return (NandFlash_PageReadFromBeginning(pageNum, blockNum, bufPtr) != 0);
}
/*********************************************************************//**
* @brief Read the whole NAND FLASH memory page based on the
* page number, the data will be stored in the pointer
* to the buffer.
* @param[in] pageNum number of page that will be read, should
* be in range: 0..63
* @param[in] blockNum number of block that will be read, should
* be in range: 0..1023
* @param[in] bufPtr pointer to the buffer that contain data will be
* read from flash memory
* @return number of byte(s) read til the end of the page
**********************************************************************/
int NandFlash_PageReadFromBeginning(uint32_t blockNum, uint32_t pageNum, uint8_t* bufPtr)
{
return (NandFlash_PageReadFromAddr(blockNum, pageNum, 0, bufPtr, NANDFLASH_PAGE_FSIZE));
}
/*********************************************************************//**
* @brief Read the whole NAND FLASH memory page based on the
* page number, the data will be stored in the pointer
* to the buffer.
* @param[in] blockNum number of block that will be read, should
* be in range: 0..1023
* @param[in] pageNum number of page that will be read, should
* be in range: 0..63
* @param[in] addrInPage the address in NandFlash to be read,
* calculated from the beginning of page
* @param[in] bufPtr pointer to the buffer that contain data will be
* read from flash memory
* @param[in] size the number of byte(s) to be read and stored to the buffer
* @return number of byte(s) read til the end of the page
**********************************************************************/
int NandFlash_PageReadFromAddr(uint32_t blockNum, uint32_t pageNum,
uint32_t addrInPage, uint8_t* bufPtr, uint32_t size)
{
uint32_t curAddr = 0;
curAddr += NANDFLASH_BASE_ADDR + blockNum * NANDFLASH_BLOCK_FSIZE;
curAddr += pageNum * NANDFLASH_PAGE_FSIZE;
curAddr += addrInPage;
return (NandFlash_ReadFromAddr(curAddr, bufPtr, size));
}
/*********************************************************************//**
* @brief Read the whole NAND FLASH memory at an expected address,
* the data will be stored in the pointer to the buffer.
* @param[in] addrInWholeNand the address in NandFlash to be read,
* calculated from the beginning of Nand base address 0
* @param[in] bufPtr pointer to the buffer that contain data will be
* read from flash memory
* @param[in] size the number of byte(s) to be read and stored to the buffer
* @return number of byte(s) read til the end of the page
**********************************************************************/
int NandFlash_ReadFromAddr(uint32_t addrInWholeNand, uint8_t* bufPtr, uint32_t size)
{
volatile uint8_t *pCLE;
volatile uint8_t *pALE;
volatile uint8_t *pDATA;
uint32_t i, curColumm, curRow;
i = 0;
pCLE = K9F1G_CLE;
pALE = K9F1G_ALE;
pDATA = K9F1G_DATA;
curColumm = addrInWholeNand % NANDFLASH_PAGE_FSIZE;
curRow = addrInWholeNand - curColumm;
*pCLE = K9FXX_READ_1;
*pALE = (uint8_t)(curColumm & 0x000000FF); /* column address low */
*pALE = (uint8_t)((curColumm & 0x00000F00) >> 8); /* column address high */
*pALE = (uint8_t)((curRow & 0x00FF0000) >> 16); /* row address low */
*pALE = (uint8_t)((curRow & 0xFF000000) >> 24); /* row address high */
*pCLE = K9FXX_READ_2;
NandFlash_WaitForReady();
//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 = *pDATA;
bufPtr++;
if((i + 1) >= size)
break;
}
// Ok, return
return i;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -