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

📄 wearleveling.c

📁 Nand Flash Translation Layer 用于nandflash的操作。 bad block memory map garbage collection average er
💻 C
📖 第 1 页 / 共 2 页
字号:
 

#include "OSModule_MemoryManagement.h"
#include "common.h"
#include "FalUserDirective.h"
#include "HardwareAdaptationLayer.h"
#include "BadBlockManagement.h"
#include "WearLeveling.h"

typedef struct abtPageBuffer
{
	INT8 pageNumber;
	UINT16 buffer[SECTOR_SIZE / sizeof(UINT16)];
}abtBuffer;

static INT16 ABTBlockPosition = 0;
static INT8 pageOffset = 0;
static FreeBlockInformation *FreeBlockListHead;
static InvalidBlockInformation *InvalidBlockListHead;
static abtBuffer ABTPageBuffer;
static UINT8 NoOfDivision = 0;
static INT8 noOfPages = -1;
static UINT8 wl_pageInBlock = 0;
static UINT16 lastPageSize = 0;

INT32 gInvalidBlocks = 0;
UINT16 ABT[BLOCK_IN_PARTITION];


abtBuffer GetWLABTPageBuffer(void);

/**********************************************************
*					   InitWearLeveling					  *
***********************************************************
* Search the ABT in the device and if it is present stores* 
* the block position of it								  *
*---------------------------------------------------------*
*	RETURN VALUE										  *
*		SUCCESS : ABT founded   						  *
*		FAILURE : ABT not founded or error generic error  *
***********************************************************/

NFTL_Return InitWearLeveling()
{
	INT16 blockIndex;

	UINT8 buf[BUFFER_SPARE_SIZE];
	UINT8 founded = 0;

	//FREE buffer
	ABTPageBuffer.pageNumber = ((INT8) - 1);
	OS_MemSet(ABTPageBuffer.buffer,0x00,SECTOR_SIZE);

	SetWLFreeBlockListHead(NULL);
	SetWLABTBlockPosition(-1);

	//retrieve the proprietries of the device
	if (GetWLnoOfPages() == -1)
	{
		SetABTDimensions() ;
		
	}

	//search the abt starting from the last block of the partition
	//for each block in flash read the first spare area
	for (blockIndex = UD_END_PARTITION;
		blockIndex > UD_END_PARTITION - SEARCH_RANGE;
		blockIndex--)
	{
		if (!founded)
		{
			SetWLpageOffset(0);

			//GetPageStatus(blockIndex,GetWLpageOffset(),buf) ;
				ReadSpare528(blockIndex,GetWLpageOffset(),buf) ;

			//abt founded
			if (buf[PAGE_STATUS_BYTE] == ABT_PAGE)
			{
				founded = 1;
				SetWLABTBlockPosition(blockIndex);
				SetWLNoOfDivision(buf[NUMBER_OF_DIVISION_BYTE]);
				//search the last abt written in this block
				while ((GetWLpageOffset() + GetWLnoOfPages() + GetWLnoOfPages()) <
					GetWLpageInBlock())
				{
					//GetPageStatus(blockIndex,GetWLpageOffset() + GetWLnoOfPages(),buf);
					ReadSpare528(blockIndex,GetWLpageOffset() + GetWLnoOfPages(),buf);

					//there is a most recent abt version
					if (buf[PAGE_STATUS_BYTE] == ABT_PAGE)
					{
						//set new offset in block
						SetWLpageOffset(GetWLpageOffset() + GetWLnoOfPages());
						SetWLNoOfDivision(buf[NUMBER_OF_DIVISION_BYTE]);
					}
					else
					{
						break;
					}
				}
			}
		}
		else
		{
			break;
		}
	}

	//no abt founded
	if (GetWLABTBlockPosition() == -1)
	{
		return FAILURE;
	}
	return SUCCESS;
}


/********************************************************
*					CreateEmptyABT						*
*-------------------------------------------------------*
*	Create the ABT in RAM with each entry set to 1		*
*  and write it in flash								*
*********************************************************/
NFTL_Return CreateEmptyABT()
{
	INT32 blockIndex;
	UINT8 buf[BUFFER_SPARE_SIZE];
	UINT8 founded = 0;


	SetWLFreeBlockListHead(NULL);
	SetWLABTBlockPosition(-1);
	SetWLNoOfDivision(0);

	//FREE buffer
	ABTPageBuffer.pageNumber = -1;
	OS_MemSet(ABTPageBuffer.buffer,0x00,SECTOR_SIZE);

	//retrieve the proprietries of the device
	if (GetWLnoOfPages() == -1)
	{
		SetABTDimensions() ;
		
	}


	//write the abt in flash in the first FREE block
	for (blockIndex = UD_END_PARTITION;
		blockIndex > UD_END_PARTITION - SEARCH_RANGE;
		blockIndex--)
	{
		if (!founded)
		{
			//GetPageStatus(blockIndex,0,buf);
			ReadSpare528(blockIndex,0,buf);

			//founded FREE block
			if (buf[BLOCK_STATUS_BYTE] == FREE_BLOCK)
			{
				INT16 i = 0;
				founded = 1;
				SetWLABTBlockPosition(blockIndex);
				SetWLpageOffset(0);
				for (i = 0; i < GetWLnoOfPages(); i++)
				{
					UINT16 k;
					UINT8 buf1[SECTOR_SIZE + BUFFER_SPARE_SIZE];
					OS_MemSet(&buf1[SECTOR_SIZE ],0xFF, BUFFER_SPARE_SIZE);
					for (k = 0; k < (SECTOR_SIZE / sizeof(UINT16)); k++)
					{
						((UINT16 *) buf1)[k] = 1;
					}

					//first page
					if (i == 0)
					{
						//write abt flag in spare
						buf1[SECTOR_SIZE + PAGE_STATUS_BYTE] = ABT_PAGE;


						buf1[SECTOR_SIZE + NUMBER_OF_DIVISION_BYTE] = GetWLNoOfDivision();
					}

					//if (WritePage(GetWLABTBlockPosition(),i,buf1) != SUCCESS)
						if (Write528(GetWLABTBlockPosition(),i,buf1) != SUCCESS)
					{
						SetWLABTBlockPosition(-1);
						return FAILURE;
					}
	#if 0
					if (UD_BUFFER_ENABLED)
					{
						if (FlushBuffer() != SUCCESS)
						{
							return FAILURE;
						}
					}
	#endif
				}
			}
		}
	}

	return SUCCESS;
}






/********************************************************
*					FlushABTImage   					* 
*********************************************************
*	Write in flash the ABT stored in ram				*
*   													*
*-------------------------------------------------------*
*	PARAMETERS  										*
*		ABT: the table to write in flash				*
*	RETURN VALUES   									*
*		SUCCESS: table written  						*
*		FAILURE : error during the write				*
********************************************************/
NFTL_Return FlushABTImage(UINT16 *ABT)
{
	INT16 i;

	ABTPageBuffer.pageNumber = -1;

	//retrieve the proprietries of the device
	if (GetWLnoOfPages() == -1)
	{
		SetABTDimensions() ;

	}

	//there is no space in block
	if ((GetWLpageOffset() + GetWLnoOfPages() + GetWLnoOfPages()) >=
		GetWLpageInBlock() * (CHUNK_SIZE / CHUNK_DATA_SIZE))
	{
		//erase the block
		if (BlockErase(GetWLABTBlockPosition()) != SUCCESS)
		{
			MarkBadBlock(GetWLABTBlockPosition());
			return FAILURE;
		}
		SetWLpageOffset(0);
	}
	else
	{
		SetWLpageOffset(GetWLpageOffset() + GetWLnoOfPages());
	}

	//write in page defined
	//EnableNAND();
	for (i = 0; i < GetWLnoOfPages(); i++)
	{
		UINT8 buf[SECTOR_SIZE + BUFFER_SPARE_SIZE];
		//OS_MemSet(buf,0xFF,SECTOR_SIZE + BUFFER_SPARE_SIZE);
		//last page
		if ((i == GetWLnoOfPages() - 1) && (GetWLlastPageSize()))
		{  
			#if 0
			OS_MemSet(buf,0xFF,SECTOR_SIZE + BUFFER_SPARE_SIZE);
			#endif
			#if 0
				{
	   			 UINT8  mi,*pd;
		 		UINT16 temp = (SECTOR_SIZE + BUFFER_SPARE_SIZE)>>4 ;
		 		pd=(UINT8 *)buf;
		 		mi=0;
				do
				{
					*pd++ = 0xFF ; 			
					*pd++ = 0xFF ;
					*pd++ = 0xFF ;
					*pd++ = 0xFF;
					*pd++ = 0xFF; 
					*pd++ = 0xFF ;
					*pd++ = 0xFF ; 
					*pd++ = 0xFF ; 
					*pd++ = 0xFF ; 			
					*pd++ = 0xFF ;
					*pd++ = 0xFF ;
					*pd++ = 0xFF;
					*pd++ = 0xFF; 
					*pd++ = 0xFF ;
					*pd++ = 0xFF ; 
					*pd++ = 0xFF ; 			 	
				} while((++mi)<temp);
			}
			#endif
			#if 1
			{
	   			UINT16  mi,*pd;
		 		UINT16 temp = (SECTOR_SIZE + BUFFER_SPARE_SIZE)>>4 ;
		 		pd=(UINT16 *)(&buf[0]);
		 		mi=0;
				do
				{
					*pd++ = 0xFFFF ; 			
					*pd++ = 0xFFFF ;
					*pd++ = 0xFFFF ;
					*pd++ = 0xFFFF;
					*pd++ = 0xFFFF; 
					*pd++ = 0xFFFF ;
					*pd++ = 0xFFFF ; 
					*pd++ = 0xFFFF ; 	 	
				} while((++mi)<temp);
			}
			#endif
		
			OS_MemCopy(buf,((UINT8 *) ABT) + (i * SECTOR_SIZE),GetWLlastPageSize());
		}
		else
		{
			#if 0
			OS_MemSet(&buf[SECTOR_SIZE ],0xFF,BUFFER_SPARE_SIZE);
			#endif
			#if 0
			{
			UINT8 *pBuf=(&buf[SECTOR_SIZE ]);
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			*pBuf++ = 0xFF ;
			

			}
			#endif
			#if 1
			{
				UINT16 *pBuf=(UINT16 *)(&buf[SECTOR_SIZE ]);
				*pBuf++ = 0xFFFF ;
				*pBuf++ = 0xFFFF ;
				*pBuf++ = 0xFFFF ;
				*pBuf++ = 0xFFFF ;
				*pBuf++ = 0xFFFF ;
				*pBuf++ = 0xFFFF ;
				*pBuf++ = 0xFFFF ;
				*pBuf++ = 0xFFFF ;
			}
			#endif
			
			OS_MemCopy(buf,((UINT8 *) ABT) + (i * SECTOR_SIZE),SECTOR_SIZE);
			if (i == 0)
			{
				//write abt flag in spare
				buf[SECTOR_SIZE + PAGE_STATUS_BYTE] = ABT_PAGE;
				buf[SECTOR_SIZE + NUMBER_OF_DIVISION_BYTE] = GetWLNoOfDivision();
			}
		}

		#if 0
				if (Write528(GetWLABTBlockPosition(),i + GetWLpageOffset(),buf) != SUCCESS)
		{
			MarkBadBlock(GetWLABTBlockPosition());
			return FAILURE;
		}
		#endif
		{
		      UINT32 returnAddress ;

			returnAddress=mCalculateAddress(GetWLABTBlockPosition(),i + GetWLpageOffset()) ;
	
			if ( NAND_PageProgramWithEcc(returnAddress,buf,CHUNK_SIZE)!=SUCCESS)
			{	
				//DisableNAND() ;
				MarkBadBlock(GetWLABTBlockPosition());
				return FAILURE;
			}
	
		}
	}
	//DisableNAND() ;

#if 0
	if (UD_BUFFER_ENABLED)
	{
		if (FlushBuffer() != SUCCESS)
		{
			MarkBadBlock(GetWLABTBlockPosition());
			return FAILURE;
		}
	}
#endif
	return SUCCESS;
}



/*********************************************************
*					GetBestFreeBlock					 *
**********************************************************
*	Retrieve the best FREE block number 				 *
*   													 *
*	RETURN VALUES   									 *
*		SUCCESS: no error is occured					 *
*		NO_FREE_BLOCKS: there are not FREE block in flash*
********************************************************/
NFTL_Return GetBestFreeBlock(UINT16 *returnBlock)
{
	FreeBlockInformation *temp = GetWLFreeBlockListHead();


	if (GetWLFreeBlockListHead() == NULL)
	{
		return NO_FREE_BLOCKS;
	}


	SetWLFreeBlockListHead((GetWLFreeBlockListHead())->Next);
	*returnBlock = temp->BlockNumber;
	OS_DRIVER_Free(temp);
	temp = NULL;
	return SUCCESS;
}



/************************************************************************
*					AddFreeBlock										*
*************************************************************************
*	Add a FREE block in FBC. The age is set to the age stored   		*
*  ABT +1   															*
*************************************************************************
*	PARAMETERS  														*
*		blockNumber : the block number to add to the list of FREE block *
*   	increment   : indicate how much of block is incresed			*
*   																	*
*	RETURN VALUES   													*
*		SUCCESS : block added to the FREE block chain   				*
*		FAILURE : error adding the block to the FBC 					* 
*************************************************************************/
NFTL_Return AddFreeBlock(UINT16 blockNumber, UINT8 increment)
{
	//localize the age in ABT
	UINT8 pageLocation;
	UINT8 offsetInPage = 0;
	FreeBlockInformation *newBlock, *temp, *prev;
#ifdef NFTL_DEBUG
	UINT8 pageStatus[CHUNK_SPARE_SIZE];
#endif

	offsetInPage = 0;
	newBlock = NULL;

#ifdef NFTL_DEBUG
	if (GetWLABTBlockPosition() == -1)
	{
		return FAILURE;
	} 

⌨️ 快捷键说明

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