📄 k9f2g8.c
字号:
/*****************************************************************************
* ex_nandflash.c: External NAND FLASH memory module file for NXP
* LPC23xx Family Microprocessors
*
* Copyright(C) 2006, NXP Semiconductor
* All rights reserved.
*
* History
* 2007.01.13 ver 1.00 Prelimnary version, first Release
*
******************************************************************************/
#include "LPC2468.h" /* LPC23xx/24xx definitions */
#include "K9F2G8.h"
BYTE InvalidBlockTable[K9F2G08_BLOCKNUM];
/*****************************************************************************
** Function name: NF_Check
**
** Descriptions: Ready/Busy check, no timeout, basically, R/B bit
** should toggle once to bail out from this routine.
**
** parameters: None
**
** Returned value: None
**
*****************************************************************************/
void NF_Check( void )
{
while( IOPIN0 & (1 << 24) ); /* from high to low once */
asm("nop");
asm("nop");
while( !(IOPIN0 & (1 << 24)) ); /* from low to high once */
return;
}
/*****************************************************************************
** Function name: NF_Init
**
** Descriptions: initialize external NAND FLASH memory
**
** parameters: None
**
** Returned value: None
**
*****************************************************************************/
void NF_Init( void )
{
DWORD i;
/**************************************************************************
* Initialize EMC for NAND FLASH
**************************************************************************/
EMC_CTRL = 0x00000001;
PCONP |= 0x00000800; /* Turn On EMC PCLK */
//GPIO P025 as CE pin,P024 as Busy Status pin
PINSEL1 &= ( ~0x0f0000 );
IODIR0 = IODIR0
| ( 1<<25 ) //P025 configured as output pin
& ( ~( 1<<24 ) ); //P024 configured as input pin
PINSEL4 = 0x50000000;
PINSEL5 = 0x05050555;
PINSEL6 = 0x55555555; //PIN selected to 16 bit data bus
PINSEL8 = 0x55555555;
PINSEL9 = 0x50555555;
/* for NAND FLASH */
EMC_STA_CFG1 = 0x00000080;
EMC_STA_WAITWEN1 = 0x2;
EMC_STA_WAITOEN1 = 0x2;
EMC_STA_WAITRD1 = 0x1F;
EMC_STA_WAITPAGE1 = 0x1F;
EMC_STA_WAITWR1 = 0x1F;
EMC_STA_WAITTURN1 = 0xF;
// delayMs(1, 2); /* Use timer 1 */
/* assume all blocks are valid to begin with */
for ( i = 0; i < K9F2G08_BLOCKNUM; i++ )
{
InvalidBlockTable[i] = 0;
}
return;
}
/*****************************************************************************
** Function name: NF_Reset
**
** Descriptions: Issue Reset command to NAND FLASH memory
**
** parameters: None
**
** Returned value: None
**
*****************************************************************************/
void NF_Reset( void )
{
volatile BYTE *pCLE;
/* Reset NAND FLASH through NAND FLASH command */
NF_Open();
pCLE = NF_CLE;
*pCLE = K9FXX_RESET;
NF_Close();
// delayMs( 1, 2 ); /* Use timer 1 */
return;
}
/*****************************************************************************
** Function name: NF_ReadStatus
**
** Descriptions: Read status from NAND FLASH memory
**
** parameters: None
**
** Returned value: Status
**
*****************************************************************************/
DWORD NF_ReadStatus( DWORD Cmd )
{
volatile BYTE *pCLE;
volatile BYTE *pDATA;
BYTE StatusData;
NF_Open();
pCLE = NF_CLE;
pDATA = NF_DATA;
*pCLE = K9FXX_READ_STATUS;
/* 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 */
do
{
StatusData = *pDATA;
}while(!(StatusData & 0x40));
NF_Close();
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 );
}
/*****************************************************************************
** Function name: NF_ReadID
**
** Descriptions: Read ID from external NAND FLASH memory
**
** parameters: None
**
** Returned value: Device ID info.
**
*****************************************************************************/
DWORD NF_ReadID( void )
{
BYTE a, b, c, d;
volatile BYTE *pCLE;
volatile BYTE *pALE;
volatile BYTE *pDATA;
NF_Open();
pCLE = NF_CLE;
pALE = NF_ALE;
pDATA = NF_DATA;
*pCLE = K9FXX_READ_ID;
*pALE = 0;
a = *pDATA;
b = *pDATA;
c = *pDATA;
d = *pDATA;
NF_Close();
return ((a << 24) | (b << 16) | (c << 8) | d);
}
/*****************************************************************************
** Function name: NF_EraseBlock
**
** Descriptions: Erase the whole NAND FLASH memory block based on the
** block number
**
** parameters: block number
**
** Returned value: Erase status: succeed or fail
**
*****************************************************************************/
DWORD NF_EraseBlock( DWORD blockNum )
{
volatile BYTE *pCLE;
volatile BYTE *pALE;
DWORD rowAddr;
pCLE = NF_CLE;
pALE = NF_ALE;
NF_Open();
rowAddr = blockNum;
*pCLE = K9FXX_BLOCK_ERASE_1;
*pALE = (BYTE)(rowAddr & 0xFF); /* column address low */
*pALE = (BYTE)((rowAddr & 0xFF00) >> 8); /* column address high */
*pALE = (BYTE)((rowAddr & 0x010000) >> 16); /* column address high */
*pCLE = K9FXX_BLOCK_ERASE_2;
NF_Close();
NF_Check();
return( NF_ReadStatus( K9FXX_BLOCK_ERASE_1 ) );
}
/*****************************************************************************
** Function name: NF_CheckValidBlock
**
** Descriptions: This routine is used to check if the block is valid or
** not.
**
** parameters: None
**
** Returned value: FALSE is invalid block is found, an initial invalid
** table will be created. TRUE if all blocks are valid.
**
*****************************************************************************/
DWORD NF_CheckValidBlock( void )
{
volatile BYTE *pCLE;
volatile BYTE *pALE;
volatile BYTE *pDATA;
DWORD block, page, retValue = TRUE;
DWORD curAddr;
pCLE = NF_CLE;
pALE = NF_ALE;
pDATA = NF_DATA;
NF_Open();
for ( block = 0; block < K9F2G08_BLOCKNUM; block++ )
{
curAddr = K9F2G08_BASE_ADDR
+ block * K9F2G08_PAGE_PER_BLOCK * NF_RW_PAGE_SIZE;
for ( page = 0; page < 2; page++ )
{
/* Check column address 2048 at first page and second page */
curAddr += page * NF_RW_PAGE_SIZE;
*pCLE = K9FXX_READ_1;
*pALE = (BYTE)(curAddr & 0x00000000); /* column address low */
*pALE = (BYTE)((curAddr | 0x00000800) >> 8); /* column address high */
*pALE = (BYTE)((curAddr & 0x00FF0000) >> 16); /* row address low */
*pALE = (BYTE)((curAddr & 0xFF000000) >> 24); /* row address high */
*pALE = (BYTE)((curAddr & 0x0100000000) >> 32); /* row address high */
*pCLE = K9FXX_READ_2;
NF_Check();
if ( *pDATA != 0xFF )
{
/* found invalid block number, mark block number in the invalid
block table. */
InvalidBlockTable[block] = 1;
retValue = FALSE; /* At least one block is invalid. */
}
}
}
NF_Close();
return( retValue );
}
/*****************************************************************************
** Function name: NF_PageProgram
**
** Descriptions: Write a full page of program into NAND flash based on the
** page number, write up to 2112 bytes of data at a time.
**
** parameters: page number, block number, and pointer to the buffer
**
** Returned value: Erase status: succeed or fail
**
*****************************************************************************/
DWORD NF_PageProgram( DWORD pageNum, DWORD blockNum, BYTE *bufPtr )
{
volatile BYTE *pCLE;
volatile BYTE *pALE;
volatile BYTE *pDATA;
DWORD i;
DWORD curAddr;
pCLE = NF_CLE;
pALE = NF_ALE;
pDATA = NF_DATA;
NF_Open();
curAddr = K9F2G08_BASE_ADDR + blockNum * K9F2G08_BLOCKNUM
+ pageNum * NF_RW_PAGE_SIZE;
*pCLE = K9FXX_BLOCK_PROGRAM_1;
*pALE = (BYTE)(curAddr & 0x000000FF); /* column address low */
*pALE = (BYTE)((curAddr & 0x00000F00) >> 8); /* column address high */
*pALE = (BYTE)((curAddr & 0x00FF0000) >> 16); /* row address low */
*pALE = (BYTE)((curAddr & 0xFF000000) >> 24); /* row address high */
*pALE = (BYTE)((curAddr & 0x0100000000) >> 32); /* row address high */
asm("nop");
asm("nop");
for ( i = 0; i < NF_RW_PAGE_SIZE; i++ )
{
*pDATA = *bufPtr++;
}
*pCLE = K9FXX_BLOCK_PROGRAM_2;
asm("nop");
asm("nop");
NF_Close();
NF_Check();
return( NF_ReadStatus( K9FXX_BLOCK_PROGRAM_1 ) );
}
/*****************************************************************************
** Function name: NF_PageRead
**
** Descriptions: Read the whole NAND FLASH memory page based on the
** page number, the data will be stored in the pointer
** to the buffer.
**
** parameters: page number, block number, buffer pointer;
**
** Returned value: Erase status: succeed or fail
**
*****************************************************************************/
DWORD NF_PageRead( DWORD pageNum, DWORD blockNum, BYTE *bufPtr )
{
volatile BYTE *pCLE;
volatile BYTE *pALE;
volatile BYTE *pDATA;
DWORD i;
DWORD curAddr;
pCLE = NF_CLE;
pALE = NF_ALE;
pDATA = NF_DATA;
NF_Open();
curAddr = K9F2G08_BASE_ADDR + blockNum * K9F2G08_BLOCKNUM
+ pageNum * NF_RW_PAGE_SIZE;
*pCLE = K9FXX_READ_1;
*pALE = (BYTE)(curAddr & 0x000000FF); /* column address low */
*pALE = (BYTE)((curAddr & 0x00000F00) >> 8); /* column address high */
*pALE = (BYTE)((curAddr & 0x00FF0000) >> 16); /* row address low */
*pALE = (BYTE)((curAddr & 0xFF000000) >> 24); /* row address high */
*pALE = (BYTE)((curAddr & 0x0100000000) >> 32); /* row address high */
*pCLE = K9FXX_READ_2;
NF_Check();
for ( i = 0; i < NF_RW_PAGE_SIZE; i++ )
{
*bufPtr = *pDATA;
bufPtr++;
}
NF_Close();
return( TRUE );
}
/*********************************************************************************
** End Of File
*********************************************************************************/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -