From dc1e237e17a423c7ddc62780f301cce2d8fc15bf Mon Sep 17 00:00:00 2001 From: hebe Date: Fri, 7 Sep 2012 09:22:37 +0200 Subject: [PATCH] Fee, Garbage collection forced directly after a job which required a bank switch. If garbage collection fails, a new attempt is done. It garbage collections fails a number of times Fee enters CORRUPTED state. In this state no new job is allowed. --- memory/Fee/Fee.c | 110 +++++++++++++++++++++++++++++++++-------------- 1 file changed, 77 insertions(+), 33 deletions(-) diff --git a/memory/Fee/Fee.c b/memory/Fee/Fee.c index 327a3eff..dd78574e 100644 --- a/memory/Fee/Fee.c +++ b/memory/Fee/Fee.c @@ -124,17 +124,17 @@ /* - * Block numbering recalculation macros + * Block numbering recalculation macros */ #define GET_DATASET_FROM_BLOCK_NUMBER(_blocknr) ((_blocknr) & ((uint16)((uint16)1u << NVM_DATASET_SELECTION_BITS) - 1u)) /* - * Page alignment macros + * Page alignment macros */ #define PAGE_ALIGN(_size) ((uint16)((((_size) + FEE_VIRTUAL_PAGE_SIZE - 1) / FEE_VIRTUAL_PAGE_SIZE) * FEE_VIRTUAL_PAGE_SIZE)) /* - * Bank properties list + * Bank properties list */ #define NUM_OF_BANKS 2 typedef struct { @@ -156,7 +156,7 @@ static const BankPropType BankProp[NUM_OF_BANKS] = { /* - * Macros and variables for flash bank administration + * Macros and variables for flash bank administration */ #define BANK_STATUS_OLD 0x00 #define BANK_STATUS_NEW 0xFF @@ -171,7 +171,7 @@ typedef union { /* - * Macros and variables for flash block administration in flash + * Macros and variables for flash block administration in flash */ #define BLOCK_STATUS_INUSE 0x00 #define BLOCK_STATUS_INVALIDATED 0x02 @@ -235,6 +235,8 @@ typedef struct { typedef struct { uint8 BankNumber; + uint8 ForceGarbageCollect; + uint8 NofFailedGarbageCollect; Fls_AddressType NewBlockAdminAddress; Fls_AddressType NewBlockDataAddress; FlsBankStatusType BankStatus[NUM_OF_BANKS]; @@ -245,13 +247,13 @@ static AdminFlsType AdminFls; /* - * Variables for quick reporting of status and job result + * Variables for quick reporting of status and job result */ static MemIf_StatusType ModuleStatus = MEMIF_UNINIT; static MemIf_JobResultType JobResult = MEMIF_JOB_OK; /* - * Variables for the current job + * Variables for the current job */ typedef enum { FEE_UNINITIALIZED = 0, @@ -289,7 +291,10 @@ typedef enum { FEE_GARBAGE_COLLECT_DATA_WRITE, FEE_GARBAGE_COLLECT_MAGIC_WRITE_REQUESTED, FEE_GARBAGE_COLLECT_MAGIC_WRITE, - FEE_GARBAGE_COLLECT_ERASE + FEE_GARBAGE_COLLECT_ERASE, + + FEE_CORRUPTED + } CurrentJobStateType; typedef struct { @@ -335,11 +340,11 @@ static CurrentJobType CurrentJob = { }; /* - * Misc definitions + * Misc definitions */ #define STATE_COUNTER_MAX 0xffff #define GARBAGE_COLLECTION_DELAY 10 - +#define MAX_NOF_FAILED_GC_ATTEMPTS 5 /*************************************** * Local functions * ***************************************/ @@ -408,16 +413,23 @@ static void FinnishJob(void) CurrentJob.State = FEE_IDLE; ModuleStatus = MEMIF_IDLE; JobResult = MEMIF_JOB_OK; - - if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) { - Fee_Config.General.NvmJobEndCallbackNotificationCallback(); + if(!AdminFls.ForceGarbageCollect){ + if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) { + Fee_Config.General.NvmJobEndCallbackNotificationCallback(); + } } } static void AbortJob(MemIf_JobResultType result) { - CurrentJob.State = FEE_IDLE; + if(AdminFls.NofFailedGarbageCollect >= MAX_NOF_FAILED_GC_ATTEMPTS){ + DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_GLOBAL_ID, FEE_FLASH_CORRUPT); + AdminFls.ForceGarbageCollect = 0; + CurrentJob.State = FEE_CORRUPTED; + } else { + CurrentJob.State = FEE_IDLE; + } ModuleStatus = MEMIF_IDLE; JobResult = result; @@ -479,7 +491,7 @@ static void StartupReadBank2StatusRequested(void) /* - * Check job result of bank status 2 read - request for block status reading + * Check job result of bank status 2 read - request for block status reading */ static void StartupReadBank2Status(void) { @@ -516,7 +528,7 @@ static void StartupReadBank2Status(void) } /* - * Start of block admin read + * Start of block admin read */ static void StartupReadBlockAdminRequested(void) { @@ -534,7 +546,7 @@ static void StartupReadBlockAdminRequested(void) /* * Check job result of block admin read, if all block processed finish - * otherwise request for a new block admin read + * otherwise request for a new block admin read */ static void StartupReadBlockAdmin(void) { @@ -621,7 +633,7 @@ static void ReadStartJob(void) } /* - * Check job result of block data read + * Check job result of block data read */ static void Reading(void) { @@ -640,6 +652,8 @@ static void Reading(void) */ static void BankHeaderOldWrite(uint8 bank) { + /* Need to collect garbage */ + AdminFls.ForceGarbageCollect = 1; /* Mark the bank as old */ memset(RWBuffer.BankCtrl.Data, 0xff, BANK_CTRL_PAGE_SIZE); RWBuffer.BankCtrl.BankStatus = BANK_STATUS_OLD; @@ -722,7 +736,7 @@ static void WriteMarkBankOldState(void) /* - * Start of header write + * Start of header write */ static void WriteHeaderRequested() { @@ -749,7 +763,7 @@ static void WriteHeaderState(void) /* - * Start block data write + * Start block data write */ static void WriteDataRequested(void) { @@ -783,7 +797,7 @@ static void WriteDataState(void) /* - * Start magic write + * Start magic write */ static void WriteMagicRequested(void) { @@ -881,11 +895,12 @@ static void GarbageCollectStartJob(void) } else { if (Fls_Erase(BankProp[sourceBank].Start, BankProp[sourceBank].End - BankProp[sourceBank].Start) == E_OK) { SetFlsJobBusy(); + CurrentJob.Op.GarbageCollect.BankNumber = sourceBank; + CurrentJob.State = FEE_GARBAGE_COLLECT_ERASE; } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } - CurrentJob.Op.GarbageCollect.BankNumber = sourceBank; - CurrentJob.State = FEE_GARBAGE_COLLECT_ERASE; } } else { CurrentJob.State = FEE_IDLE; @@ -911,6 +926,7 @@ static void GarbageCollectWriteHeader(void) CurrentJob.State = FEE_GARBAGE_COLLECT_MAGIC_WRITE_REQUESTED; } } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -933,6 +949,7 @@ static void GarbageCollectReadDataRequested(void) if (Fls_Read(CurrentJob.AdminFlsBlockPtr->BlockDataAddress + CurrentJob.Op.GarbageCollect.DataOffset, RWBuffer.Byte, CurrentJob.Length) == E_OK) { SetFlsJobBusy(); } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -948,6 +965,7 @@ static void GarbageCollectReadData(void) if (Fls_GetJobResult() == MEMIF_JOB_OK) { CurrentJob.State = FEE_GARBAGE_COLLECT_DATA_WRITE_REQUESTED; } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -965,9 +983,11 @@ static void GarbageCollectWriteDataRequested(void) if (Fls_Write(CurrentJob.Op.GarbageCollect.WriteDataAddress + CurrentJob.Op.GarbageCollect.DataOffset, RWBuffer.Byte, CurrentJob.Length) == E_OK) { SetFlsJobBusy(); } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -991,6 +1011,7 @@ static void GarbageCollectWriteData(void) CurrentJob.State = FEE_GARBAGE_COLLECT_DATA_READ_REQUESTED; } } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -1009,6 +1030,7 @@ static void GarbageCollectWriteMagicRequested(void) if (Fls_Write(CurrentJob.Op.GarbageCollect.WriteAdminAddress + BLOCK_CTRL_MAGIC_POS_OFFSET, RWBuffer.BlockCtrl.MagicPage.Byte, BLOCK_CTRL_MAGIC_PAGE_SIZE) == E_OK) { SetFlsJobBusy(); } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -1024,8 +1046,9 @@ static void GarbageCollectWriteMagic(void) if (Fls_GetJobResult() == MEMIF_JOB_OK) { CurrentJob.AdminFlsBlockPtr->BlockAdminAddress = CurrentJob.Op.GarbageCollect.WriteAdminAddress; CurrentJob.AdminFlsBlockPtr->BlockDataAddress = CurrentJob.Op.GarbageCollect.WriteDataAddress; - FinnishJob(); + CurrentJob.State = FEE_GARBAGE_COLLECT_REQUESTED; } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -1040,8 +1063,11 @@ static void GarbageCollectErase(void) if (CheckFlsJobFinnished()) { if (Fls_GetJobResult() == MEMIF_JOB_OK) { AdminFls.BankStatus[CurrentJob.Op.GarbageCollect.BankNumber] = BANK_STATUS_NEW; + AdminFls.ForceGarbageCollect = 0; + AdminFls.NofFailedGarbageCollect = 0; FinnishJob(); } else { + AdminFls.NofFailedGarbageCollect++; AbortJob(Fls_GetJobResult()); } } @@ -1121,7 +1147,7 @@ static void InvalidateMarkBankOld(void) } /* - * Start the writing of the "Invalid" header. + * Start the writing of the "Invalid" header. */ static void InvalidateWriteInvalidateHeaderRequested(void) { @@ -1175,6 +1201,8 @@ void Fee_Init(void) #endif AdminFls.BankNumber = 0; + AdminFls.ForceGarbageCollect = 0; + AdminFls.NofFailedGarbageCollect = 0; AdminFls.NewBlockDataAddress = BankProp[AdminFls.BankNumber].Start; AdminFls.NewBlockAdminAddress = BankProp[AdminFls.BankNumber].End - (BLOCK_CTRL_PAGE_SIZE + BANK_CTRL_PAGE_SIZE); @@ -1216,7 +1244,9 @@ Std_ReturnType Fee_Read(uint16 blockNumber, uint16 blockOffset, uint8* dataBuffe uint16 dataset; DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_ID, FEE_E_UNINIT, E_NOT_OK); - + if(AdminFls.ForceGarbageCollect || (FEE_CORRUPTED == CurrentJob.State)){ + return E_NOT_OK; + } if( !(ModuleStatus == MEMIF_IDLE) ) { DET_REPORTERROR(MODULE_ID_FEE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK); return E_NOT_OK; @@ -1258,7 +1288,9 @@ Std_ReturnType Fee_Write(uint16 blockNumber, uint8* dataBufferPtr) uint16 dataset; DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_ID, FEE_E_UNINIT, E_NOT_OK); - + if(AdminFls.ForceGarbageCollect || (FEE_CORRUPTED == CurrentJob.State)){ + return E_NOT_OK; + } if( !(ModuleStatus == MEMIF_IDLE) ) { DET_REPORTERROR(MODULE_ID_FEE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK); return E_NOT_OK; @@ -1303,7 +1335,11 @@ void Fee_Cancel(void) */ MemIf_StatusType Fee_GetStatus(void) { - return ModuleStatus; + if(AdminFls.ForceGarbageCollect && (FEE_IDLE == CurrentJob.State)){ + return MEMIF_BUSY_INTERNAL; + } else { + return ModuleStatus; + } } @@ -1327,6 +1363,9 @@ Std_ReturnType Fee_InvalidateBlock(uint16 blockNumber) uint16 dataset; DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_INVALIDATE_BLOCK_ID, FEE_E_UNINIT, E_NOT_OK); + if(AdminFls.ForceGarbageCollect || (FEE_CORRUPTED == CurrentJob.State)){ + return E_NOT_OK; + } if( !(ModuleStatus == MEMIF_IDLE) ) { DET_REPORTERROR(MODULE_ID_FEE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK); return E_NOT_OK; @@ -1391,7 +1430,7 @@ void Fee_MainFunction(void) break; case FEE_IDLE: - if (CurrentJob.InStateCounter > GARBAGE_COLLECTION_DELAY) { + if (AdminFls.ForceGarbageCollect) { CheckIfGarbageCollectionNeeded(); } break; @@ -1435,7 +1474,7 @@ void Fee_MainFunction(void) break; /* - * Write states + * Write states */ case FEE_WRITE_REQUESTED: WriteStartJob(); @@ -1470,7 +1509,7 @@ void Fee_MainFunction(void) break; /* - * Garbage collection states + * Garbage collection states */ case FEE_GARBAGE_COLLECT_REQUESTED: GarbageCollectStartJob(); @@ -1509,7 +1548,7 @@ void Fee_MainFunction(void) break; /* - * Invalidate states + * Invalidate states */ case FEE_INVALIDATE_REQUESTED: InvalidateStartJob(); @@ -1527,9 +1566,14 @@ void Fee_MainFunction(void) InvalidateWriteInvalidateHeader(); break; + /* + * Corrupted state + */ + case FEE_CORRUPTED: + break; /* - * Other + * Other */ default: break; -- 2.39.2