⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 am29lv160d.c

📁 AXD下 S3C2440 nor flash program nand flash
💻 C
字号:
/*******************************************************************************/
/*                                                                             */
/*    FILE:     am29lv160d.c()				                                   */
/*																			   */
/*    PURPOSE:  Performs operations specific to the am29lv160d flash device    */
/*              while adhering to the adi device drivers model.                */
/*                                                                             */
/*******************************************************************************/

//----- Includes  -----//

#include "am29lv160d.h"


//---- Function Prototypes  ----//

static ERROR_CODE GetSectorNumber( unsigned long ulAddr, int *pnSector );
static ERROR_CODE GetSectorStartEnd( unsigned long *ulStartOff, unsigned long *ulEndOff, int nSector );
static unsigned long GetFlashStartAddress( unsigned long ulAddr);

static void ReadFlash(unsigned long ulOffset, unsigned short *pusValue );
static void WriteFlash(unsigned long ulOffset, unsigned short usValue );
static void ResetFlash(unsigned long ulStartAddr);

void GetCodes(unsigned short *pnManCode, unsigned short *pnDevCode, unsigned long ulStartAddr);

static ERROR_CODE PollToggleBit(unsigned long ulOffset);
ERROR_CODE EraseBlock( int nBlock, unsigned long ulStartAddr );
ERROR_CODE EraseFlash(unsigned long ulStartAddr);
ERROR_CODE ProgramFlash( unsigned long ulAddr, unsigned short usValue );




//----------- Get Sector Number() ----------//
//
//  PURPOSE
//  	Gets a sector number based on the offset.
//
//  INPUTS
//  	unsigned long ulAddr - absolute address
//		int 	 *pnSector   - pointer to sector number
//
//	RETURN VALUE
//  	ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

static ERROR_CODE GetSectorNumber( unsigned long ulAddr, int *pnSector )
{
	int nSector = 0;
	unsigned long ulMask;					//offset mask
	unsigned long ulOffset;					//offset
	unsigned long ulBlkSize 	= 0x10000;	// Block size 0

	// get offset from absolute address
	ulMask      	  = 0x3fffff;
	ulOffset		  = ulAddr & ulMask;

	// sector numbers for the FLASH A boot sectors
	if(0 < ulOffset < 0x004000)
	{
		nSector = 0;
	}
	else if(ulOffset < 0x006000)
	{
		nSector = 1;
	}
	else if(ulOffset < 0x008000)
	{
		nSector = 2;
	}
	else if(ulOffset < 0x010000)
	{
		nSector = 3;
	}
	else if( 0x010000 <= ulOffset < 0x1fffff)
	{
		nSector = (ulOffset - 0x010000)/ulBlkSize + 3;
	}
	else
	{
		// invalid sector
		return INVALID_SECTOR;
	}

	// if it is a valid sector, set it
	if ( (nSector >= 0) && (nSector < NUM_SECTORS) )
		*pnSector = nSector;

	// else it is an invalid sector
	else
		return INVALID_SECTOR;

	// ok
	return NO_ERR;
}


//----------- Get Sector Start End() ----------//
//
//  PURPOSE
//  	Gets a sector start and end address based on the sector number.
//
//  INPUTS
//  	unsigned long *ulStartOff - pointer to the start offset
//		unsigned long *ulEndOff - pointer to the end offset
//		int nSector - sector number
//
//	RETURN VALUE
//		ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

static ERROR_CODE GetSectorStartEnd( unsigned long *ulStartOff, unsigned long *ulEndOff, int nSector )
{
	// The blocks in the flash memory are asymmetrically arranged
	// Thus we use block sizes to determine the block addresses
	unsigned long  ulBlkSize 	= 0x10000;	// Block size 

	// main block
	if( nSector == 0 )
	{
		*ulStartOff = 0;
		*ulEndOff 	= 0x003fff;
	}
	else if( nSector == 1 )
	{
		*ulStartOff = 0x004000;
		*ulEndOff 	= 0x005fff;
	}
	else if( nSector == 2 )
	{
		*ulStartOff = 0x006000;
		*ulEndOff 	= 0x007fff;
	}
	else if( nSector == 3 )
	{
		*ulStartOff = 0x008000;
		*ulEndOff 	= 0x00ffff;
	}
	else if( (nSector >= 4) && (nSector < 35) )
	{
		*ulStartOff = 0x010000 + (nSector-4) * ulBlkSize;
		*ulEndOff = ( (*ulStartOff) + ulBlkSize );
	}
	else
	  	return INVALID_SECTOR;
	  	
	*ulEndOff -= 1;  	

	// ok
	return NO_ERR;
}


//----------- Get Flash Start Address() ----------//
//
//  PURPOSE
//  	Gets flash start address from an absolute address.
//
//  INPUTS
//  	unsigned long ulAddr - absolute address
//
//	RETURN VALUE
//		unsigned long - Flash start address

static unsigned long GetFlashStartAddress( unsigned long ulAddr)
{

	ERROR_CODE 	  ErrorCode = NO_ERR;		//tells us if there was an error erasing flash
	unsigned long ulFlashStartAddr;			//flash start address
	unsigned long ulSectStartAddr;			//sector start address
	unsigned long ulSectEndAddr;			//sector end address
	unsigned long ulMask;					//offset mask

	// get flash start address from absolute address
	GetSectorStartEnd( &ulSectStartAddr, &ulSectEndAddr, (NUM_SECTORS-1));
	ulMask      	  = ~(ulSectEndAddr);
	ulFlashStartAddr  =  ulAddr & ulMask;

	return(ulFlashStartAddr);
}


//----------- Read Flash() ----------//
//
//  PURPOSE
//  	Reads a value from an address in flash.
//
//  INPUTS
// 		unsigned long ulAddr - the address to read from
// 		int pnValue - pointer to store value read from flash
//
//	RETURN VALUE

static void ReadFlash( unsigned long ulAddr, unsigned short *pusValue )
{
	// set our flash address to where we want to read
	unsigned short *pFlashAddr = (unsigned short *)(ulAddr);

	// read the value
	*pusValue = (unsigned short)*pFlashAddr;
}


//----------- Write Flash() ----------//
//
//  PURPOSE
//  	Write a value to an address in flash.
//
//  INPUTS
//	 	unsigned long  ulAddr - address to write to
//		unsigned short nValue - value to write
//
//	RETURN VALUE

static void WriteFlash( unsigned long ulAddr, unsigned short usValue )
{
	// set the address
	unsigned short *pFlashAddr = (unsigned short *)(ulAddr);

	*pFlashAddr = usValue;
}


//----------- Reset Flash() ----------//
//
//  PURPOSE
//  	Sends a "reset" command to the flash.
//
//	INPUTS
//		unsigned long ulStartAddr - flash start address
//
// 	RETURN VALUE
//  	ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

void ResetFlash(unsigned long ulAddr)
{

	unsigned long ulFlashStartAddr;		//flash start address

	// get flash start address from absolute address
	// The ulAddr should ideally be pointing to the flash start
	// address. However we just verify it here again.
	ulFlashStartAddr = GetFlashStartAddress(ulAddr);

	// send the reset command to the flash
	WriteFlash( ulFlashStartAddr + 0x0555, 0xf0 );
}


//----------- Get Codes() ----------//
//
//  PURPOSE
//  	Sends an "auto select" command to the flash which will allow
//		us to get the manufacturer and device codes.
//
//  INPUTS
//  	int *pnManCode - pointer to manufacture code
//		int *pnDevCode - pointer to device code
//		unsigned long ulStartAddr - flash start address
//
//	RETURN VALUE
//  	ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

void GetCodes(unsigned short *pnManCode, unsigned short *pnDevCode, unsigned long ulAddr)
{

	unsigned long ulFlashStartAddr;		//flash start address

	// get flash start address from absolute address
	// The ulAddr should ideally be pointing to the flash start
	// address. However we just verify it here again.
	ulFlashStartAddr = GetFlashStartAddress(ulAddr);

 	// send the auto select command to the flash
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0xaa );
	WriteFlash( ulFlashStartAddr + 0x0555, 0x55 );
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0x90 );

 	// now we can read the codes
	ReadFlash( ulFlashStartAddr + 0x0000, (unsigned short *)pnManCode );
	*pnManCode &= 0xFFFF;

	ReadFlash( ulFlashStartAddr + 0x0002, (unsigned short *)pnDevCode );
	*pnDevCode &= 0xFFFF;

	// we need to issue another command to get the part out
	// of auto select mode so issue a reset which just puts
	// the device back in read mode
	ResetFlash(ulAddr);
}


//----------- Poll Toggle Bit() ----------//
//
//  PURPOSE
//  	Polls the toggle bit in the flash to see when the operation
//		is complete.
//
//	INPUTS
//	unsigned long ulAddr - address in flash
//
// 	RETURN VALUE
//  	ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

static ERROR_CODE PollToggleBit(unsigned long ulAddr)
{
	ERROR_CODE ErrorCode = NO_ERR;	// flag to indicate error
	unsigned short usVal1;
	unsigned short usVal2;

	// read flash 1 time
	ReadFlash( ulAddr, &usVal1 );

	while( ErrorCode == NO_ERR )
	{
		// read the value 2 times
		ReadFlash( ulAddr, &usVal1 );
		ReadFlash( ulAddr, &usVal2 );

		// XOR to see if any bits are different
		usVal1 ^= usVal2;

		// see if we are toggling
		if( !(usVal1 & 0x40) )
			break;

		// check error bit
		if( !(usVal2 & 0x20) )
			continue;
		else
		{
			// read the value 2 times
			ReadFlash( ulAddr, &usVal1 );
			ReadFlash( ulAddr, &usVal2 );

			// XOR to see if any bits are different
			usVal1 ^= usVal2;

			// see if we are toggling
			if( !(usVal1 & 0x40) )
				break;
			else
			{
				ErrorCode = POLL_TIMEOUT;
				ResetFlash(ulAddr);
			}
		}
	}

	// now return
	return ErrorCode;
}


//----------- Erase Block() ----------//
//
//  PURPOSE
//  	Sends an "erase block" command to the flash.
//
//	INPUTS
//		int nBlock - block to erase
//		unsigned long ulStartAddr - flash start address
//
// 	RETURN VALUE
//  	ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

ERROR_CODE EraseBlock( int nBlock, unsigned long ulAddr )
{
	ERROR_CODE 	  ErrorCode   = NO_ERR;		//tells us if there was an error erasing flash
 	unsigned long ulSectStart = 0x0;		//stores the sector start offset
 	unsigned long ulSectEnd   = 0x0;		//stores the sector end offset(however we do not use it here)
	unsigned long ulFlashStartAddr;			//flash start address

	// get flash start address from absolute address
	// The ulAddr should ideally be pointing to the flash start
	// address. However we just verify it here again.
	ulFlashStartAddr = GetFlashStartAddress(ulAddr);

	// Get the sector start offset
	// we get the end offset too however we do not actually use it for Erase sector
	GetSectorStartEnd( &ulSectStart, &ulSectEnd, nBlock );

	// send the erase block command to the flash
	WriteFlash( (ulFlashStartAddr + 0x0AAA), 0xaa );
	WriteFlash( (ulFlashStartAddr + 0x0555), 0x55 );
	WriteFlash( (ulFlashStartAddr + 0x0AAA), 0x80 );
	WriteFlash( (ulFlashStartAddr + 0x0AAA), 0xaa );
	WriteFlash( (ulFlashStartAddr + 0x0555), 0x55 );

	// the last write has to be at an address in the block
	WriteFlash( (ulFlashStartAddr + ulSectStart), 0x30 );

	// poll until the command has completed
	ErrorCode = PollToggleBit(ulFlashStartAddr + ulSectStart);

 	// block erase should be complete
	return ErrorCode;
}


//----------- Erase Flash() ----------//
//
//  PURPOSE
//  	Sends an "erase all" command to the flash.
//
//	INPUTS
//		unsigned long ulStartAddr - flash start address
//
// 	RETURN VALUE
//  	ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

ERROR_CODE EraseFlash(unsigned long ulAddr)
{
	ERROR_CODE ErrorCode = NO_ERR;	// tells us if there was an error erasing flash
	unsigned long ulFlashStartAddr;	// flash start address

	// get flash start address from absolute address
	// The ulAddr should ideally be pointing to the flash start
	// address. However we just verify it here again.
	ulFlashStartAddr = GetFlashStartAddress(ulAddr);

	// erase contents of Flash
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0xaa );
	WriteFlash( ulFlashStartAddr + 0x0555, 0x55 );
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0x80 );
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0xaa );
	WriteFlash( ulFlashStartAddr + 0x0555, 0x55 );
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0x10 );

	// poll until the command has completed
	ErrorCode = PollToggleBit(ulFlashStartAddr + 0x0000);

	// erase should be complete
	return ErrorCode;
}


//----------- Program Flash() ----------//
//
//  PURPOSE
//  	Sends an "program" command to the flash.
//
//  INPUTS
//	 	unsigned long  ulAddr - address to write to
//		unsigned short nValue - value to write
//
//	RETURN VALUE
//  	ERROR_CODE - value if any error occurs
//  	NO_ERR     - otherwise

ERROR_CODE ProgramFlash( unsigned long ulAddr, unsigned short usValue )
{
	ERROR_CODE ErrorCode = NO_ERR;	// tells us if there was an error erasing flash
	unsigned long ulFlashStartAddr;	// flash start address

	// get flash start address from absolute address
	// The ulAddr should ideally be pointing to the flash start
	// address. However we just verify it here again.
	ulFlashStartAddr = GetFlashStartAddress(ulAddr);

	// unlock flash
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0xaa );
	WriteFlash( ulFlashStartAddr + 0x0555, 0x55 );
	WriteFlash( ulFlashStartAddr + 0x0AAA, 0xa0 );

	// program our actual value now
	WriteFlash( ulFlashStartAddr + ulAddr, usValue );

	// make sure the write was successful
	ErrorCode = PollToggleBit(ulFlashStartAddr + 0x0000);

	return(ErrorCode);
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -