📄 wearleveling.c
字号:
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 + -