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

📄 translationmodule.c

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


#include "OSModule_MemoryManagement.h"
#include"BadBlockManagement.h"  
#include"HardwareAdaptationLayer.h"
#include"StructureManager.h"
#include"Common.h"
#include"FALUserDirective.h"
#include"HALUserDirective.h"
#include "WearLeveling.h" 
#include "GarbageCollector.h"
#include "TranslationModule.h"
#include "LLD.h"
#include "mmiSendMessage.h"
#include "NandFat.h"


  
  

#define PHYSICAL_BLOCK_NUMBERS	(UD_END_PARTITION - UD_START_PARTITION + 1)
#define	ACCESSIBLE_BLOCKS		(PHYSICAL_BLOCK_NUMBERS - HIDE_BLOCK_NUMBER - 2)
#define	FIRST_PAGE				0
#define MINIMUM_REWRITINGNUMBER 	1
#define INITIALISED			1
#define NOT_INITIALISED 		0
#define RESEVED_AREA_BLOCK         48

#define NFTL_SEMAPHORE_ID 0x09
#define INTERVAL  50
#define END_POINT  4000


/****************************************************************************
			Data Structure
****************************************************************************/


//VIRTUAL TO PHYSICAL MAPPING TABLE
static void *VirtualToPhysicalMT[ACCESSIBLE_BLOCKS]={NULL};

//Number Of Page Per Physical Block


//Number of Virtual Block used as Main Block (Root Block) 
/*static UINT16 NumberofUsedAccessibleBlock;*/

//system status
static UINT8 isInitialised = NOT_INITIALISED;

UINT32 gFirstGoodBlcok = 0, gLastGoodBlock = 0;
extern FATSYS_STRUCT gNandFATSYS ;
extern const UINT8 *BPBTaBle ;
//extern UINT8 gNFLASHBuf[] ;
extern INT32 gInvalidBlocks;
extern UINT8 SDAndNandFlag ; /*1: NAND; 0: SD*/

static UINT8 gTMBuffer[SECTOR_SIZE + BUFFER_SPARE_SIZE];






//********* END Data Structure *************//



/****************************************************************************
			Private Methods
****************************************************************************/

void UpdateVirtualToPhysicalMT(UINT16 VBIndex, UINT16 NewPhysicalBlockNumber);

NFTL_Return CallGarbageCollection(UINT16 VirtualBlockNumber, UINT8 Sector);
NFTL_Return IsInTable(UINT16 *tempTable, int len, UINT16 value);
NFTL_Return PartialDefrag(UINT16 StartVBIndex, UINT16 EndVBIndex);

extern UINT16 MMI_PutString( INT8 * str);
extern UINT32 NandClusterToAddr(UINT16 clust_no);
extern void OS_DRIVER_ObtainSemaphore (UINT16 SemaId);
extern void OS_DRIVER_ReleaseSemaphore (UINT16 SemaId);



//********* END Private Methods *************//


/***********************  FormatFlash *******************************
* Erase all nand device, except bad blocks, and create  		   *
* the data structures that contain the number of bad blocks and the *
* age of each physical block  										*
*-------------------------------------------------------------------*
*   No Parameters : 								  				*
*																	*
*	return values:													*
*				SUCCESS: flash formatted with success    			*
*				FAILURE: flash no formatted 					 	*
*********************************************************************/

