]> rtime.felk.cvut.cz Git - arc.git/blob - memory/Fee/Fee.c
Added consistency and validation handling to Fee.
[arc.git] / memory / Fee / Fee.c
1 /* -------------------------------- Arctic Core ------------------------------\r
2  * Arctic Core - the open source AUTOSAR platform http://arccore.com\r
3  *\r
4  * Copyright (C) 2009  ArcCore AB <contact@arccore.com>\r
5  *\r
6  * This source code is free software; you can redistribute it and/or modify it\r
7  * under the terms of the GNU General Public License version 2 as published by the\r
8  * Free Software Foundation; See <http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt>.\r
9  *\r
10  * This program is distributed in the hope that it will be useful, but\r
11  * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY\r
12  * or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License\r
13  * for more details.\r
14  * -------------------------------- Arctic Core ------------------------------*/\r
15 \r
16 \r
17 \r
18 \r
19 \r
20 \r
21 \r
22 \r
23 \r
24 #include <string.h>\r
25 #include "Fee.h"\r
26 #include "Fee_Cbk.h"\r
27 #include "NvM.h"\r
28 #include "Fls.h"\r
29 #include "Rte.h" // ???\r
30 #if defined(USE_DEM)\r
31 #include "Dem.h"\r
32 #endif\r
33 //#include "SchM_NvM.h"\r
34 #include "MemMap.h"\r
35 \r
36 /*\r
37  * Local definitions
38  */\r
39 #if  ( FEE_DEV_ERROR_DETECT == STD_ON )\r
40 #include "Det.h"\r
41 #define VALIDATE(_exp,_api,_err ) \\r
42         if( !(_exp) ) { \\r
43           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
44         }\r
45 \r
46 #define VALIDATE_RV(_exp,_api,_err,_rv ) \\r
47         if( !(_exp) ) { \\r
48           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
49           return _rv; \\r
50         }\r
51 \r
52 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
53   if( !(_exp) ) { \\r
54           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
55           return; \\r
56         }\r
57 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)\r
58 \r
59 #else\r
60 #define VALIDATE(_exp,_api,_err )\r
61 #define VALIDATE_RV(_exp,_api,_err,_rv )\r
62 #define VALIDATE_NO_RV(_exp,_api,_err )\r
63 #define DET_REPORTERROR(_module,_instance,_api,_err)\r
64 #endif\r
65 \r
66 \r
67 #define GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blocknr)      ((blocknr >> NVM_DATASET_SELECTION_BITS) - 1)\r
68 #define GET_DATASET_FROM_BLOCK_NUMBER(blocknr)  (blocknr & ((1 << NVM_DATASET_SELECTION_BITS) - 1))\r
69 \r
70 #define FLS_READY       (FlsAdmin.State == FEE_FLS_STATE_READY)\r
71 \r
72 #define MAGIC_LEN               4\r
73 #define VALIDATE_POS    (MAGIC_LEN + 0)\r
74 typedef struct {\r
75         uint8   Magic[MAGIC_LEN];\r
76         uint8   Valid;\r
77 } BlockHeaderType;\r
78 \r
79 static BlockHeaderType BlockHeader;\r
80 #define BLOCK_HEADER_LEN                (sizeof(BlockHeaderType))\r
81 \r
82 static const uint8 MagicMaster[MAGIC_LEN] = { 0xeb, 0xba, 0xba, 0xbe };\r
83 static const BlockHeaderType BlockHeaderMaster = {\r
84                 .Magic = {0xeb, 0xba, 0xba, 0xbe },\r
85                 .Valid = TRUE\r
86 };\r
87 \r
88 // Variables for quick reporting of status and job result\r
89 static MemIf_StatusType ModuleStatus = MEMIF_UNINIT;\r
90 static MemIf_JobResultType JobResult = MEMIF_JOB_OK;\r
91 \r
92 typedef enum {\r
93         FEE_JOB_TYPE_NONE,\r
94         FEE_JOB_TYPE_READ,\r
95         FEE_JOB_TYPE_WRITE,\r
96         FEE_JOB_TYPE_CANCEL,\r
97         FEE_JOB_TYPE_INVALIDATE,\r
98         FEE_JOB_TYPE_ERASE_IMMEDIATE_BLOCK\r
99 } CurrentJobTypeType;\r
100 \r
101 typedef enum {\r
102   FEE_UNINITIALIZED = 0,\r
103   FEE_IDLE,\r
104   FEE_WRITE_REQUESTED,\r
105   FEE_WRITE_EREASE_PENDING,\r
106   FEE_WRITE_PENDING,\r
107   FEE_WRITE_HEADER_PENDING,\r
108   FEE_READ_REQUESTED,\r
109   FEE_READ_HEADER_PENDING,\r
110   FEE_READ_PENDING,\r
111   FEE_CANCEL_REQUESTED,\r
112   FEE_CANCEL_PENDING,\r
113   FEE_INVALIDATE_REQUESTED,\r
114   FEE_INVALIDATE_PENDING,\r
115   FEE_ERASE_IMMEDIATE_REQUESTED,\r
116   FEE_ERASE_IMMEDIATE_PENDING\r
117 } CurrentJobStateType;\r
118 \r
119 typedef enum {\r
120         FEE_FLS_STATE_IDLE,\r
121         FEE_FLS_STATE_PENDING,\r
122         FEE_FLS_STATE_READY\r
123 } FlsStateType;\r
124 \r
125 typedef struct {\r
126         FlsStateType State;\r
127         Std_ReturnType ErrorStatus;\r
128         MemIf_JobResultType JobResult;\r
129 } FlsAdminType;\r
130 \r
131 static FlsAdminType FlsAdmin = {\r
132                 .State = FEE_FLS_STATE_IDLE,\r
133                 .ErrorStatus = E_OK,\r
134                 .JobResult = MEMIF_JOB_OK\r
135 };\r
136 \r
137 typedef struct {\r
138         boolean         Consistent;\r
139         boolean         Valid;\r
140 } BlockAdminType;\r
141 \r
142 static BlockAdminType BlockAdminList[FEE_NUM_OF_BLOCKS];\r
143 \r
144 typedef struct {\r
145         CurrentJobTypeType                      Type;\r
146         CurrentJobStateType                     State;\r
147         const Fee_BlockConfigType       *BlockConfigPtr;\r
148         BlockAdminType                          *BlockAdminPtr;\r
149         uint16                                          Length;\r
150         uint16                                          Offset;\r
151         uint32                                          FlsBlockAddr;           // Flash source/Dest depending of operation\r
152         uint8                                           *RamPtr;                // RAM source/Dest depending of operation\r
153 } CurrentJobType;\r
154 \r
155 static CurrentJobType CurrentJob = {\r
156                 .Type = FEE_JOB_TYPE_NONE,\r
157                 .State = FEE_IDLE\r
158 };\r
159 \r
160 #if (FEE_POLLING_MODE == STD_ON)\r
161 void PollFlsJobResult(void)\r
162 {\r
163         MemIf_JobResultType jobResult;\r
164 \r
165         if (FlsAdmin.State = FEE_FLS_STATE_PENDING) {\r
166                 jobResult = Fls_GetJobResult();\r
167 \r
168                 if (jobResult == MEMIF_JOB_OK) {\r
169                         FlsAdmin.ErrorStatus = E_OK;\r
170                         FlsAdmin.JobResult = jobResult;\r
171                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
172                 } else if (jobResult != MEMIF_JOB_PENDING) {\r
173                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
174                         FlsAdmin.JobResult = jobResult;\r
175                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
176                 }\r
177         }\r
178 }\r
179 #else\r
180 #define PollFlsJobResult(...)\r
181 \r
182 void Fee_JobEndNotification(void)\r
183 {\r
184         FlsAdmin.State = FEE_FLS_STATE_READY;\r
185         FlsAdmin.ErrorStatus = E_OK;\r
186         FlsAdmin.JobResult = Fls_GetJobResult();\r
187 }\r
188 \r
189 void Fee_JobErrorNotification(void)\r
190 {\r
191         FlsAdmin.State = FEE_FLS_STATE_READY;\r
192         FlsAdmin.ErrorStatus = E_NOT_OK;\r
193         FlsAdmin.JobResult = Fls_GetJobResult();\r
194 }\r
195 #endif\r
196 \r
197 void FinnishJob(void)\r
198 {\r
199         FlsAdmin.State = FEE_FLS_STATE_IDLE;\r
200         CurrentJob.State = FEE_IDLE;\r
201 \r
202         ModuleStatus = MEMIF_IDLE;\r
203         JobResult = FlsAdmin.JobResult;\r
204 \r
205         if (FlsAdmin.ErrorStatus == E_OK) {\r
206                 if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) {\r
207                         Fee_Config.General.NvmJobEndCallbackNotificationCallback();\r
208                 }\r
209         } else {\r
210                 if (Fee_Config.General.NvmJobErrorCallbackNotificationCallback != NULL) {\r
211                         Fee_Config.General.NvmJobErrorCallbackNotificationCallback();\r
212                 }\r
213         }\r
214 }\r
215 \r
216 \r
217 void Fee_Init(void)\r
218 {\r
219         // Reporting information\r
220         ModuleStatus = MEMIF_IDLE;\r
221         JobResult = MEMIF_JOB_OK;\r
222 \r
223         // State of device\r
224         CurrentJob.State = FEE_IDLE;\r
225         FlsAdmin.State = FEE_FLS_STATE_IDLE;\r
226         FlsAdmin.ErrorStatus = E_OK;\r
227         FlsAdmin.JobResult = MEMIF_JOB_OK;\r
228 }\r
229 \r
230 \r
231 void Fee_SetMode(MemIf_ModeType mode)\r
232 {\r
233 #if ( FLS_SET_MODE_API == STD_ON )\r
234         Fls_SetMode(mode);\r
235 #else\r
236         DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_SET_MODE_ID, FEE_E_NOT_SUPPORTED);\r
237 #endif\r
238 }\r
239 \r
240 \r
241 Std_ReturnType Fee_Read(uint16 blockNumber, uint16 blockOffset, uint8* dataBufferPtr, uint16 length)\r
242 {\r
243         uint16 blockIndex;\r
244 \r
245         VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_ID, FEE_E_UNINIT, E_NOT_OK);\r
246         VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);\r
247 \r
248         VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
249         blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
250         VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
251         VALIDATE_RV(dataBufferPtr != NULL, FEE_READ_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
252         VALIDATE_RV(blockOffset < Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_OFS, E_NOT_OK);\r
253         VALIDATE_RV(blockOffset + length <= Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_LEN, E_NOT_OK);\r
254 \r
255 \r
256         /** @req FEE022 */\r
257         ModuleStatus = MEMIF_BUSY;\r
258         JobResult = MEMIF_JOB_PENDING;\r
259 \r
260         CurrentJob.Type = FEE_JOB_TYPE_READ;\r
261         CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];\r
262         CurrentJob.BlockAdminPtr = &BlockAdminList[blockIndex];\r
263         CurrentJob.Length = length;\r
264         CurrentJob.Offset = blockOffset;\r
265         CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize;               /** @req FEE021 */\r
266         CurrentJob.RamPtr = dataBufferPtr;\r
267         CurrentJob.State = FEE_READ_REQUESTED;\r
268 \r
269         return E_OK;\r
270 }\r
271 \r
272 \r
273 Std_ReturnType Fee_Write(uint16 blockNumber, uint8* dataBufferPtr)\r
274 {\r
275         uint16 blockIndex;\r
276 \r
277         VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_ID, FEE_E_UNINIT, E_NOT_OK);\r
278         VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_WRITE_ID, FEE_E_BUSY, E_NOT_OK);\r
279 \r
280         VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
281         blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
282         VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
283         VALIDATE_RV(dataBufferPtr != NULL, FEE_WRITE_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
284 \r
285 \r
286         /** @req FEE025 */\r
287         ModuleStatus = MEMIF_BUSY;\r
288         JobResult = MEMIF_JOB_PENDING;\r
289 \r
290         CurrentJob.Type = FEE_JOB_TYPE_WRITE;\r
291         CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];\r
292         CurrentJob.BlockAdminPtr = &BlockAdminList[blockIndex];\r
293         CurrentJob.Length = CurrentJob.BlockConfigPtr->BlockSize;\r
294         CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize;               /** @req FEE024 */\r
295         CurrentJob.RamPtr = dataBufferPtr;\r
296         CurrentJob.State = FEE_WRITE_REQUESTED;\r
297 \r
298         return E_OK;\r
299 }\r
300 \r
301 \r
302 void Fee_Cancel(void)\r
303 {\r
304 \r
305 }\r
306 \r
307 \r
308 MemIf_StatusType Fee_GetStatus(void)\r
309 {\r
310         return ModuleStatus;\r
311 }\r
312 \r
313 \r
314 MemIf_JobResultType Fee_GetJobResult(void)\r
315 {\r
316         return JobResult;\r
317 }\r
318 \r
319 \r
320 Std_ReturnType Fee_InvalidateBlock(uint16 blockNumber)\r
321 {\r
322         uint16 blockIndex;\r
323 \r
324         VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_INVALIDATE_BLOCK_ID, FEE_E_UNINIT, E_NOT_OK);\r
325         VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_INVALIDATE_BLOCK_ID, FEE_E_BUSY, E_NOT_OK);\r
326 \r
327         VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
328         blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
329         VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
330 \r
331 \r
332         ModuleStatus = MEMIF_BUSY;\r
333         JobResult = MEMIF_JOB_PENDING;\r
334 \r
335         CurrentJob.Type = FEE_JOB_TYPE_INVALIDATE;\r
336         CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];\r
337         CurrentJob.BlockAdminPtr = &BlockAdminList[blockIndex];\r
338         CurrentJob.Length = 0;\r
339         CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize;               /** @req FEE024 */\r
340         CurrentJob.RamPtr = NULL;\r
341         CurrentJob.State = FEE_INVALIDATE_REQUESTED;\r
342 \r
343         return E_OK;\r
344 }\r
345 \r
346 \r
347 Std_ReturnType Fee_EraseImmediateBlock(uint16 blockNumber)\r
348 {\r
349         VALIDATE_RV(blockNumber < FEE_NUM_OF_BLOCKS, FEE_ERASE_IMMEDIATE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
350         VALIDATE_RV(Fee_Config.BlockConfig[blockNumber].ImmediateData, FEE_ERASE_IMMEDIATE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
351 \r
352         ModuleStatus = MEMIF_BUSY;\r
353         JobResult = MEMIF_JOB_PENDING;\r
354         CurrentJob.Type = FEE_JOB_TYPE_ERASE_IMMEDIATE_BLOCK;\r
355         CurrentJob.State = FEE_ERASE_IMMEDIATE_REQUESTED;\r
356 \r
357         return E_OK;\r
358 }\r
359 \r
360 \r
361 void ReadStartJob(void)\r
362 {\r
363         if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {\r
364                 FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
365                 CurrentJob.State = FEE_READ_HEADER_PENDING;\r
366                 // Start by reading the header block\r
367                 if (Fls_Read(CurrentJob.FlsBlockAddr, (uint8*)&BlockHeader, BLOCK_HEADER_LEN) != E_OK) {\r
368                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
369                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
370                         FlsAdmin.JobResult = Fls_GetJobResult();\r
371                 }\r
372         }\r
373 }\r
374 \r
375 void ReadCheckHeaderJob(void)\r
376 {\r
377         if (FlsAdmin.ErrorStatus == E_OK) {\r
378                 if (memcmp(BlockHeader.Magic, MagicMaster, MAGIC_LEN) == 0) {\r
379                         if (BlockHeader.Valid) {\r
380                                 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {\r
381                                         FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
382                                         CurrentJob.State = FEE_READ_PENDING;\r
383                                         // Read the actual data\r
384                                         if (Fls_Read(CurrentJob.FlsBlockAddr + CurrentJob.Offset + BLOCK_HEADER_LEN, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {\r
385                                                 FlsAdmin.State = FEE_FLS_STATE_READY;\r
386                                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
387                                                 FlsAdmin.JobResult = Fls_GetJobResult();\r
388                                                 FinnishJob();\r
389                                         }\r
390                                 }\r
391                         } else {\r
392                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
393                                 FlsAdmin.JobResult = MEMIF_BLOCK_INVALID;\r
394                                 FinnishJob();\r
395                         }\r
396                 } else {\r
397                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
398                         FlsAdmin.JobResult = MEMIF_BLOCK_INCONSISTENT;\r
399                         FinnishJob();\r
400                 }\r
401         } else {\r
402                 FinnishJob();\r
403         }\r
404 }\r
405 \r
406 \r
407 void WriteStartJob(void)\r
408 {\r
409         if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {\r
410                 FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
411                 CurrentJob.State = FEE_WRITE_EREASE_PENDING;\r
412                 // Start by erasing the block\r
413                 if (Fls_Erase(CurrentJob.FlsBlockAddr, CurrentJob.Length + BLOCK_HEADER_LEN) != E_OK) {\r
414                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
415                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
416                         FlsAdmin.JobResult = Fls_GetJobResult();\r
417                 }\r
418         }\r
419 }\r
420 \r
421 \r
422 void WriteCheckEraseJob(void)\r
423 {\r
424         if (FlsAdmin.ErrorStatus == E_OK) {\r
425                 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {\r
426                         FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
427                         CurrentJob.State = FEE_WRITE_PENDING;\r
428                         // Write the actual data\r
429                         if (Fls_Write(CurrentJob.FlsBlockAddr + BLOCK_HEADER_LEN, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {\r
430                                 FlsAdmin.State = FEE_FLS_STATE_READY;\r
431                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
432                                 FlsAdmin.JobResult = Fls_GetJobResult();\r
433                                 FinnishJob();\r
434                         }\r
435                 }\r
436         } else {\r
437                 FinnishJob();\r
438         }\r
439 }\r
440 \r
441 \r
442 void WriteCheckWriteJob(void)\r
443 {\r
444         if (FlsAdmin.ErrorStatus == E_OK) {\r
445                 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {\r
446                         FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
447                         CurrentJob.State = FEE_WRITE_HEADER_PENDING;\r
448                         // Write the block header (mark it as consistent and valid)\r
449                         if (Fls_Write(CurrentJob.FlsBlockAddr, (uint8*)&BlockHeaderMaster, BLOCK_HEADER_LEN) != E_OK) {\r
450                                 FlsAdmin.State = FEE_FLS_STATE_READY;\r
451                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
452                                 FlsAdmin.JobResult = Fls_GetJobResult();\r
453                                 FinnishJob();\r
454                         }\r
455                 }\r
456         } else {\r
457                 FinnishJob();\r
458         }\r
459 }\r
460 \r
461 \r
462 void InvalidateStartJob(void)\r
463 {\r
464         static const uint8 zero = 0;\r
465 \r
466         if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {\r
467                 FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
468                 CurrentJob.State = FEE_INVALIDATE_PENDING;\r
469                 // Write a zero to the Validate flag\r
470                 if (Fls_Write(CurrentJob.FlsBlockAddr + VALIDATE_POS, &zero, 1) != E_OK) {\r
471                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
472                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
473                         FlsAdmin.JobResult = Fls_GetJobResult();\r
474                 }\r
475         }\r
476 }\r
477 \r
478 \r
479 void Fee_MainFunction(void)\r
480 {\r
481         switch (CurrentJob.State) {\r
482         case FEE_UNINITIALIZED:\r
483         case FEE_IDLE:\r
484                 break;\r
485 \r
486         case FEE_READ_REQUESTED:\r
487                 ReadStartJob();\r
488                 break;\r
489 \r
490         case FEE_READ_HEADER_PENDING:\r
491                 PollFlsJobResult();\r
492                 if (FLS_READY) {\r
493                         ReadCheckHeaderJob();\r
494                 }\r
495                 break;\r
496 \r
497         case FEE_READ_PENDING:\r
498                 PollFlsJobResult();\r
499                 if (FLS_READY) {\r
500                         FinnishJob();\r
501                 }\r
502                 break;\r
503 \r
504         case FEE_WRITE_REQUESTED:\r
505                 WriteStartJob();\r
506                 break;\r
507 \r
508         case FEE_WRITE_EREASE_PENDING:\r
509                 PollFlsJobResult();\r
510                 if (FLS_READY) {\r
511                         WriteCheckEraseJob();\r
512                 }\r
513                 break;\r
514 \r
515         case FEE_WRITE_PENDING:\r
516                 PollFlsJobResult();\r
517                 if (FLS_READY) {\r
518                         WriteCheckWriteJob();\r
519                 }\r
520                 break;\r
521 \r
522         case FEE_WRITE_HEADER_PENDING:\r
523                 PollFlsJobResult();\r
524                 if (FLS_READY) {\r
525                         FinnishJob();\r
526                 }\r
527                 break;\r
528 \r
529         case FEE_INVALIDATE_REQUESTED:\r
530                 InvalidateStartJob();\r
531                 break;\r
532 \r
533         case FEE_INVALIDATE_PENDING:\r
534                 PollFlsJobResult();\r
535                 if (FLS_READY) {\r
536                         FinnishJob();\r
537                 }\r
538                 break;\r
539 \r
540         default:\r
541                 break;\r
542         }\r
543 }\r
544 \r