📄 translationmodule.c
字号:
#include "OSModule_MemoryManagement.h"
#include"BadBlockManagement.h"
#include"HardwareAdaptationLayer.h"
#include"StructureManager.h"
#include"Common.h"
#include"FALUserDirective.h"
#include"HALUserDirective.h"
#include "WearLeveling.h"
#include "GarbageCollector.h"
#include "TranslationModule.h"
#include "LLD.h"
#include "mmiSendMessage.h"
#include "NandFat.h"
#define PHYSICAL_BLOCK_NUMBERS (UD_END_PARTITION - UD_START_PARTITION + 1)
#define ACCESSIBLE_BLOCKS (PHYSICAL_BLOCK_NUMBERS - HIDE_BLOCK_NUMBER - 2)
#define FIRST_PAGE 0
#define MINIMUM_REWRITINGNUMBER 1
#define INITIALISED 1
#define NOT_INITIALISED 0
#define RESEVED_AREA_BLOCK 48
#define NFTL_SEMAPHORE_ID 0x09
#define INTERVAL 50
#define END_POINT 4000
/****************************************************************************
Data Structure
****************************************************************************/
//VIRTUAL TO PHYSICAL MAPPING TABLE
static void *VirtualToPhysicalMT[ACCESSIBLE_BLOCKS]={NULL};
//Number Of Page Per Physical Block
//Number of Virtual Block used as Main Block (Root Block)
/*static UINT16 NumberofUsedAccessibleBlock;*/
//system status
static UINT8 isInitialised = NOT_INITIALISED;
UINT32 gFirstGoodBlcok = 0, gLastGoodBlock = 0;
extern FATSYS_STRUCT gNandFATSYS ;
extern const UINT8 *BPBTaBle ;
//extern UINT8 gNFLASHBuf[] ;
extern INT32 gInvalidBlocks;
extern UINT8 SDAndNandFlag ; /*1: NAND; 0: SD*/
static UINT8 gTMBuffer[SECTOR_SIZE + BUFFER_SPARE_SIZE];
//********* END Data Structure *************//
/****************************************************************************
Private Methods
****************************************************************************/
void UpdateVirtualToPhysicalMT(UINT16 VBIndex, UINT16 NewPhysicalBlockNumber);
NFTL_Return CallGarbageCollection(UINT16 VirtualBlockNumber, UINT8 Sector);
NFTL_Return IsInTable(UINT16 *tempTable, int len, UINT16 value);
NFTL_Return PartialDefrag(UINT16 StartVBIndex, UINT16 EndVBIndex);
extern UINT16 MMI_PutString( INT8 * str);
extern UINT32 NandClusterToAddr(UINT16 clust_no);
extern void OS_DRIVER_ObtainSemaphore (UINT16 SemaId);
extern void OS_DRIVER_ReleaseSemaphore (UINT16 SemaId);
//********* END Private Methods *************//
/*********************** FormatFlash *******************************
* Erase all nand device, except bad blocks, and create *
* the data structures that contain the number of bad blocks and the *
* age of each physical block *
*-------------------------------------------------------------------*
* No Parameters : *
* *
* return values: *
* SUCCESS: flash formatted with success *
* FAILURE: flash no formatted *
*********************************************************************/
static NFTL_Return FormatFlash(void)
{
NFTL_Return result, result1;
UINT16 PhysicalBlockNumber, FirstGoodBlock = UD_END_PARTITION, i;
UINT16 LastGoodBlock = UD_START_PARTITION;
UINT8 PageNumber = 0, SpareBuffer[BUFFER_SPARE_SIZE];
UINT16 NumberOfBadBlock = 0;
BadBlockElem bbt, *temp;
if (RecognizeDevice() != SUCCESS)
{
return FAILURE;
}
if (NFTL_Unmount() != SUCCESS)
{
return FAILURE;
}
#ifdef NFTL_DEBUG
//Verify the FAL User Directive
if (PHYSICAL_BLOCK_NUMBERS > GetDeviceArchitecture().numOfBlocks)
{
return FAILURE;
}
if (HIDE_BLOCK_NUMBER >= (PHYSICAL_BLOCK_NUMBERS - 2))
{
return FAILURE;
}
if (HIDE_BLOCK_NUMBER < ((MAXIMUM_REWRITING - 1) / 2))
{
return FAILURE;
}
#endif /*NFTL_DEBUG*/
//reset Virtual to Physical mapping table
//initialize the VirtualToPhysicalMT
for (i = 0; i < ACCESSIBLE_BLOCKS; i++)
VirtualToPhysicalMT[i] = NULL;
//initialize the HAL data structure to configure the Low Level Driver according to the flash device
result = HALInitialization();
if (result == FAILURE)
{
return FAILURE;
}
//Search the bad block table in the first good block
result1 = GetBadBlockTable(&bbt,UD_START_PARTITION);
//unrecoverable error reading BBT
//is it possible that the falsh is entirely damaged
if (result1 == FAILURE)
{
return FAILURE;
}
//search the last good block
PhysicalBlockNumber = UD_END_PARTITION;
while (LastGoodBlock == UD_START_PARTITION)
{
//read spare area of PhysicalBlockNumber
UINT32 returnAddress ;
CalculateAddress(PhysicalBlockNumber,FIRST_PAGE ,&returnAddress) ;
NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;
//the block is bad
//add block to BBT
if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
{
//Write in RAM bbt that the PhysicalBlockNumber is bad
result = AddBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
return FAILURE;
}
}
//the block is good,record the block position
else
{
LastGoodBlock = PhysicalBlockNumber;
}
PhysicalBlockNumber--;
}
//if device is unformatted
//create ABT, format the flash creating FBC
if (result1 == DEVICE_UNFORMATTED)
{
result = FAILURE;
while (result == FAILURE)
{
//erase the last block to save within it the ABT
result = BlockErase(LastGoodBlock);
if (result == FAILURE)
{
//Mark in flash PhysicalBlockNumber as bad
result1 = MarkBadBlock(LastGoodBlock);
if (result1 == FAILURE)
{
return FAILURE;
}
//Write in RAM bbt that the PhysicalBlockNumber is bad
result1 = AddBadBlock(LastGoodBlock);
if (result1 == FAILURE)
{
return FAILURE;
}
LastGoodBlock--;
}
}
//create in flash the empty Aging Block Table
result = CreateEmptyABT();
if (result == FAILURE)
{
return FAILURE;
}
//The device is unformatted
for (PhysicalBlockNumber = UD_START_PARTITION;
PhysicalBlockNumber < LastGoodBlock;
PhysicalBlockNumber++)
{
//read spare area of PhysicalBlockNumber
UINT32 returnAddress ;
CalculateAddress(PhysicalBlockNumber,PageNumber ,&returnAddress) ;
NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;
//the block is bad
//add it to BBT
if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
{
//Write in RAM bbt that the PhysicalBlockNumber is bad
result = AddBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
return FAILURE;
}
}
//the block is good
else
{
//save the physical block number of first good block
if (FirstGoodBlock == UD_END_PARTITION)
{
FirstGoodBlock = PhysicalBlockNumber;
}
//erase block
result = BlockErase(PhysicalBlockNumber);
//the block is bad
//mark it and add to BBT
if (result == FAILURE)
{
//Mark in flash PhysicalBlockNumber as bad
result = MarkBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
return FAILURE;
}
//Write in RAM bbt that the PhysicalBlockNumber is bad
result = AddBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
return FAILURE;
}
}
//erased block is good
else if (result == NAND_PASS)
{
if (PhysicalBlockNumber != FirstGoodBlock)
{
//Add OS_Free block in FreeBlockChain of WL
result = AddFreeBlock(PhysicalBlockNumber,1);
if (result == FAILURE)
{
return FAILURE;
}
}
}
else
{
return FAILURE;
}
}
}
//update in flash the BBT
result = FlushBadBlockTable(FirstGoodBlock);
if (result == FAILURE)
{
return FAILURE;
}
}
//if device is formatted
//initialize STNFTL reading the BBT and ABT
else
{
UINT16 *tempTable = NULL;
INT32 i;
UINT8 isFirstGood = 0;
result = GetBadBlocksNumber(&NumberOfBadBlock);
//create an array with the bad block number
if (NumberOfBadBlock != 0)
{
temp = &bbt;
tempTable = (UINT16 *)OS_DRIVER_Malloc(sizeof(UINT16) * NumberOfBadBlock);
if (tempTable == NULL)
{
return FAILURE;
}
for (i = 0; i < NumberOfBadBlock; i++)
{
tempTable[i] = temp->blockNumber;
temp = temp->next;
}
}
//search ABT and initialize WL
result = InitWearLeveling();
if (result == FAILURE)
{
//angelo workaround
result = CreateEmptyABT();
}
//read all first block spare area of partition except bad block
for (PhysicalBlockNumber = UD_START_PARTITION;
PhysicalBlockNumber < LastGoodBlock;
PhysicalBlockNumber++)
{
UINT32 returnAddress;
if (IsInTable(tempTable,NumberOfBadBlock,PhysicalBlockNumber) == SUCCESS)
{
continue;
}
//read spare area of PhysicalBlockNumber
CalculateAddress(PhysicalBlockNumber,PageNumber ,&returnAddress) ;
NAND_SpareReadRandom(returnAddress,SpareBuffer,CHUNK_SPARE_SIZE) ;
//verify if block is GOOD or BAD
if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
{
//Write in RAM bbt that the PhysicalBlockNumber is bad
result = AddBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
return FAILURE;
}
}
else
{
//this is the first good block in partition
if (isFirstGood == 0)
{
FirstGoodBlock = PhysicalBlockNumber;
isFirstGood = 1;
}
else
{
result = BlockErase(PhysicalBlockNumber);
if (result == FAILURE)
{
//Mark in flash PhysicalBlockNumber as bad
result = MarkBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
return FAILURE;
}
//Write in RAM bbt that the PhysicalBlockNumber is bad
result = AddBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
return FAILURE;
}
}
else
{
//Add OS_Free block in FreeBlockChain of WL
result = AddFreeBlock(PhysicalBlockNumber,1);
}
}
}
}
if (tempTable != NULL)
{
OS_DRIVER_Free(tempTable);
tempTable = NULL;
}
//update in flash the BBT in flash
result = FlushBadBlockTable(FirstGoodBlock);
if (result == FAILURE)
{
return FAILURE;
}
}
SetSMUsedBlocks(0);
isInitialised = INITIALISED;
return 1;
}
/*********************** NFTL_Initialize *******************************
* Initialize in RAM all structures necessary to known data status *
* saved in flash *
* *
*-------------------------------------------------------------------*
* No Parameters : *
* *
* return values: *
* SUCCESS:no problems is occurred *
* FAILURE:the initialize operation is failed *
*********************************************************************/
static NFTL_Return NFTLInitialize(void)
{
NFTL_Return result;
UINT8 SpareBuffer[BUFFER_SPARE_SIZE], Conflict = 0;
UINT16 PhysicalBlockNumber, VirtualBlockNumber, CPhyBlockNum, tempCPhyBlockNum = 0,
ConflictBlockNumber = 0;
UINT16 FirstGoodBlock = UD_END_PARTITION, LastGoodBlock = UD_START_PARTITION;
INT32 isConflict = 0;
UINT16 *tempTable = NULL;
INT32 i;
UINT16 NumberOfBadBlocks = 0;
BadBlockElem bbt, *temp = NULL;
ResetCache();
//if is yet initialised return success
if (isInitialised == INITIALISED)
{
return SUCCESS;
}
#ifdef NFTL_DEBUG
//Verify the FAL User Directive
if (PHYSICAL_BLOCK_NUMBERS > GetDeviceArchitecture().numOfBlocks)
return FAILURE;
if (HIDE_BLOCK_NUMBER >= (PHYSICAL_BLOCK_NUMBERS - 2))
return FAILURE;
if (HIDE_BLOCK_NUMBER < ((MAXIMUM_REWRITING - 1) / 2))
return FAILURE;
#endif /*NFTL_DEBUG*/
//reset Virtual to Physical mapping table
//initialize the VirtualToPhysicalMT
for (i = 0; i < ACCESSIBLE_BLOCKS; i++)
VirtualToPhysicalMT[i] = NULL;
//initialize the HAL data structure to configure the Low Level Driver according to the flash device
result = HALInitialization();
if (result == FAILURE)
{
return FAILURE;
}
//Load in RAM the BBT
result = GetBadBlockTable(&bbt,UD_START_PARTITION);
if (result != SUCCESS)
{
MMI_PutString((INT8 *)"1a\r\n");
return result;
}
//search the ABT in last block valid
result = InitWearLeveling();
if (result == FAILURE)
{
MMI_PutString((INT8 *)"1b\r\n");
return FAILURE;
}
PhysicalBlockNumber = UD_START_PARTITION;
// search the first good block
while (FirstGoodBlock == UD_END_PARTITION)
{
//read spare area of PhysicalBlockNumber
ReadSpare528(PhysicalBlockNumber,FIRST_PAGE,SpareBuffer);
//verify if block is GOOD or BAD
if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
{
//Write in RAM bbt that the PhysicalBlockNumber is bad
result = AddBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
MMI_PutString((INT8 *)"1c\r\n");
return FAILURE;
}
}
else
{
FirstGoodBlock = PhysicalBlockNumber;
}
PhysicalBlockNumber++;
}
//search the last good block
PhysicalBlockNumber = UD_END_PARTITION;
// search the first good block
while (LastGoodBlock == UD_START_PARTITION)
{
//read spare area of PhysicalBlockNumber
ReadSpare528(PhysicalBlockNumber,FIRST_PAGE,SpareBuffer);
//verify if block is GOOD or BAD
if (SpareBuffer[BLOCK_STATUS_BYTE] != ALL_ONE)
{
//Write in RAM bbt that the PhysicalBlockNumber is bad
result = AddBadBlock(PhysicalBlockNumber);
if (result == FAILURE)
{
MMI_PutString((INT8 *)"1d\r\n");
return FAILURE;
}
}
else
{
LastGoodBlock = PhysicalBlockNumber;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -