]> rtime.felk.cvut.cz Git - arc.git/blobdiff - memory/Fee/Fee.c
Fee, removed counter which is no longer used.
[arc.git] / memory / Fee / Fee.c
index 1d1c91b2f1db43af2d8ee2115b215dd2ef3c7f54..671ad4c0bf5b9caadeddb2d42dc146ffcd119ea0 100644 (file)
  * for more details.\r
  * -------------------------------- Arctic Core ------------------------------*/\r
 \r
+/** @reqSettings DEFAULT_SPECIFICATION_REVISION=3.1.5 */\r
 \r
 \r
+/*\r
+ * Author: pete\r
+ *\r
+ * Part of Release:\r
+ *   3.1.5\r
+ *\r
+ * Description:\r
+ *   Implements the Fee module\r
+ *\r
+ * Support:\r
+ *   General                  Have Support\r
+ *   -------------------------------------------\r
+ *   FEE_DEV_ERROR_DETECT            Y\r
+ *   FeeIndex                                           N (always 0)\r
+ *   FEE_NVM_JOB_END_NOTIFICATION    Y (Under ArcCore FEE_USE_JOB_NOTIFICATIONS is used)\r
+ *   FEE_NVM_JOB_ERROR_NOTIFICATION  Y (Under ArcCore FEE_USE_JOB_NOTIFICATIONS is used)\r
+ *   FEE_POLLING_MODE                           Y\r
+ *   FEE_VERSION_INFO_API            Y\r
+ *   FEE_VIRTUAL_PAGE_SIZE           Y\r
+ *\r
+ *   Block                    Have Support\r
+ *   -------------------------------------------\r
+ *   FeeBlockNumber                    Y\r
+ *   FeeBlockSize                      Y\r
+ *   FeeImmediateData               N\r
+ *   FeeNumberOfWriteCycles         N\r
+ *   FeeDeviceIndex                    N\r
+ *\r
+ *   Published Information       Have Support\r
+ *   -------------------------------------------\r
+ *   FEE_BLOCK_OVERHEAD                N\r
+ *   FEE_MAXIMUM_BLOCKING_TIME         N\r
+ *   FEE_PAGE_OVERHEAD                         N\r
+ */\r
 \r
 \r
-\r
-\r
-\r
-//lint -emacro(904,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
+//lint -emacro(904,DET_VALIDATE_RV,DET_VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
 \r
 // Exception made as a result of that NVM_DATASET_SELECTION_BITS can be zero\r
 //lint -emacro(835, MIN_BLOCKNR) // 835 PC-lint: A zero has been given as right argument to operator '<<' or '>>'\r
 //#include "SchM_NvM.h"\r
 #include "MemMap.h"\r
 \r
+#include <stdio.h>\r
+//#define DEBUG_FEE    1\r
+#if defined(DEBUG_FEE)\r
+#define DEBUG_PRINTF(format,...)                                       printf(format,## __VA_ARGS__ );\r
+#else\r
+#define DEBUG_PRINTF(format,...)\r
+#endif\r
+\r
+\r
+\r
 /*\r
  * Local definitions\r
  */\r
  */\r
 #if  ( FEE_DEV_ERROR_DETECT == STD_ON )\r
 #include "Det.h"\r
-#define VALIDATE(_exp,_api,_err ) \\r
+#define DET_VALIDATE(_exp,_api,_err ) \\r
         if( !(_exp) ) { \\r
           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
         }\r
 \r
-#define VALIDATE_RV(_exp,_api,_err,_rv ) \\r
+#define DET_VALIDATE_RV(_exp,_api,_err,_rv ) \\r
         if( !(_exp) ) { \\r
           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
           return _rv; \\r
         }\r
 \r
-#define VALIDATE_NO_RV(_exp,_api,_err ) \\r
+#define DET_VALIDATE_NO_RV(_exp,_api,_err ) \\r
   if( !(_exp) ) { \\r
           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
           return; \\r
 #define MIN_BLOCKNR            ((uint16)((uint16)1 << NVM_DATASET_SELECTION_BITS))\r
 \r
 #else\r
-#define VALIDATE(_exp,_api,_err )\r
-#define VALIDATE_RV(_exp,_api,_err,_rv )\r
-#define VALIDATE_NO_RV(_exp,_api,_err )\r
+#define DET_VALIDATE(_exp,_api,_err )\r
+#define DET_VALIDATE_RV(_exp,_api,_err,_rv )\r
+#define DET_VALIDATE_NO_RV(_exp,_api,_err )\r
 #define DET_REPORTERROR(_module,_instance,_api,_err)\r
 #endif\r
 \r
 \r
 /*\r
- * Block numbering recalculation macros
+ * Block numbering recalculation macros\r
  */\r
-#define GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(_blocknr)    (((_blocknr) >> NVM_DATASET_SELECTION_BITS) - 1u)\r
 #define GET_DATASET_FROM_BLOCK_NUMBER(_blocknr)        ((_blocknr) & ((uint16)((uint16)1u << NVM_DATASET_SELECTION_BITS) - 1u))\r
-#define BLOCK_INDEX_AND_SET_TO_BLOCKNR(_blocknr, _set) ((uint16)((_blocknr + 1u) << NVM_DATASET_SELECTION_BITS) | _set)\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
@@ -116,7 +156,7 @@ static const BankPropType BankProp[NUM_OF_BANKS] = {
 \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
@@ -131,7 +171,7 @@ typedef union {
 \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
@@ -195,6 +235,8 @@ typedef struct {
 \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
@@ -205,13 +247,13 @@ static AdminFlsType AdminFls;
 \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
@@ -249,12 +291,14 @@ typedef enum {
   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
        CurrentJobStateType                     State;\r
-       uint16                                          InStateCounter;\r
        uint16                                          BlockNumber;\r
        uint16                                          Length;\r
        const Fee_BlockConfigType       *BlockConfigPtr;\r
@@ -290,19 +334,33 @@ typedef struct {
 \r
 static CurrentJobType CurrentJob = {\r
                .State = FEE_IDLE,\r
-               .InStateCounter = 0\r
                //lint -e{785}          PC-Lint (785) - rest of structure members is initialized when used.\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
+uint16 GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(uint16 blockNumber) {\r
+       const Fee_BlockConfigType *FeeBlockCon;\r
+       uint16 BlockIndex = FEE_NUM_OF_BLOCKS + 1; // An invalid block\r
+\r
+       FeeBlockCon = Fee_Config.BlockConfig;\r
+       for (uint16 i = 0; i < FEE_NUM_OF_BLOCKS; i++)\r
+       {\r
+               if (FeeBlockCon[i].BlockNumber == blockNumber)\r
+               {\r
+                       BlockIndex = i;\r
+                       break;\r
+               }\r
+       }\r
+\r
+       return BlockIndex;\r
+}\r
+\r
 \r
 #if (FEE_POLLING_MODE == STD_ON)\r
 #define SetFlsJobBusy()                        /* Nothing needs to be done here */\r
@@ -351,16 +409,23 @@ static void FinnishJob(void)
        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
@@ -422,7 +487,7 @@ static void StartupReadBank2StatusRequested(void)
 \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
@@ -459,7 +524,7 @@ static void StartupReadBank2Status(void)
 }\r
 \r
 /*\r
- * Start of block admin read
+ * Start of block admin read\r
  */\r
 static void StartupReadBlockAdminRequested(void)\r
 {\r
@@ -477,14 +542,14 @@ static void StartupReadBlockAdminRequested(void)
 \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
        if (CheckFlsJobFinnished()) {\r
                if (Fls_GetJobResult() == MEMIF_JOB_OK) {\r
                        if (RWBuffer.BlockCtrl.DataPage.Data.Status == BLOCK_STATUS_EMPTY) {\r
-                               VALIDATE(CurrentJob.Op.Startup.NrOfBanks != 0, FEE_STARTUP_ID, FEE_FLASH_CORRUPT);\r
+                               DET_VALIDATE(CurrentJob.Op.Startup.NrOfBanks != 0, FEE_STARTUP_ID, FEE_FLASH_CORRUPT);\r
                                CurrentJob.Op.Startup.NrOfBanks--;\r
                                CurrentJob.Op.Startup.BankNumber = (CurrentJob.Op.Startup.BankNumber + 1) % 2;\r
                                CurrentJob.Op.Startup.BlockAdminAddress = BankProp[CurrentJob.Op.Startup.BankNumber].End - (BLOCK_CTRL_PAGE_SIZE + BANK_CTRL_PAGE_SIZE);\r
@@ -511,6 +576,7 @@ static void StartupReadBlockAdmin(void)
                                                }\r
                                        }\r
                                }\r
+                               // TODO Check wrap around here\r
                                CurrentJob.Op.Startup.BlockAdminAddress -= BLOCK_CTRL_PAGE_SIZE;\r
                                AdminFls.NewBlockAdminAddress = CurrentJob.Op.Startup.BlockAdminAddress;\r
                        }\r
@@ -563,7 +629,7 @@ static void ReadStartJob(void)
 }\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
@@ -582,6 +648,8 @@ static void Reading(void)
  */\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
@@ -664,7 +732,7 @@ static void WriteMarkBankOldState(void)
 \r
 \r
 /*\r
- * Start of header write
+ * Start of header write\r
  */\r
 static void WriteHeaderRequested()\r
 {\r
@@ -691,13 +759,15 @@ static void WriteHeaderState(void)
 \r
 \r
 /*\r
- * Start block data write
+ * Start block data write\r
  */\r
 static void WriteDataRequested(void)\r
 {\r
        if (Fls_GetStatus() == MEMIF_IDLE) {\r
                CurrentJob.State = FEE_WRITE_DATA;\r
                /* Write the actual data */\r
+               DEBUG_PRINTF("WriteDataRequested: 0x%x 0x%x %d  ",CurrentJob.Op.Write.WriteDataAddress, CurrentJob.Op.Write.RamPtr, CurrentJob.Length );\r
+\r
                if (Fls_Write(CurrentJob.Op.Write.WriteDataAddress, CurrentJob.Op.Write.RamPtr, CurrentJob.Length) == E_OK) {\r
                        SetFlsJobBusy();\r
                } else {\r
@@ -723,7 +793,7 @@ static void WriteDataState(void)
 \r
 \r
 /*\r
- * Start magic write
+ * Start magic write\r
  */\r
 static void WriteMagicRequested(void)\r
 {\r
@@ -799,7 +869,7 @@ static void GarbageCollectStartJob(void)
                                                if ((AdminFls.BlockDescrTbl[blockIndex][set].BlockAdminAddress >= BankProp[sourceBank].Start) && (AdminFls.BlockDescrTbl[blockIndex][set].BlockAdminAddress < (BankProp[sourceBank].End))) {\r
                                                        CurrentJob.AdminFlsBlockPtr = &AdminFls.BlockDescrTbl[blockIndex][set];\r
                                                        CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];\r
-                                                       CurrentJob.BlockNumber = BLOCK_INDEX_AND_SET_TO_BLOCKNR(blockIndex, set);\r
+                                                       CurrentJob.BlockNumber = Fee_Config.BlockConfig[blockIndex].BlockNumber;\r
                                                        if (AdminFls.BlockDescrTbl[blockIndex][set].Status == BLOCK_STATUS_INVALIDATED) {\r
                                                                CurrentJob.Length = 0;\r
                                                        } else {\r
@@ -821,11 +891,12 @@ static void GarbageCollectStartJob(void)
                        } 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
@@ -847,10 +918,11 @@ static void GarbageCollectWriteHeader(void)
                                CurrentJob.State = FEE_GARBAGE_COLLECT_DATA_READ_REQUESTED;\r
                        } else {\r
                                /* Yes, we are finished */\r
-                               VALIDATE_NO_RV(CurrentJob.AdminFlsBlockPtr->Status == BLOCK_STATUS_INVALIDATED, FEE_GARBAGE_WRITE_HEADER_ID, FEE_UNEXPECTED_STATUS);\r
+                               DET_VALIDATE_NO_RV(CurrentJob.AdminFlsBlockPtr->Status == BLOCK_STATUS_INVALIDATED, FEE_GARBAGE_WRITE_HEADER_ID, FEE_UNEXPECTED_STATUS);\r
                                CurrentJob.State = FEE_GARBAGE_COLLECT_MAGIC_WRITE_REQUESTED;\r
                        }\r
                } else {\r
+                       AdminFls.NofFailedGarbageCollect++;\r
                        AbortJob(Fls_GetJobResult());\r
                }\r
        }\r
@@ -873,6 +945,7 @@ static void GarbageCollectReadDataRequested(void)
                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
@@ -888,6 +961,7 @@ static void GarbageCollectReadData(void)
                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
@@ -905,9 +979,11 @@ static void GarbageCollectWriteDataRequested(void)
                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
@@ -931,6 +1007,7 @@ static void GarbageCollectWriteData(void)
                                CurrentJob.State = FEE_GARBAGE_COLLECT_DATA_READ_REQUESTED;\r
                        }\r
                } else {\r
+                       AdminFls.NofFailedGarbageCollect++;\r
                        AbortJob(Fls_GetJobResult());\r
                }\r
        }\r
@@ -949,6 +1026,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) {\r
                        SetFlsJobBusy();\r
                } else {\r
+                       AdminFls.NofFailedGarbageCollect++;\r
                        AbortJob(Fls_GetJobResult());\r
                }\r
        }\r
@@ -964,8 +1042,9 @@ static void GarbageCollectWriteMagic(void)
                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
@@ -980,8 +1059,11 @@ static void GarbageCollectErase(void)
        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
@@ -1061,7 +1143,7 @@ static void InvalidateMarkBankOld(void)
 }\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
@@ -1109,12 +1191,13 @@ void Fee_Init(void)
 \r
        /* State of device */\r
        CurrentJob.State = FEE_STARTUP_REQUESTED;\r
-       CurrentJob.InStateCounter = 0;\r
 #if (FEE_POLLING_MODE == STD_OFF)\r
        FlsJobReady = TRUE;\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
@@ -1155,18 +1238,23 @@ Std_ReturnType Fee_Read(uint16 blockNumber, uint16 blockOffset, uint8* dataBuffe
        uint16 blockIndex;\r
        uint16 dataset;\r
 \r
-       VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_ID, FEE_E_UNINIT, E_NOT_OK);\r
-       VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);\r
+       DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_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
+       }\r
 \r
