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

📄 translationmodule.c

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

		PhysicalBlockNumber--;
	}


	//get bad blocks number 
	result = GetBadBlocksNumber(&NumberOfBadBlocks);

	//create an array with the bad block number
	if (NumberOfBadBlocks != 0)
	{
//#ifdef NFTL_DEBUG
		INT8 mstr[20];
		sprintf(mstr,"NumberOfBadBlocks=%d \n",(int) NumberOfBadBlocks);
		MMI_PutString((INT8 *) mstr); 
//#endif /*NFTL_DEBUG*/    

		temp = &bbt;
		tempTable = (UINT16 *)OS_DRIVER_Malloc(sizeof(UINT16) * NumberOfBadBlocks);
		if (tempTable == NULL)
		{
			MMI_PutString((INT8 *)"1f\r\n");
			return FAILURE;
		}

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

	//Read the first spare area of all blocks (except the bad block) to rebuild the tree structures
	for (PhysicalBlockNumber = FirstGoodBlock + 1;
		PhysicalBlockNumber < LastGoodBlock;
		PhysicalBlockNumber++)
	{   
		UINT32 returnAddress;
		//Verify if PhysicalBlockNumber is a block bad. In this case, jump at next PhysicalBlockNumber
		if (IsInTable(tempTable,NumberOfBadBlocks,PhysicalBlockNumber) == SUCCESS)
		{
			continue;
		}

		//read the second page to check if block is invalid
		CalculateAddress(PhysicalBlockNumber,FIRST_PAGE + 1,&returnAddress) ;
		NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;/*look the first page*/
		if (SpareBuffer[INVALID_BLOCK_BYTE] != 0xFF)//is invalid
		{
			MMI_PutString((INT8 *) "BlockErase Invalid Block"); 
			result = BlockErase(PhysicalBlockNumber);
			if (result == FAILURE)
			{
				//Mark in flash PhysicalBlockNumber as bad
				result = MarkBadBlock(PhysicalBlockNumber);
				if (result == FAILURE)
				{	MMI_PutString((INT8 *)"2a\r\n");
					return FAILURE;
				}
				//Write in RAM bbt that the PhysicalBlockNumber is bad
				result = AddBadBlock(PhysicalBlockNumber);
				if (result == FAILURE)
				{
					MMI_PutString((INT8 *)"2b\r\n");
					return FAILURE;
				}
			}
			else if (result == NAND_PASS)
			{
				result = AddFreeBlock(PhysicalBlockNumber, 1);
				if (result == FAILURE)
				{
					MMI_PutString((INT8 *)"2c\r\n");
					return FAILURE;}
			}
			else
			{
				return result;
			}

			continue;
		}

		//Read spare area the PhysicalBlockNumber
		CalculateAddress(PhysicalBlockNumber,FIRST_PAGE ,&returnAddress) ;
		NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;

		if ((SpareBuffer[VIRTUAL_BLOCK_NUMBER_BYTE] == ALL_ONE) &&
			(SpareBuffer[BLOCK_STATUS_BYTE] == ALL_ONE))
		{
			result = AddFreeBlock(PhysicalBlockNumber,0);
			if (result == FAILURE)
			{
				MMI_PutString((INT8 *)"2d\r\n");
				return FAILURE;
			}
		}
		else
		{
			if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
			{
				if (AddBadBlock(PhysicalBlockNumber) != SUCCESS)
				{
					MMI_PutString((INT8 *)"2f\r\n");
					return FAILURE;
				}
			}
			else
			{   
				VirtualBlockNumber = ((UINT16) (SpareBuffer[VIRTUAL_BLOCK_NUMBER_BYTE])) <<8;
				VirtualBlockNumber += SpareBuffer[VIRTUAL_BLOCK_NUMBER_BYTE + 1];

				result = AddBlock(PhysicalBlockNumber,SpareBuffer,
							&VirtualToPhysicalMT[VirtualBlockNumber],&Conflict,
							&CPhyBlockNum,0);

				if (result == FAILURE)
				{
					MMI_PutString((INT8 *)"3a\r\n");
					return FAILURE;
				}
				if (Conflict == 1)
				{
					isConflict = 1;
					ConflictBlockNumber = VirtualBlockNumber;
					tempCPhyBlockNum = CPhyBlockNum;
				}
			}
		}
	}

	if (isConflict == 1)
	{
		if (ResolveConflict(&(VirtualToPhysicalMT[ConflictBlockNumber]),tempCPhyBlockNum) ==
			FAILURE)
		{
			MMI_PutString((INT8 *)"3b\r\n");
			return FAILURE;
		}
	}
	isInitialised = INITIALISED;
	return SUCCESS;
} 

