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