-       VALIDATE_RV(blockNumber >= MIN_BLOCKNR, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
        blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
-       VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
-       VALIDATE_RV(dataBufferPtr != NULL, FEE_READ_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
-       VALIDATE_RV(blockOffset < Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_OFS, E_NOT_OK);\r
-       VALIDATE_RV(blockOffset + length <= Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_LEN, E_NOT_OK);\r
+       DET_VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
+       DET_VALIDATE_RV(dataBufferPtr != NULL, FEE_READ_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
+       DET_VALIDATE_RV(blockOffset < Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_OFS, E_NOT_OK);\r
+       DET_VALIDATE_RV(blockOffset + length <= Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_LEN, E_NOT_OK);\r
 \r
        dataset = GET_DATASET_FROM_BLOCK_NUMBER(blockNumber);\r
-       VALIDATE_RV(dataset < FEE_MAX_NUM_SETS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
+       DET_VALIDATE_RV(dataset < FEE_MAX_NUM_SETS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
 \r
 \r
        /** @req FEE022 */\r
@@ -1194,16 +1282,21 @@ Std_ReturnType Fee_Write(uint16 blockNumber, uint8* dataBufferPtr)
        uint16 blockIndex;\r
        uint16 dataset;\r
 \r
-       VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_ID, FEE_E_UNINIT, E_NOT_OK);\r
-       VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_WRITE_ID, FEE_E_BUSY, E_NOT_OK);\r
+       DET_VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_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
+       }\r
 \r
-       VALIDATE_RV(blockNumber >= MIN_BLOCKNR, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
        blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
-       VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
-       VALIDATE_RV(dataBufferPtr != NULL, FEE_WRITE_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
+       DET_VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
+       DET_VALIDATE_RV(dataBufferPtr != NULL, FEE_WRITE_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
 \r
        dataset = GET_DATASET_FROM_BLOCK_NUMBER(blockNumber);\r
-       VALIDATE_RV(dataset < FEE_MAX_NUM_SETS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
+       DET_VALIDATE_RV(dataset < FEE_MAX_NUM_SETS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
 \r
 \r
        /** @req FEE025 */\r
@@ -1237,7 +1330,11 @@ void Fee_Cancel(void)
  */\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
@@ -1260,15 +1357,20 @@ Std_ReturnType Fee_InvalidateBlock(uint16 blockNumber)
        uint16 blockIndex;\r
        uint16 dataset;\r
 \r
-       VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_INVALIDATE_BLOCK_ID, FEE_E_UNINIT, E_NOT_OK);\r
-       VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_INVALIDATE_BLOCK_ID, FEE_E_BUSY, E_NOT_OK);\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
+       }\r
 \r
-       VALIDATE_RV(blockNumber >= MIN_BLOCKNR, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
        blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
-       VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
+       DET_VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
 \r
        dataset = GET_DATASET_FROM_BLOCK_NUMBER(blockNumber);\r
-       VALIDATE_RV(dataset < FEE_MAX_NUM_SETS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
+       DET_VALIDATE_RV(dataset < FEE_MAX_NUM_SETS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
 \r
 \r
        ModuleStatus = MEMIF_BUSY;\r
@@ -1307,23 +1409,13 @@ Std_ReturnType Fee_EraseImmediateBlock(uint16 blockNumber)
  */\r
 void Fee_MainFunction(void)\r
 {\r
-       static CurrentJobStateType LastState = FEE_UNINITIALIZED;\r
-\r
-       if (CurrentJob.State == LastState) {\r
-               if (CurrentJob.InStateCounter < STATE_COUNTER_MAX) {\r
-                       CurrentJob.InStateCounter++;\r
-               }\r
-       } else {\r
-               LastState = CurrentJob.State;\r
-               CurrentJob.InStateCounter = 0;\r
-       }\r
 \r
        switch (CurrentJob.State) {\r
        case FEE_UNINITIALIZED:\r
                break;\r
 \r
        case FEE_IDLE:\r
-               if (CurrentJob.InStateCounter > GARBAGE_COLLECTION_DELAY) {\r
+               if (AdminFls.ForceGarbageCollect) {\r
                        CheckIfGarbageCollectionNeeded();\r
                }\r
                break;\r
@@ -1367,7 +1459,7 @@ void Fee_MainFunction(void)
                break;\r
 \r
        /*\r
-        * Write states
+        * Write states\r
         */\r
        case FEE_WRITE_REQUESTED:\r
                WriteStartJob();\r
@@ -1402,7 +1494,7 @@ void Fee_MainFunction(void)
                break;\r
 \r
        /*\r
-        * Garbage collection states
+        * Garbage collection states\r
         */\r
        case FEE_GARBAGE_COLLECT_REQUESTED:\r
                GarbageCollectStartJob();\r
@@ -1441,7 +1533,7 @@ void Fee_MainFunction(void)
                break;\r
 \r
        /*\r
-        * Invalidate states
+        * Invalidate states\r
         */\r
        case FEE_INVALIDATE_REQUESTED:\r
                InvalidateStartJob();\r
@@ -1459,9 +1551,14 @@ void Fee_MainFunction(void)
                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