\r
\r
/*\r
- * Block numbering recalculation macros
+ * Block numbering recalculation macros\r
*/\r
#define GET_DATASET_FROM_BLOCK_NUMBER(_blocknr) ((_blocknr) & ((uint16)((uint16)1u << NVM_DATASET_SELECTION_BITS) - 1u))\r
\r
/*\r
- * Page alignment macros
+ * Page alignment macros\r
*/\r
#define PAGE_ALIGN(_size) ((uint16)((((_size) + FEE_VIRTUAL_PAGE_SIZE - 1) / FEE_VIRTUAL_PAGE_SIZE) * FEE_VIRTUAL_PAGE_SIZE))\r
\r
/*\r
- * Bank properties list
+ * Bank properties list\r
*/\r
#define NUM_OF_BANKS 2\r
typedef struct {\r
\r
\r
/*\r
- * Macros and variables for flash bank administration
+ * Macros and variables for flash bank administration\r
*/\r
#define BANK_STATUS_OLD 0x00\r
#define BANK_STATUS_NEW 0xFF\r
\r
\r
/*\r
- * Macros and variables for flash block administration in flash
+ * Macros and variables for flash block administration in flash\r
*/\r
#define BLOCK_STATUS_INUSE 0x00\r
#define BLOCK_STATUS_INVALIDATED 0x02\r
\r
typedef struct {\r
uint8 BankNumber;\r
+ uint8 ForceGarbageCollect;\r
+ uint8 NofFailedGarbageCollect;\r
Fls_AddressType NewBlockAdminAddress;\r
Fls_AddressType NewBlockDataAddress;\r
FlsBankStatusType BankStatus[NUM_OF_BANKS];\r
\r
\r
/*\r
- * Variables for quick reporting of status and job result
+ * Variables for quick reporting of status and job result\r
*/\r
static MemIf_StatusType ModuleStatus = MEMIF_UNINIT;\r
static MemIf_JobResultType JobResult = MEMIF_JOB_OK;\r
\r
/*\r
- * Variables for the current job
+ * Variables for the current job\r
*/\r
typedef enum {\r
FEE_UNINITIALIZED = 0,\r
FEE_GARBAGE_COLLECT_DATA_WRITE,\r
FEE_GARBAGE_COLLECT_MAGIC_WRITE_REQUESTED,\r
FEE_GARBAGE_COLLECT_MAGIC_WRITE,\r
- FEE_GARBAGE_COLLECT_ERASE\r
+ FEE_GARBAGE_COLLECT_ERASE,\r
+\r
+ FEE_CORRUPTED\r
+\r
} CurrentJobStateType;\r
\r
typedef struct {\r
};\r
\r
/*\r
- * Misc definitions
+ * Misc definitions\r
*/\r
#define STATE_COUNTER_MAX 0xffff\r
#define GARBAGE_COLLECTION_DELAY 10\r
-\r
+#define MAX_NOF_FAILED_GC_ATTEMPTS 5\r
/***************************************\r
* Local functions *\r
***************************************/\r
CurrentJob.State = FEE_IDLE;\r
ModuleStatus = MEMIF_IDLE;\r
JobResult = MEMIF_JOB_OK;\r
-\r
- if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) {\r
- Fee_Config.General.NvmJobEndCallbackNotificationCallback();\r
+ if(!AdminFls.ForceGarbageCollect){\r
+ if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) {\r
+ Fee_Config.General.NvmJobEndCallbackNotificationCallback();\r
+ }\r
}\r
}\r
\r
\r
static void AbortJob(MemIf_JobResultType result)\r
{\r
- CurrentJob.State = FEE_IDLE;\r
+ if(AdminFls.NofFailedGarbageCollect >= MAX_NOF_FAILED_GC_ATTEMPTS){\r
+ DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_GLOBAL_ID, FEE_FLASH_CORRUPT);\r
+ AdminFls.ForceGarbageCollect = 0;\r
+ CurrentJob.State = FEE_CORRUPTED;\r
+ } else {\r
+ CurrentJob.State = FEE_IDLE;\r
+ }\r
ModuleStatus = MEMIF_IDLE;\r
JobResult = result;\r
\r
\r
\r
/*\r
- * 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\r
*/\r
static void StartupReadBank2Status(void)\r
{\r
}\r
\r
/*\r
- * Start of block admin read
+ * Start of block admin read\r
*/\r
static void StartupReadBlockAdminRequested(void)\r
{\r
\r
/*\r
* Check job result of block admin read, if all block processed finish\r
- * otherwise request for a new block admin read
+ * otherwise request for a new block admin read\r
*/\r
static void StartupReadBlockAdmin(void)\r
{\r
}\r
\r
/*\r
- * Check job result of block data read
+ * Check job result of block data read\r
*/\r
static void Reading(void)\r
{\r
*/\r
static void BankHeaderOldWrite(uint8 bank)\r
{\r
+ /* Need to collect garbage */\r
+ AdminFls.ForceGarbageCollect = 1;\r
/* Mark the bank as old */\r
memset(RWBuffer.BankCtrl.Data, 0xff, BANK_CTRL_PAGE_SIZE);\r
RWBuffer.BankCtrl.BankStatus = BANK_STATUS_OLD;\r
\r
\r
/*\r
- * Start of header write
+ * Start of header write\r
*/\r
static void WriteHeaderRequested()\r
{\r
\r
\r
/*\r
- * Start block data write
+ * Start block data write\r
*/\r
static void WriteDataRequested(void)\r
{\r
\r
\r
/*\r
- * Start magic write
+ * Start magic write\r
*/\r
static void WriteMagicRequested(void)\r
{\r
} else {\r
if (Fls_Erase(BankProp[sourceBank].Start, BankProp[sourceBank].End - BankProp[sourceBank].Start) == E_OK) {\r
SetFlsJobBusy();\r
+ CurrentJob.Op.GarbageCollect.BankNumber = sourceBank;\r
+ CurrentJob.State = FEE_GARBAGE_COLLECT_ERASE;\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
- CurrentJob.Op.GarbageCollect.BankNumber = sourceBank;\r
- CurrentJob.State = FEE_GARBAGE_COLLECT_ERASE;\r
}\r
} else {\r
CurrentJob.State = FEE_IDLE;\r
CurrentJob.State = FEE_GARBAGE_COLLECT_MAGIC_WRITE_REQUESTED;\r
}\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
if (Fls_Read(CurrentJob.AdminFlsBlockPtr->BlockDataAddress + CurrentJob.Op.GarbageCollect.DataOffset, RWBuffer.Byte, CurrentJob.Length) == E_OK) {\r
SetFlsJobBusy();\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
if (Fls_GetJobResult() == MEMIF_JOB_OK) {\r
CurrentJob.State = FEE_GARBAGE_COLLECT_DATA_WRITE_REQUESTED;\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
if (Fls_Write(CurrentJob.Op.GarbageCollect.WriteDataAddress + CurrentJob.Op.GarbageCollect.DataOffset, RWBuffer.Byte, CurrentJob.Length) == E_OK) {\r
SetFlsJobBusy();\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
CurrentJob.State = FEE_GARBAGE_COLLECT_DATA_READ_REQUESTED;\r
}\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
if (Fls_Write(CurrentJob.Op.GarbageCollect.WriteAdminAddress + BLOCK_CTRL_MAGIC_POS_OFFSET, RWBuffer.BlockCtrl.MagicPage.Byte, BLOCK_CTRL_MAGIC_PAGE_SIZE) == E_OK) {\r
SetFlsJobBusy();\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
if (Fls_GetJobResult() == MEMIF_JOB_OK) {\r
CurrentJob.AdminFlsBlockPtr->BlockAdminAddress = CurrentJob.Op.GarbageCollect.WriteAdminAddress;\r
CurrentJob.AdminFlsBlockPtr->BlockDataAddress = CurrentJob.Op.GarbageCollect.WriteDataAddress;\r
- FinnishJob();\r
+ CurrentJob.State = FEE_GARBAGE_COLLECT_REQUESTED;\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
if (CheckFlsJobFinnished()) {\r
if (Fls_GetJobResult() == MEMIF_JOB_OK) {\r
AdminFls.BankStatus[CurrentJob.Op.GarbageCollect.BankNumber] = BANK_STATUS_NEW;\r
+ AdminFls.ForceGarbageCollect = 0;\r
+ AdminFls.NofFailedGarbageCollect = 0;\r
FinnishJob();\r
} else {\r
+ AdminFls.NofFailedGarbageCollect++;\r
AbortJob(Fls_GetJobResult());\r
}\r
}\r
}\r
\r
/*\r
- * Start the writing of the "Invalid" header.
+ * Start the writing of the "Invalid" header.\r
*/\r
static void InvalidateWriteInvalidateHeaderRequested(void)\r
{\r
#endif\r
\r
AdminFls.BankNumber = 0;\r
+ AdminFls.ForceGarbageCollect = 0;\r
+ AdminFls.NofFailedGarbageCollect = 0;\r
AdminFls.NewBlockDataAddress = BankProp[AdminFls.BankNumber].Start;\r
AdminFls.NewBlockAdminAddress = BankProp[AdminFls.BankNumber].End - (BLOCK_CTRL_PAGE_SIZE + BANK_CTRL_PAGE_SIZE);\r
\r
uint16 dataset;\r
\r
DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_ID, FEE_E_UNINIT, E_NOT_OK);\r
-\r
+ if(AdminFls.ForceGarbageCollect || (FEE_CORRUPTED == CurrentJob.State)){\r
+ return E_NOT_OK;\r
+ }\r
if( !(ModuleStatus == MEMIF_IDLE) ) {\r
DET_REPORTERROR(MODULE_ID_FEE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);\r
return E_NOT_OK;\r
uint16 dataset;\r
\r
DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_ID, FEE_E_UNINIT, E_NOT_OK);\r
-\r
+ if(AdminFls.ForceGarbageCollect || (FEE_CORRUPTED == CurrentJob.State)){\r
+ return E_NOT_OK;\r
+ }\r
if( !(ModuleStatus == MEMIF_IDLE) ) {\r
DET_REPORTERROR(MODULE_ID_FEE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);\r
return E_NOT_OK;\r
*/\r
MemIf_StatusType Fee_GetStatus(void)\r
{\r
- return ModuleStatus;\r
+ if(AdminFls.ForceGarbageCollect && (FEE_IDLE == CurrentJob.State)){\r
+ return MEMIF_BUSY_INTERNAL;\r
+ } else {\r
+ return ModuleStatus;\r
+ }\r
}\r
\r
\r
uint16 dataset;\r
\r
DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_INVALIDATE_BLOCK_ID, FEE_E_UNINIT, E_NOT_OK);\r
+ if(AdminFls.ForceGarbageCollect || (FEE_CORRUPTED == CurrentJob.State)){\r
+ return E_NOT_OK;\r
+ }\r
if( !(ModuleStatus == MEMIF_IDLE) ) {\r
DET_REPORTERROR(MODULE_ID_FEE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);\r
return E_NOT_OK;\r
break;\r
\r
case FEE_IDLE:\r
- if (CurrentJob.InStateCounter > GARBAGE_COLLECTION_DELAY) {\r
+ if (AdminFls.ForceGarbageCollect) {\r
CheckIfGarbageCollectionNeeded();\r
}\r
break;\r
break;\r
\r
/*\r
- * Write states
+ * Write states\r
*/\r
case FEE_WRITE_REQUESTED:\r
WriteStartJob();\r
break;\r
\r
/*\r
- * Garbage collection states
+ * Garbage collection states\r
*/\r
case FEE_GARBAGE_COLLECT_REQUESTED:\r
GarbageCollectStartJob();\r
break;\r
\r
/*\r
- * Invalidate states
+ * Invalidate states\r
*/\r
case FEE_INVALIDATE_REQUESTED:\r
InvalidateStartJob();\r
InvalidateWriteInvalidateHeader();\r
break;\r
\r
+ /*\r
+ * Corrupted state\r
+ */\r
+ case FEE_CORRUPTED:\r
+ break;\r
\r
/*\r
- * Other
+ * Other\r
*/\r
default:\r
break;\r