static NFTL_Return FormatFlash(void)
{
	NFTL_Return result, result1;
	UINT16 PhysicalBlockNumber, FirstGoodBlock = UD_END_PARTITION, i; 
	UINT16 LastGoodBlock = UD_START_PARTITION;
	UINT8 PageNumber = 0, SpareBuffer[BUFFER_SPARE_SIZE];
       UINT16 NumberOfBadBlock = 0;
	BadBlockElem bbt, *temp;
	
	if (RecognizeDevice() != SUCCESS)
	{
		return FAILURE;
	}

	if (NFTL_Unmount() != SUCCESS)
	{
		return FAILURE;
	}
#ifdef NFTL_DEBUG
	//Verify the FAL User Directive
	if (PHYSICAL_BLOCK_NUMBERS > GetDeviceArchitecture().numOfBlocks)
	{
		return FAILURE;
	}

	if (HIDE_BLOCK_NUMBER >= (PHYSICAL_BLOCK_NUMBERS - 2))
	{
		return FAILURE;
	}

	if (HIDE_BLOCK_NUMBER < ((MAXIMUM_REWRITING - 1) / 2))
	{
		return FAILURE;
	}
#endif /*NFTL_DEBUG*/

	//reset Virtual to Physical mapping table
	//initialize the VirtualToPhysicalMT
	for (i = 0; i < ACCESSIBLE_BLOCKS; i++)
		VirtualToPhysicalMT[i] = NULL;

	//initialize the HAL data structure to configure the Low Level Driver according to the flash device
	result = HALInitialization();
	if (result == FAILURE)
	{
		return FAILURE;
	}


	//Search the bad block table in the first good block
	result1 = GetBadBlockTable(&bbt,UD_START_PARTITION);
	//unrecoverable error reading BBT
	//is it possible that the falsh is entirely damaged
	if (result1 == FAILURE)
	{
		return FAILURE;
	}

	//search the last good block
	PhysicalBlockNumber = UD_END_PARTITION;

	while (LastGoodBlock == UD_START_PARTITION)
	{
		//read spare area of PhysicalBlockNumber
              UINT32 returnAddress ;
		CalculateAddress(PhysicalBlockNumber,FIRST_PAGE ,&returnAddress) ;
		NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;
		//the block is bad
		//add block to BBT
		if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
		{
			//Write in RAM bbt that the PhysicalBlockNumber is bad
			result = AddBadBlock(PhysicalBlockNumber);
			if (result == FAILURE)
			{
				return FAILURE;
			}
		}
		//the block is good,record the block position
		else
		{
			LastGoodBlock = PhysicalBlockNumber;
		}

		PhysicalBlockNumber--;
	}



	//if device is unformatted
	//create ABT, format the flash creating FBC
	if (result1 == DEVICE_UNFORMATTED)
	{
		result = FAILURE;

		while (result == FAILURE)
		{
			//erase the last block to save within it the ABT
			result = BlockErase(LastGoodBlock);
			if (result == FAILURE)
			{
				//Mark in flash PhysicalBlockNumber as bad
				result1 = MarkBadBlock(LastGoodBlock);
				if (result1 == FAILURE)
				{
					return FAILURE;
				}

				//Write in RAM bbt that the PhysicalBlockNumber is bad
				result1 = AddBadBlock(LastGoodBlock);
				if (result1 == FAILURE)
				{
					return FAILURE;
				}

				LastGoodBlock--;
			}
		}

		//create in flash the empty Aging Block Table 
		result = CreateEmptyABT();
		if (result == FAILURE)
		{
			return FAILURE;
		}		

		//The device is unformatted

		for (PhysicalBlockNumber = UD_START_PARTITION;
			PhysicalBlockNumber < LastGoodBlock;
			PhysicalBlockNumber++)
		{
			//read spare area of PhysicalBlockNumber
			 UINT32 returnAddress ;
			CalculateAddress(PhysicalBlockNumber,PageNumber ,&returnAddress) ;
			NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;
			//the block is bad
			//add it to BBT
			if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
			{
				//Write in RAM bbt that the PhysicalBlockNumber is bad
				result = AddBadBlock(PhysicalBlockNumber);
				if (result == FAILURE)
				{
					return FAILURE;
				}
			}
			//the block is good
			else
			{
				//save the physical block number of first good block
				if (FirstGoodBlock == UD_END_PARTITION)
				{
					FirstGoodBlock = PhysicalBlockNumber;
				}

				//erase block
				result = BlockErase(PhysicalBlockNumber);
				//the block is bad
				//mark it and add to BBT
				if (result == FAILURE)
				{
					//Mark in flash PhysicalBlockNumber as bad
					result = MarkBadBlock(PhysicalBlockNumber);
					if (result == FAILURE)
					{
						return FAILURE;
					}

					//Write in RAM bbt that the PhysicalBlockNumber is bad
					result = AddBadBlock(PhysicalBlockNumber);
					if (result == FAILURE)
					{
						return FAILURE;
					}
				}
				//erased block is good 
				else if (result == NAND_PASS)
				{
					if (PhysicalBlockNumber != FirstGoodBlock)
					{
						//Add OS_Free block in FreeBlockChain of WL

						result = AddFreeBlock(PhysicalBlockNumber,1);


						if (result == FAILURE)
						{
							return FAILURE;
						}
					}
				}
				else
				{
					return FAILURE;
				}
			}
		}

		//update in flash the BBT
		result = FlushBadBlockTable(FirstGoodBlock);
		if (result == FAILURE)
		{
			return FAILURE;
		}
	}
	//if device is formatted
	//initialize STNFTL reading the BBT and ABT
	else
	{
		UINT16 *tempTable = NULL;
		INT32 i;
		UINT8 isFirstGood = 0;

		result = GetBadBlocksNumber(&NumberOfBadBlock);

		//create an array with the bad block number
		if (NumberOfBadBlock != 0)
		{
			temp = &bbt;
			tempTable = (UINT16 *)OS_DRIVER_Malloc(sizeof(UINT16) * NumberOfBadBlock);
			if (tempTable == NULL)
			{
				return FAILURE;
			}

			for (i = 0; i < NumberOfBadBlock; i++)
			{
				tempTable[i] = temp->blockNumber;
				temp = temp->next;
			}
		}

		//search ABT and initialize WL
		result = InitWearLeveling();
		if (result == FAILURE)
		{
			//angelo workaround
			result = CreateEmptyABT();
		}


		//read all first block spare area of partition except bad block
		for (PhysicalBlockNumber = UD_START_PARTITION;
			PhysicalBlockNumber < LastGoodBlock;
			PhysicalBlockNumber++)
		{	
			UINT32 returnAddress;
			if (IsInTable(tempTable,NumberOfBadBlock,PhysicalBlockNumber) == SUCCESS)
			{
				continue;
			}

			//read spare area of PhysicalBlockNumber
			CalculateAddress(PhysicalBlockNumber,PageNumber ,&returnAddress) ;
			NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;

			//verify if block is GOOD or BAD
			if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
			{
				//Write in RAM bbt that the PhysicalBlockNumber is bad
				result = AddBadBlock(PhysicalBlockNumber);
				if (result == FAILURE)
				{
					return FAILURE;
				}
			}
			else
			{
				//this is the first good block in partition
				if (isFirstGood == 0)
				{
					FirstGoodBlock = PhysicalBlockNumber; 
					isFirstGood = 1;
				}
				else
				{
					result = BlockErase(PhysicalBlockNumber);
					if (result == FAILURE)
					{
						//Mark in flash PhysicalBlockNumber as bad
						result = MarkBadBlock(PhysicalBlockNumber);
						if (result == FAILURE)
						{
							return FAILURE;
						}

						//Write in RAM bbt that the PhysicalBlockNumber is bad
						result = AddBadBlock(PhysicalBlockNumber);
						if (result == FAILURE)
						{
							return FAILURE;
						}
					}
					else
					{
						//Add OS_Free block in FreeBlockChain of WL

						result = AddFreeBlock(PhysicalBlockNumber,1);
					}
				}
			}
		}

		if (tempTable != NULL)
		{
			OS_DRIVER_Free(tempTable);
			tempTable = NULL;
		}
		//update in flash the BBT in flash
		result = FlushBadBlockTable(FirstGoodBlock);
		if (result == FAILURE)
		{
			return FAILURE;
		}
	}
	SetSMUsedBlocks(0);
	isInitialised = INITIALISED;
	return 1;
}


/***********************  NFTL_Initialize *******************************
* Initialize in RAM all structures necessary to known data status   *
* saved in flash 													*
*   						   										*
*-------------------------------------------------------------------*
*   No Parameters : 								  				*
*																	*
*	return values:													*
*				SUCCESS:no problems is occurred 		   			*
*				FAILURE:the initialize operation is failed  	   	*
*********************************************************************/

static NFTL_Return NFTLInitialize(void)
{
	NFTL_Return result; 
	UINT8 SpareBuffer[BUFFER_SPARE_SIZE], Conflict = 0;
	UINT16 PhysicalBlockNumber, VirtualBlockNumber, CPhyBlockNum, tempCPhyBlockNum = 0,
		ConflictBlockNumber = 0;
	UINT16 FirstGoodBlock = UD_END_PARTITION, LastGoodBlock = UD_START_PARTITION;
	INT32 isConflict = 0;
	UINT16 *tempTable = NULL;
	INT32 i;
	UINT16 NumberOfBadBlocks = 0; 
	BadBlockElem bbt, *temp = NULL; 

	ResetCache();
	//if is yet initialised return success
	if (isInitialised == INITIALISED)
	{
		return SUCCESS;
	}

#ifdef NFTL_DEBUG
	//Verify the FAL User Directive
	if (PHYSICAL_BLOCK_NUMBERS > GetDeviceArchitecture().numOfBlocks)
		return FAILURE;

	if (HIDE_BLOCK_NUMBER >= (PHYSICAL_BLOCK_NUMBERS - 2))
		return FAILURE;

	if (HIDE_BLOCK_NUMBER < ((MAXIMUM_REWRITING - 1) / 2))
		return FAILURE;
#endif /*NFTL_DEBUG*/

    //reset Virtual to Physical mapping table
	//initialize the VirtualToPhysicalMT
	for (i = 0; i < ACCESSIBLE_BLOCKS; i++)
		VirtualToPhysicalMT[i] = NULL;

	//initialize the HAL data structure to configure the Low Level Driver according to the flash device
	result = HALInitialization();
	if (result == FAILURE)
	{
		return FAILURE;
	}

	//Load in RAM the BBT
	result = GetBadBlockTable(&bbt,UD_START_PARTITION);
	 if (result != SUCCESS)
	{
		MMI_PutString((INT8 *)"1a\r\n");
		return result;
	}

	//search the ABT in last block valid
	result = InitWearLeveling();
	if (result == FAILURE)
	{
		MMI_PutString((INT8 *)"1b\r\n");
		return FAILURE;
	}

	PhysicalBlockNumber = UD_START_PARTITION;

	// search the first good block
	while (FirstGoodBlock == UD_END_PARTITION)
	{
		//read spare area of PhysicalBlockNumber
		ReadSpare528(PhysicalBlockNumber,FIRST_PAGE,SpareBuffer);
		//verify if block is GOOD or BAD
		if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
		{
			//Write in RAM bbt that the PhysicalBlockNumber is bad
			result = AddBadBlock(PhysicalBlockNumber);
			if (result == FAILURE)
			{	
				MMI_PutString((INT8 *)"1c\r\n");
				return FAILURE;
			}
		}
		else
		{
			FirstGoodBlock = PhysicalBlockNumber;
		}
		PhysicalBlockNumber++;
	}


	//search the last good block
	PhysicalBlockNumber = UD_END_PARTITION;

	// search the first good block
	while (LastGoodBlock == UD_START_PARTITION)
	{
		//read spare area of PhysicalBlockNumber
		ReadSpare528(PhysicalBlockNumber,FIRST_PAGE,SpareBuffer);

		//verify if block is GOOD or BAD
		if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
		{
			//Write in RAM bbt that the PhysicalBlockNumber is bad
			result = AddBadBlock(PhysicalBlockNumber);
			if (result == FAILURE)
			{
				MMI_PutString((INT8 *)"1d\r\n");
				return FAILURE;
			}
		}
		else
		{
			LastGoodBlock = PhysicalBlockNumber;

⌨️ 快捷键说明

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