NFTL_Return NFTL_Initialize(void)
{
     	 NFTL_Return ErrorCode;
	EnableNAND();
	ErrorCode = NFTLInitialize();
	DisableNAND();
	return ErrorCode ;
	
}
/***********************  WriteSector *******************************
* Write a sector in flash managing the sector history data structure*
*   													 			*
*-------------------------------------------------------------------*
*   VirtualAddress :is the sector address   						*
*   Buffer  	   : contain the data to write in flash 	  		*
*																	*
*	return values:													*
*				WRONG_ADDRESS: the virtual address is mistaken  	*
*				SUCCESS:no problems is occurred 		   			*
*				FAILURE:the write operation is failed   	  		*
*********************************************************************/


static NFTL_Return WriteSector(UINT32 VirtualAddress, UINT8 *Buffer)
{
	UINT16 VirtualBlockNumber = 0, Sector = 0, PagePerVirtualBlock = 0, VBIndex = 0,
		VBBestDataStructure = 0;
	UINT16 *InvalidBlocks = NULL, NewPhysicalBlockNumber = 0, NumberOfUsedBlocks = 0;
	UINT8 SizeDataStructure = 1, BestSizeDataStructure = 1;
	UINT16 badBlocksNumber;
	static UINT16 StartVBIndex = 0, EndVBIndex = 50;
	NFTL_Return result = SUCCESS;
	void *BestDataStructure = NULL;
	UINT8 LastWrite = 0;

	SDAndNandFlag=1;

#ifdef NFTL_DEBUG
{	
	UINT32 NumberOfAddressableSector = 0;
	//Verify if the VirtualAddress in within partition
	NumberOfAddressableSector = ACCESSIBLE_BLOCKS * GetDeviceArchitecture().pagesInBlock ;
	if (VirtualAddress >= NumberOfAddressableSector)
	{
		return WRONG_ADDRESS;
	}
}
#endif /*NFTL_DEBUG*/
	
	VirtualBlockNumber = VirtualAddress >>5;
	Sector = VirtualAddress & 31;/*PAGES_OF_BLOCK-1*/
	
	if (gInvalidBlocks > SPACE_TO_FREE)
	{
		FreeDirtySpace();
	}

	if (StartVBIndex >= END_POINT)
	{
		StartVBIndex = 0;
		EndVBIndex = INTERVAL;
	}	
	PartialDefrag(StartVBIndex,EndVBIndex);
	StartVBIndex = EndVBIndex;
	EndVBIndex += INTERVAL;
	if (StartVBIndex == END_POINT)
	{
		EndVBIndex = ACCESSIBLE_BLOCKS;
	}


	//Execute the write in the sector history data structure	
	result = SM_WritePage(VirtualBlockNumber,Sector,Buffer,
				&(VirtualToPhysicalMT[VirtualBlockNumber]));

	//if the program operation fail the physical position is bad. The sector must be remapped.
	if (result == FAILURE)
	{
		return FAILURE;
	}

	if (result == DATA_STRUCTURE_FULL)
	{
		result = CallGarbageCollection(VirtualBlockNumber,Sector);
		if (result == FAILURE)
		{
			return result;
		}

		if (result == NO_FREE_BLOCKS)//garbage not performed
		{
			if (FreeDirtySpace() != SUCCESS)
			{
				return FAILURE;
			}
			result = CallGarbageCollection(VirtualBlockNumber,Sector);
			if (result == FAILURE)
			{
				return result;
			}
		}
		//Execute the write in the sector history data structure	
		result = SM_WritePage(VirtualBlockNumber,Sector,Buffer,
					&(VirtualToPhysicalMT[VirtualBlockNumber]));

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

		if (InvalidBlocks != NULL)
		{
			OS_DRIVER_Free(InvalidBlocks);
			InvalidBlocks = NULL;
		}
		return SUCCESS;
	}

	if (result == NO_FREE_BLOCKS)
	{
		if (FreeDirtySpace() != SUCCESS)
		{
			return FAILURE;
		}
		result = SM_WritePage(VirtualBlockNumber,Sector,Buffer,
					&(VirtualToPhysicalMT[VirtualBlockNumber]));

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


	return SUCCESS;
}

NFTL_Return FreeDirtySpace()
{
	extern NFTL_Return NFTL_FreeDirtySpace(void);
	
	NFTL_Return result;
	
	OS_DRIVER_ObtainSemaphore(NFTL_SEMAPHORE_ID);
	result = NFTL_FreeDirtySpace();
	OS_DRIVER_ReleaseSemaphore(NFTL_SEMAPHORE_ID);
	return result ;
}

NFTL_Return NFTL_FreeDirtySpace()
{
	NFTL_Return result, result1;
	UINT16 returnBlock;
	int counter = 1;
	UINT8 flag = 0;

	result = GetBestInvalidBlock(&returnBlock);

	while ((result == SUCCESS) && (counter < SPACE_TO_FREE))
	{
		result1 = BlockErase(returnBlock)  ;
		if (result1 == SUCCESS)
		{
			if (AddFreeBlock(returnBlock,1) != SUCCESS)
			{
				return FAILURE;
			}
			SetSMUsedBlocks(GetSMUsedBlocks() - 1);
		}
		else if (result1 == FAILURE)
		{
			UINT16 numBadBlocks;
			if (MarkBadBlock(returnBlock) == FAILURE)
			{
				return FAILURE;
			}
			SetSMUsedBlocks(GetSMUsedBlocks() - 1);
			if (GetBadBlocksNumber(&numBadBlocks) == FAILURE)
			{
				return FAILURE;
			}
			numBadBlocks++;
			if (SetBadBlocksNumber(numBadBlocks) == FAILURE)
			{
				return FAILURE;
			}
		}
		else
		{
			return result1;
		}
		counter++;
		flag = 1;
		if (counter < SPACE_TO_FREE)
		{
			result = GetBestInvalidBlock(&returnBlock);
		}
	}

	if (counter > 1)
	{
		//MMI_PutString((INT8 *) "FreeDirtySpace__\n\r");
		if (FlushAgingTable() != SUCCESS)
		{
			return FAILURE;
		}
	}
	return SUCCESS;
}

/***********************  ReadSector *******************************
* Read a sector from flash searching the last sector update written *
*   													 			*
*-------------------------------------------------------------------*
*   VirtualAddress :is the sector address   						*
*   Buffer  	   :contain the data to read from flash 	  		*
*																	*
*	return values:													*
*				WRONG_ADDRESS: the virtual address is mistaken  	*
*				SUCCESS:no problems is occurred 		   			*
*				FAILURE:the read operation is failed		 		*
*********************************************************************/
static NFTL_Return ReadSector(UINT32 VirtualAddress, UINT8 *Buffer)
{
	
	UINT16 VirtualBlockNumber, Sector, PagePerVirtualBlock;
	NFTL_Return result;

	SDAndNandFlag=1;

#ifdef NFTL_DEBUG
{	//Verify if the VirtualAddress in within partition
	UINT32 NumberOfAddressableSector;
	NumberOfAddressableSector = ACCESSIBLE_BLOCKS * GetDeviceArchitecture().pagesInBlock * (GetDeviceArchitecture().mainSize /
		CHUNK_DATA_SIZE);
	if (VirtualAddress >= NumberOfAddressableSector)
	{
		OS_MemSet(Buffer,0xFF,SECTOR_SIZE);
		return WRONG_ADDRESS;
	}
}
#endif /*NFTL_DEBUG*/
	//Calculate the number of physical page per Virtual Block
	VirtualBlockNumber = VirtualAddress >>5;
	Sector = VirtualAddress &31;/*PAGES_OF_BLOCK-1*/
	
	if (VirtualToPhysicalMT[VirtualBlockNumber] == NULL)
	{
		OS_MemSet(Buffer,0xFF,SECTOR_SIZE);
		return UNWRITTEN;
	}
	else
	{
		OS_MemSet(gTMBuffer,0xFF,SECTOR_SIZE + BUFFER_SPARE_SIZE);

		result = SM_ReadPage(VirtualBlockNumber,Sector,gTMBuffer,
					VirtualToPhysicalMT[VirtualBlockNumber]); 
		if (result == SUCCESS)
		{
			if (gTMBuffer[SECTOR_SIZE + ERASE_STATUS_BYTE] == ERASED)
			{
				OS_MemSet(Buffer,0xFF,SECTOR_SIZE);
				result = PAGENOTFOUND;
				return result;
			}
			OS_MemCopy(Buffer,gTMBuffer,SECTOR_SIZE);
		}

		if ((result == UNWRITTEN) || (result == PAGENOTFOUND))
		{
			OS_MemCopy(Buffer,gTMBuffer,SECTOR_SIZE);
		}
		return result;
	}

	return SUCCESS;
}

NFTL_Return Defrag()
{
	extern NFTL_Return NFTL_Defrag(void);
	NFTL_Return result;
	
	OS_DRIVER_ObtainSemaphore(NFTL_SEMAPHORE_ID);
	result = NFTL_Defrag();
	OS_DRIVER_ReleaseSemaphore(NFTL_SEMAPHORE_ID);
	return result ;
}
/***********************  Defrag	*********************************
* Reduce the all data structures that contain the sector history	*
*   													 			*
*-------------------------------------------------------------------*
*	return values:													*
*				SUCCESS:no problems is occurred 		   			*
*				FAILURE:the defrag operation is failed  	   		*
*********************************************************************/

NFTL_Return NFTL_Defrag(void)
{
	UINT16 VBIndex, *InvalidBlocks = NULL; 
	UINT8 SizeDataStructure;
	UINT16 NewPhysicalBlockNumber;
	NFTL_Return result;
	UINT8 LastWrite = 0;


	//Read the all elements of VirtualToPhysicalMappingTable 
	for (VBIndex = 0; VBIndex < ACCESSIBLE_BLOCKS; VBIndex++)
	{
		//verify if the VirtualBlock "VBIndex" is used
		if (VirtualToPhysicalMT[VBIndex] != NULL)
		{
			//verify if there is only one block in data structure
			SizeDataStructure = DimensionDataStructure(VirtualToPhysicalMT[VBIndex]);	

			if (SizeDataStructure > 1)
			{
				//the VirtualBlock "VBIndex" is used and the hystory data structure can be erased 			
				//allocate a new Block

				result = GetBestFreeBlock(&NewPhysicalBlockNumber);
				if (result != SUCCESS)
				{
					return NO_INVALID_BLOCKS;
				}

				//allocate the array to cointain the block to erase
				InvalidBlocks = (UINT16 *)OS_DRIVER_Malloc(sizeof(UINT16) * SizeDataStructure);
				if (InvalidBlocks == NULL)
				{
					return FAILURE;
				} 

				//search the physical block that must be erased
				ListInvalidBlock(VirtualToPhysicalMT[VBIndex],InvalidBlocks);
				//execute the garbage collection
				result = MinimizeStructure(InvalidBlocks,SizeDataStructure,
							VirtualToPhysicalMT[VBIndex],NewPhysicalBlockNumber,
							NOT_VALUE);

				if (result != SUCCESS)
				{
					return FAILURE;
				}

				//Update VirtualToPhysicalMT and erase the data old structure from RAM

				UpdateVirtualToPhysicalMT(VBIndex,NewPhysicalBlockNumber);

				LastWrite = GetGCNumPageWritten();
				if (UpdateLastwrite(VirtualToPhysicalMT[VBIndex],LastWrite) != SUCCESS)
				{
					return FAILURE;
				}

				if (InvalidBlocks != NULL)
				{
					OS_DRIVER_Free(InvalidBlocks);
					InvalidBlocks = NULL;
				}
			}
		}
	}

	return SUCCESS;
}


/****************  UpdateVirtualToPhysicalMT *****************************
*Update the Virtual To Physical Mapping Table freeing the space occupied *
* in RAM by tree data structure and updating the Root Node    			 *
*------------------------------------------------------------------------*
*   VBIndex :is the number of Virtual Block 							 *
*   NewPhysicalBlockNumber:is the physical block number that contains the*
*						   Root of Virtual Block indicated by VBIndex    *
**************************************************************************/


void UpdateVirtualToPhysicalMT(UINT16 VBIndex, UINT16 NewPhysicalBlockNumber)
{
	//update the physical block number linked with VB indicated by VBIndex
	UpdatePhysicalBlock(VirtualToPhysicalMT[VBIndex],NewPhysicalBlockNumber);
	//OS_Free the data structure allocated for VB block history indicated by VBIndex
	EraseRAMStructure(VirtualToPhysicalMT[VBIndex]);

	return;
}

/****************  CallGarbageCollection ******************************
* Initialize the all parameter necessary to call Garbage Collector    *
*   													 			  *
*-------------------------------------------------------------------  *
*   VirtualBlockNumber :is the virtual block number that is connected *
*					with tree data structure that needed to be defrag *
*   Sector  	   :is the sector that has caused the defrag   		  *
*																	  *
*	return values:													  *
*				WRONG_ADDRESS: the virtual address is mistaken  	  *

⌨️ 快捷键说明

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