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

📄 wearleveling.c

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

	if ((blockNumber > UD_END_PARTITION))
	{
		return FAILURE;
	}

	GetPageStatus(blockNumber,0,pageStatus);
	if (pageStatus[BLOCK_STATUS_BYTE] != 0xFF)
	{
		return FAILURE;
	}
	//retrieve the proprietries of the device
	if (GetWLnoOfPages() == -1)
	{
		SetABTDimensions();
	
	}
#endif

	pageLocation = GetWLpageOffset();
	//pageLocation += ((blockNumber - UD_START_PARTITION) / (SECTOR_SIZE / sizeof(UINT16))); 
	pageLocation += ((blockNumber - UD_START_PARTITION) >>8) ; 

	//offsetInPage = ((blockNumber - UD_START_PARTITION) % (SECTOR_SIZE / sizeof(UINT16))); 
	offsetInPage = ((blockNumber - UD_START_PARTITION) &255) ; 
	//EnableNAND();
	//page is in buffer
	if (GetWLABTPageBuffer().pageNumber != pageLocation)
	{
		
				if (Read512(GetWLABTBlockPosition(),pageLocation,(UINT8 *)(&ABTPageBuffer.buffer[0])) != SUCCESS)
		{   
		     		MMI_PutString("Read  ABT Fail");
		     		//DisableNAND() ;
		    		 return FAILURE ;
		}
	

		//OS_MemCopy(ABTPageBuffer.buffer,tempBuff,SECTOR_SIZE);
		ABTPageBuffer.pageNumber = pageLocation;
	}
	//DisableNAND() ;



	newBlock = (FreeBlockInformation *) OS_DRIVER_Malloc(sizeof(FreeBlockInformation));
	if (newBlock == NULL)
	{
		return FAILURE;
	}

	newBlock->Age = (ABTPageBuffer.buffer)[offsetInPage];
	newBlock->Age += increment;


	if (newBlock->Age == 0xFFFF)
	{
		//angelo
		INT16 y;
		INT32 counter = 0;
		INT16 dim = SECTOR_SIZE;

		newBlock->Age = (newBlock->Age)>>1;
		//EnableNAND();
		for (y = GetWLpageOffset(); y < GetWLpageOffset() + GetWLnoOfPages(); y++)
		{
			
			if (Read512(GetWLABTBlockPosition(),y,(UINT8 *) (ABT + counter))!= SUCCESS)
			{
					 MMI_PutString("Read  ABT Fail");
					//DisableNAND() ;
					return FAILURE;
			}
			//OS_MemCopy((UINT8 *) ABT + counter,temp,dim);
			counter += SECTOR_SIZE;
		}
		//DisableNAND() ;

		for (y = 0; y < BLOCK_IN_PARTITION; y++)
			if (ABT[y] > 1)
			{
				ABT[y] = ABT[y] / 2;
			}

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

		//EnableNAND();
		//write in page defined
		for (y = 0; y < GetWLnoOfPages(); y++)
		{
			UINT8 buf[SECTOR_SIZE + BUFFER_SPARE_SIZE];
			OS_MemSet(buf,0xFF,SECTOR_SIZE + BUFFER_SPARE_SIZE);
			//last page
			if ((y == GetWLnoOfPages() - 1) && GetWLlastPageSize())
			{
				OS_MemCopy(buf,((UINT8 *) ABT) + (y * SECTOR_SIZE),
					GetWLlastPageSize());
			}
			else
			{
				OS_MemCopy(buf,((UINT8 *) ABT) + (y * SECTOR_SIZE),SECTOR_SIZE);

				if (y == 0)
				{
					//write abt flag in spare
					buf[SECTOR_SIZE + PAGE_STATUS_BYTE] = ABT_PAGE;
					SetWLNoOfDivision(GetWLNoOfDivision() + 1);
					buf[SECTOR_SIZE + NUMBER_OF_DIVISION_BYTE] = GetWLNoOfDivision();
				}
			}

			//if (WritePage(GetWLABTBlockPosition(),y + GetWLpageOffset(),buf) !=
			//	SUCCESS)
			//	if (Write528(GetWLABTBlockPosition(),y + GetWLpageOffset(),buf) !=
			//	SUCCESS)
			{
				 UINT32 returnAddress ;
				 returnAddress=mCalculateAddress(GetWLABTBlockPosition(),y + GetWLpageOffset()) ;
		                if(  NAND_PageProgramWithEcc(returnAddress,buf,CHUNK_SIZE) !=SUCCESS)
				{
					//DisableNAND();
					return FAILURE;
				}
			}
			//{
			//	DisableNAND();
			//	return FAILURE;
			//}
		}
		//DisableNAND();
		
#if 0
			//flush the buffer for security reasons
		if (UD_BUFFER_ENABLED)
		{
			if (FlushBuffer() != SUCCESS)
			{
				return FAILURE;
			}
		}
#endif
		//each age in FBC is divided
		temp = GetWLFreeBlockListHead();
		while (temp != NULL)
		{
			if (temp->Age > 1)
			{
				temp->Age = temp->Age / 2;
			}
			temp = temp->Next;
		}
	}

	newBlock->BlockNumber = blockNumber;
	newBlock->Next = NULL;



	if (GetWLFreeBlockListHead() == NULL)
	{
		SetWLFreeBlockListHead(newBlock);
		return SUCCESS;
	}

	//blockPresent=0;MD
	prev = temp = GetWLFreeBlockListHead();

	while ((temp != NULL) && (temp->Age < newBlock->Age))
		//while ((temp != NULL) )
	{
		//the block is yet in fbc
		if (temp->BlockNumber == blockNumber)
		{
			return SUCCESS;
		}
		prev = temp;
		temp = temp->Next;
	}

	//first of chain
	if (prev == temp)
	{
		SetWLFreeBlockListHead(newBlock);
		(GetWLFreeBlockListHead())->Next = prev;
		return SUCCESS;
	}		
	newBlock->Next = prev->Next;
	prev->Next = newBlock;


	return SUCCESS;
}




/*******************************************************
*					FlushAgingTable 				   *
********************************************************
*	Load in ram the ABT from flash  				   *
*   Update the ABT with information contained in FBC   *
* 	Store ABT in flash  							   * 
********************************************************
*	RETURN VALUES   								   *
*		SUCCESS : the write in flash is correct 	   *
*		FAILURE : the error is occured  			   * 
********************************************************/

NFTL_Return FlushAgingTable()
{
	UINT32  i;
	NFTL_Return ret;
	
	FreeBlockInformation *temp = NULL;
	if (GetWLABTBlockPosition() == -1)
	{
		return FAILURE;
	}

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

	//fill the ABT
	//EnableNAND();
	for (i = 0; i < GetWLnoOfPages(); i++)
	{
	        UINT32 step=0;

	if (Read512(GetWLABTBlockPosition(),i + GetWLpageOffset(),((UINT8 *) (ABT+step))) != SUCCESS)
		{
			//mark ABT block as bad
			//DisableNAND() ;
			MarkBadBlock(GetWLABTBlockPosition());
			MMI_PutString("Read  ABT Fail");
			return FAILURE;
		}
		step = (UINT32)i<<9;
		
	}
	//DisableNAND() ;

	temp = GetWLFreeBlockListHead();
	while (temp != NULL)
	{
		ABT[temp->BlockNumber - UD_START_PARTITION] = temp->Age;
		temp = temp->Next;
	}

	ret = FlushABTImage(ABT);
	
	return(ret);
}

/*******************************************************
*					SetABTDimensions				   *
********************************************************
* Calculate the number of page that compose ABT and    *
* the dimention of last page that contain ABT		   *
*   												   *
********************************************************
*	RETURN VALUES   								   *
*		SUCCESS : the operation is finished with success*
*		FAILURE : the error is occured  			   * 
********************************************************/

NFTL_Return SetABTDimensions()
{
	SetWLpageInBlock(32);
	//calculate pages needed to store ABT in a block
	SetWLnoOfPages((BLOCK_IN_PARTITION * sizeof(UINT16)) >>9);

	if (((BLOCK_IN_PARTITION * sizeof(UINT16)) & ( SECTOR_SIZE-1)) > 0)
	{
		SetWLlastPageSize((BLOCK_IN_PARTITION * sizeof(UINT16)) & ( SECTOR_SIZE-1));
		SetWLnoOfPages(GetWLnoOfPages() + 1);
	}

	return SUCCESS;
}


NFTL_Return AddInvalidBlock(UINT16 blockNumber)
{
	InvalidBlockInformation *temp = (InvalidBlockInformation *)
		OS_DRIVER_Malloc(sizeof(InvalidBlockInformation));
	if (temp == NULL)
	{
		return FAILURE;
	}

	temp->BlockNumber = blockNumber;
	temp->Next = GetWLInvalidBlockListHead();
	SetWLInvalidBlockListHead(temp);
	gInvalidBlocks++ ;
	return SUCCESS;
}

NFTL_Return GetBestInvalidBlock(UINT16 *returnBlock)
{
	InvalidBlockInformation *temp = NULL;
	if (GetWLInvalidBlockListHead() == NULL)
	{
		return NO_INVALID_BLOCKS;
	}
	temp = GetWLInvalidBlockListHead();

	SetWLInvalidBlockListHead((GetWLInvalidBlockListHead())->Next);
	*returnBlock = temp->BlockNumber;
	OS_DRIVER_Free(temp);
	temp = NULL;
	gInvalidBlocks-- ;
	if (gInvalidBlocks < 0)
	{
		return NO_INVALID_BLOCKS;
	}
	return SUCCESS;
}


NFTL_Return Unmount_WearLeveling()
{
	//reset static variable
	FreeBlockInformation *temp;
	InvalidBlockInformation *temp2;
	SetWLABTBlockPosition(-1);//block containing the ABT (-1 if not exsist)

	SetWLpageOffset(0);	  //offset of the page where start the valid abt in block
	SetWLNoOfDivision(0);
	SetWLnoOfPages(-1);
	SetWLpageInBlock(0);
	SetWLlastPageSize(0);


	while (GetWLFreeBlockListHead() != NULL)
	{
		temp = GetWLFreeBlockListHead();
		SetWLFreeBlockListHead(GetWLFreeBlockListHead()->Next);
		if (temp != NULL)
		{
			OS_DRIVER_Free(temp);
			temp = NULL;
		}
	}

	while (GetWLInvalidBlockListHead() != NULL)
	{
		temp2 = GetWLInvalidBlockListHead();
		SetWLInvalidBlockListHead(GetWLInvalidBlockListHead()->Next);
		if (temp2 != NULL)
		{
			OS_DRIVER_Free(temp2);
			temp2 = NULL;
		}
	}

	return SUCCESS;
}


INT16 GetWLABTBlockPosition()
{
	return ABTBlockPosition;
}

void SetWLABTBlockPosition(INT16 value)
{
	ABTBlockPosition = value;
}

UINT8 GetWLpageOffset()
{
	return pageOffset;
}

void SetWLpageOffset(UINT8 value)
{
	pageOffset = value;
}

FreeBlockInformation * GetWLFreeBlockListHead()
{
	return FreeBlockListHead;
}

void SetWLFreeBlockListHead(FreeBlockInformation *value)
{
	FreeBlockListHead = value;
}

InvalidBlockInformation * GetWLInvalidBlockListHead()
{
	return InvalidBlockListHead;
}

void SetWLInvalidBlockListHead(InvalidBlockInformation *value)
{
	InvalidBlockListHead = value;
}

abtBuffer GetWLABTPageBuffer()
{
	return ABTPageBuffer;
}



INT8 GetWLNoOfDivision()
{
	return NoOfDivision;
}

void SetWLNoOfDivision(INT8 value)
{
	NoOfDivision = value;
}

INT8 GetWLnoOfPages()
{
	return noOfPages;
}

void SetWLnoOfPages(INT8 value)
{
	noOfPages = value;
}

UINT8 GetWLpageInBlock()
{
	return wl_pageInBlock;
}

void SetWLpageInBlock(UINT8 value)
{
	wl_pageInBlock = value;
}

UINT16 GetWLlastPageSize()
{
	return lastPageSize;
}

void SetWLlastPageSize(UINT16 value)
{
	lastPageSize = value;
}

⌨️ 快捷键说明

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