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