]> rtime.felk.cvut.cz Git - arc.git/blob - memory/Fee/Fee.c
Merge in from default
[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 \r
40 // Validation macros\r
41 #if  ( FEE_DEV_ERROR_DETECT == STD_ON )\r
42 #include "Det.h"\r
43 #define VALIDATE(_exp,_api,_err ) \\r
44         if( !(_exp) ) { \\r
45           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
46         }\r
47 \r
48 #define VALIDATE_RV(_exp,_api,_err,_rv ) \\r
49         if( !(_exp) ) { \\r
50           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
51           return _rv; \\r
52         }\r
53 \r
54 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
55   if( !(_exp) ) { \\r
56           Det_ReportError(MODULE_ID_FEE, 0, _api, _err); \\r
57           return; \\r
58         }\r
59 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)\r
60 \r
61 #else\r
62 #define VALIDATE(_exp,_api,_err )\r
63 #define VALIDATE_RV(_exp,_api,_err,_rv )\r
64 #define VALIDATE_NO_RV(_exp,_api,_err )\r
65 #define DET_REPORTERROR(_module,_instance,_api,_err)\r
66 #endif\r
67 \r
68 // Block numbering recalculation macros\r
69 #define GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blocknr)      ((blocknr >> NVM_DATASET_SELECTION_BITS) - 1)\r
70 #define GET_DATASET_FROM_BLOCK_NUMBER(blocknr)  (blocknr & ((1 << NVM_DATASET_SELECTION_BITS) - 1))\r
71 \r
72 // Macro for checking if the flash is ready\r
73 #define FLASH_READY     (FlsAdmin.State == FEE_FLS_STATE_READY)\r
74 \r
75 // Macros and variables for flash block administration\r
76 #define BLOCK_ADMIN_STATUS_VALID        0x01\r
77 #define BLOCK_ADMIN_STATUS_EMPTY        0x02\r
78 \r
79 #define BLOCK_ADMIN_MAGIC_LEN           4\r
80 typedef struct {\r
81         uint8   Status;\r
82         uint8   Spare;\r
83         uint8   Magic[BLOCK_ADMIN_MAGIC_LEN];\r
84 } FlsBlockAdminType;\r
85 \r
86 static FlsBlockAdminType FlsBlockAdmin;\r
87 \r
88 #define BLOCK_ADMIN_LEN                         (sizeof(FlsBlockAdminType))\r
89 #define BLOCK_ADMIN_VALIDATE_POS        0\r
90 #define BLOCK_ADMIN_MAGIC_POS           2\r
91 \r
92 static const uint8 MagicMaster[BLOCK_ADMIN_MAGIC_LEN] = { 0xeb, 0xba, 0xba, 0xbe };\r
93 static const FlsBlockAdminType FlsBlockAdminMaster = {\r
94                 .Status = BLOCK_ADMIN_STATUS_VALID | ~BLOCK_ADMIN_STATUS_EMPTY,\r
95                 .Magic = { 0xeb, 0xba, 0xba, 0xbe }\r
96 };\r
97 \r
98 // Variables for keeping the state and status of the flash\r
99 typedef enum {\r
100         FEE_FLS_STATE_IDLE,\r
101         FEE_FLS_STATE_PENDING,\r
102         FEE_FLS_STATE_READY\r
103 } FlsStateType;\r
104 \r
105 typedef struct {\r
106         FlsStateType State;\r
107         Std_ReturnType ErrorStatus;\r
108         MemIf_JobResultType JobResult;\r
109 } FlsAdminType;\r
110 \r
111 static FlsAdminType FlsAdmin = {\r
112                 .State = FEE_FLS_STATE_IDLE,\r
113                 .ErrorStatus = E_OK,\r
114                 .JobResult = MEMIF_JOB_OK\r
115 };\r
116 \r
117 // Variables for quick reporting of status and job result\r
118 static MemIf_StatusType ModuleStatus = MEMIF_UNINIT;\r
119 static MemIf_JobResultType JobResult = MEMIF_JOB_OK;\r
120 \r
121 // Variables for the current job\r
122 typedef enum {\r
123   FEE_UNINITIALIZED = 0,\r
124   FEE_IDLE,\r
125   FEE_WRITE_REQUESTED,\r
126   FEE_WRITE_MAGIC_EREASE_PENDING,\r
127   FEE_WRITE_EREASE_PENDING,\r
128   FEE_WRITE_PENDING,\r
129   FEE_WRITE_BLOCK_ADMIN_PENDING,\r
130   FEE_READ_REQUESTED,\r
131   FEE_READ_BLOCK_ADMIN_PENDING,\r
132   FEE_READ_PENDING,\r
133   FEE_CANCEL_REQUESTED,\r
134   FEE_CANCEL_PENDING,\r
135   FEE_INVALIDATE_REQUESTED,\r
136   FEE_INVALIDATE_PENDING,\r
137   FEE_ERASE_IMMEDIATE_REQUESTED,\r
138   FEE_ERASE_IMMEDIATE_PENDING\r
139 } CurrentJobStateType;\r
140 \r
141 typedef struct {\r
142         CurrentJobStateType                     State;\r
143         const Fee_BlockConfigType       *BlockConfigPtr;\r
144         uint16                                          Length;\r
145         uint16                                          Offset;\r
146         uint32                                          FlsBlockAddr;           // Flash source/Dest depending of operation\r
147         uint32                                          FlsBlockAdminAddr;      // Startadress of admin block\r
148         uint8                                           *RamPtr;                // RAM source/Dest depending of operation\r
149 } CurrentJobType;\r
150 \r
151 static CurrentJobType CurrentJob = {\r
152                 .State = FEE_IDLE\r
153 };\r
154 \r
155 \r
156 /*\r
157  * Local functions
158  */\r
159 #if (FEE_POLLING_MODE == STD_ON)\r
160 void PollFlsJobResult(void)\r
161 {\r
162         MemIf_JobResultType jobResult;\r
163 \r
164         if (FlsAdmin.State == FEE_FLS_STATE_PENDING) {\r
165                 jobResult = Fls_GetJobResult();\r
166 \r
167                 if (jobResult == MEMIF_JOB_OK) {\r
168                         FlsAdmin.ErrorStatus = E_OK;\r
169                         FlsAdmin.JobResult = jobResult;\r
170                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
171                 } else if (jobResult != MEMIF_JOB_PENDING) {\r
172                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
173                         FlsAdmin.JobResult = jobResult;\r
174                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
175                 }\r
176         }\r
177 }\r
178 #else\r
179 #define PollFlsJobResult(...)\r
180 #endif\r
181 \r
182 \r
183 void FinnishJob(void)\r
184 {\r
185         FlsAdmin.State = FEE_FLS_STATE_IDLE;\r
186         CurrentJob.State = FEE_IDLE;\r
187 \r
188         ModuleStatus = MEMIF_IDLE;\r
189         JobResult = FlsAdmin.JobResult;\r
190 \r
191         if (FlsAdmin.ErrorStatus == E_OK) {\r
192                 if (Fee_Config.General.NvmJobEndCallbackNotificationCallback != NULL) {\r
193                         Fee_Config.General.NvmJobEndCallbackNotificationCallback();\r
194                 }\r
195         } else {\r
196                 if (Fee_Config.General.NvmJobErrorCallbackNotificationCallback != NULL) {\r
197                         Fee_Config.General.NvmJobErrorCallbackNotificationCallback();\r
198                 }\r
199         }\r
200 }\r
201 \r
202 \r
203 void ReadStartJob(void)\r
204 {\r
205         if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {\r
206                 FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
207                 CurrentJob.State = FEE_READ_BLOCK_ADMIN_PENDING;\r
208                 // Start by reading the admin block\r
209                 if (Fls_Read(CurrentJob.FlsBlockAdminAddr, (uint8*)&FlsBlockAdmin, BLOCK_ADMIN_LEN) != E_OK) {\r
210                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
211                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
212                         FlsAdmin.JobResult = Fls_GetJobResult();\r
213                 }\r
214         }\r
215 }\r
216 \r
217 void ReadCheckBlockAdminJob(void)\r
218 {\r
219         if (FlsAdmin.ErrorStatus == E_OK) {\r
220                 if (memcmp(FlsBlockAdmin.Magic, MagicMaster, BLOCK_ADMIN_MAGIC_LEN) == 0) {\r
221                         if (FlsBlockAdmin.Status & BLOCK_ADMIN_STATUS_VALID) {\r
222                                 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {\r
223                                         FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
224                                         CurrentJob.State = FEE_READ_PENDING;\r
225                                         // Read the actual data\r
226                                         if (Fls_Read(CurrentJob.FlsBlockAddr + CurrentJob.Offset, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {\r
227                                                 FlsAdmin.State = FEE_FLS_STATE_READY;\r
228                                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
229                                                 FlsAdmin.JobResult = Fls_GetJobResult();\r
230                                                 FinnishJob();\r
231                                         }\r
232                                 }\r
233                         } else {\r
234                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
235                                 FlsAdmin.JobResult = MEMIF_BLOCK_INVALID;\r
236                                 FinnishJob();\r
237                         }\r
238                 } else {\r
239                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
240                         FlsAdmin.JobResult = MEMIF_BLOCK_INCONSISTENT;\r
241                         FinnishJob();\r
242                 }\r
243         } else {\r
244                 FinnishJob();\r
245         }\r
246 }\r
247 \r
248 \r
249 void WriteStartJob(void)\r
250 {\r
251         if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {\r
252                 FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
253                 CurrentJob.State = FEE_WRITE_MAGIC_EREASE_PENDING;\r
254                 // Start by erasing the magic\r
255                 if (Fls_Erase(CurrentJob.FlsBlockAdminAddr + BLOCK_ADMIN_MAGIC_POS, BLOCK_ADMIN_MAGIC_LEN) != E_OK) {\r
256                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
257                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
258                         FlsAdmin.JobResult = Fls_GetJobResult();\r
259                 }\r
260         }\r
261 }\r
262 \r
263 \r
264 void WriteCheckMagicEraseJob(void)\r
265 {\r
266         if (FlsAdmin.ErrorStatus == E_OK) {\r
267                 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {\r
268                         FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
269                         CurrentJob.State = FEE_WRITE_EREASE_PENDING;\r
270                         // Erase the rest of the block\r
271                         if (Fls_Erase(CurrentJob.FlsBlockAddr, CurrentJob.BlockConfigPtr->BlockSize + BLOCK_ADMIN_LEN - BLOCK_ADMIN_MAGIC_LEN) != E_OK) {\r
272                                 FlsAdmin.State = FEE_FLS_STATE_READY;\r
273                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
274                                 FlsAdmin.JobResult = Fls_GetJobResult();\r
275                                 FinnishJob();\r
276                         }\r
277                 }\r
278         } else {\r
279                 FinnishJob();\r
280         }\r
281 }\r
282 \r
283 \r
284 void WriteCheckEraseJob(void)\r
285 {\r
286         if (FlsAdmin.ErrorStatus == E_OK) {\r
287                 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {\r
288                         FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
289                         CurrentJob.State = FEE_WRITE_PENDING;\r
290                         // Write the actual data\r
291                         if (Fls_Write(CurrentJob.FlsBlockAddr, CurrentJob.RamPtr, CurrentJob.Length) != E_OK) {\r
292                                 FlsAdmin.State = FEE_FLS_STATE_READY;\r
293                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
294                                 FlsAdmin.JobResult = Fls_GetJobResult();\r
295                                 FinnishJob();\r
296                         }\r
297                 }\r
298         } else {\r
299                 FinnishJob();\r
300         }\r
301 }\r
302 \r
303 \r
304 void WriteCheckWriteJob(void)\r
305 {\r
306         if (FlsAdmin.ErrorStatus == E_OK) {\r
307                 if (FlsAdmin.State != FEE_FLS_STATE_PENDING) {\r
308                         FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
309                         CurrentJob.State = FEE_WRITE_BLOCK_ADMIN_PENDING;\r
310                         // Write the block admin (mark it as consistent, valid and not empty)\r
311                         if (Fls_Write(CurrentJob.FlsBlockAdminAddr, (uint8*)&FlsBlockAdminMaster, BLOCK_ADMIN_LEN) != E_OK) {\r
312                                 FlsAdmin.State = FEE_FLS_STATE_READY;\r
313                                 FlsAdmin.ErrorStatus = E_NOT_OK;\r
314                                 FlsAdmin.JobResult = Fls_GetJobResult();\r
315                                 FinnishJob();\r
316                         }\r
317                 }\r
318         } else {\r
319                 FinnishJob();\r
320         }\r
321 }\r
322 \r
323 \r
324 void InvalidateStartJob(void)\r
325 {\r
326         static const uint8 zero = 0;\r
327 \r
328         if (FlsAdmin.State == FEE_FLS_STATE_IDLE) {\r
329                 FlsAdmin.State = FEE_FLS_STATE_PENDING;\r
330                 CurrentJob.State = FEE_INVALIDATE_PENDING;\r
331                 // Write a zero to the Validate flag\r
332                 if (Fls_Write(CurrentJob.FlsBlockAdminAddr + BLOCK_ADMIN_VALIDATE_POS, &zero, 1) != E_OK) {\r
333                         FlsAdmin.State = FEE_FLS_STATE_READY;\r
334                         FlsAdmin.ErrorStatus = E_NOT_OK;\r
335                         FlsAdmin.JobResult = Fls_GetJobResult();\r
336                 }\r
337         }\r
338 }\r
339 \r
340 \r
341 /***************************************\r
342  *    External accessible functions    *
343  ***************************************/\r
344 /*\r
345  * Procedure:   Fee_Init\r
346  * Reentrant:   No\r
347  */\r
348 void Fee_Init(void)\r
349 {\r
350         // Reporting information\r
351         ModuleStatus = MEMIF_IDLE;\r
352         JobResult = MEMIF_JOB_OK;\r
353 \r
354         // State of device\r
355         CurrentJob.State = FEE_IDLE;\r
356         FlsAdmin.State = FEE_FLS_STATE_IDLE;\r
357         FlsAdmin.ErrorStatus = E_OK;\r
358         FlsAdmin.JobResult = MEMIF_JOB_OK;\r
359 }\r
360 \r
361 \r
362 /*\r
363  * Procedure:   Fee_SetMode\r
364  * Reentrant:   No\r
365  */\r
366 void Fee_SetMode(MemIf_ModeType mode)\r
367 {\r
368 #if ( FLS_SET_MODE_API == STD_ON )\r
369         Fls_SetMode(mode);\r
370 #else\r
371         DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_SET_MODE_ID, FEE_E_NOT_SUPPORTED);\r
372 #endif\r
373 }\r
374 \r
375 /*\r
376  * Procedure:   Fee_Read\r
377  * Reentrant:   No\r
378  */\r
379 Std_ReturnType Fee_Read(uint16 blockNumber, uint16 blockOffset, uint8* dataBufferPtr, uint16 length)\r
380 {\r
381         uint16 blockIndex;\r
382 \r
383         VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_READ_ID, FEE_E_UNINIT, E_NOT_OK);\r
384         VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_READ_ID, FEE_E_BUSY, E_NOT_OK);\r
385 \r
386         VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
387         blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
388         VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
389         VALIDATE_RV(dataBufferPtr != NULL, FEE_READ_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
390         VALIDATE_RV(blockOffset < Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_OFS, E_NOT_OK);\r
391         VALIDATE_RV(blockOffset + length <= Fee_Config.BlockConfig[blockIndex].BlockSize, FEE_READ_ID, FEE_E_INVALID_BLOCK_LEN, E_NOT_OK);\r
392 \r
393 \r
394         /** @req FEE022 */\r
395         ModuleStatus = MEMIF_BUSY;\r
396         JobResult = MEMIF_JOB_PENDING;\r
397 \r
398         CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];\r
399         CurrentJob.Length = length;\r
400         CurrentJob.Offset = blockOffset;\r
401         CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize;               /** @req FEE021 */\r
402         CurrentJob.FlsBlockAdminAddr = CurrentJob.FlsBlockAddr + CurrentJob.BlockConfigPtr->BlockSize;\r
403         CurrentJob.RamPtr = dataBufferPtr;\r
404         CurrentJob.State = FEE_READ_REQUESTED;\r
405 \r
406         return E_OK;\r
407 }\r
408 \r
409 \r
410 /*\r
411  * Procedure:   Fee_Write\r
412  * Reentrant:   No\r
413  */\r
414 Std_ReturnType Fee_Write(uint16 blockNumber, uint8* dataBufferPtr)\r
415 {\r
416         uint16 blockIndex;\r
417 \r
418         VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_WRITE_ID, FEE_E_UNINIT, E_NOT_OK);\r
419         VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_WRITE_ID, FEE_E_BUSY, E_NOT_OK);\r
420 \r
421         VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
422         blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
423         VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
424         VALIDATE_RV(dataBufferPtr != NULL, FEE_WRITE_ID, FEE_E_INVALID_DATA_PTR, E_NOT_OK);\r
425 \r
426 \r
427         /** @req FEE025 */\r
428         ModuleStatus = MEMIF_BUSY;\r
429         JobResult = MEMIF_JOB_PENDING;\r
430 \r
431         CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];\r
432         CurrentJob.Length = CurrentJob.BlockConfigPtr->BlockSize;\r
433         CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize;               /** @req FEE024 */\r
434         CurrentJob.FlsBlockAdminAddr = CurrentJob.FlsBlockAddr + CurrentJob.BlockConfigPtr->BlockSize;\r
435         CurrentJob.RamPtr = dataBufferPtr;\r
436         CurrentJob.State = FEE_WRITE_REQUESTED;\r
437 \r
438         return E_OK;\r
439 }\r
440 \r
441 \r
442 /*\r
443  * Procedure:   Fee_Cancel\r
444  * Reentrant:   No\r
445  */\r
446 void Fee_Cancel(void)\r
447 {\r
448         DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_CANCEL_ID, FEE_E_NOT_IMPLEMENTED_YET);\r
449 }\r
450 \r
451 \r
452 /*\r
453  * Procedure:   Fee_GetStatus\r
454  * Reentrant:   No\r
455  */\r
456 MemIf_StatusType Fee_GetStatus(void)\r
457 {\r
458         return ModuleStatus;\r
459 }\r
460 \r
461 \r
462 /*\r
463  * Procedure:   Fee_GetJobResult\r
464  * Reentrant:   No\r
465  */\r
466 MemIf_JobResultType Fee_GetJobResult(void)\r
467 {\r
468         return JobResult;\r
469 }\r
470 \r
471 \r
472 /*\r
473  * Procedure:   Fee_InvalidateBlock\r
474  * Reentrant:   No\r
475  */\r
476 Std_ReturnType Fee_InvalidateBlock(uint16 blockNumber)\r
477 {\r
478         uint16 blockIndex;\r
479 \r
480         VALIDATE_RV(ModuleStatus != MEMIF_UNINIT, FEE_INVALIDATE_BLOCK_ID, FEE_E_UNINIT, E_NOT_OK);\r
481         VALIDATE_RV(ModuleStatus == MEMIF_IDLE, FEE_INVALIDATE_BLOCK_ID, FEE_E_BUSY, E_NOT_OK);\r
482 \r
483         VALIDATE_RV(blockNumber >= (1 << NVM_DATASET_SELECTION_BITS), FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
484         blockIndex = GET_BLOCK_INDEX_FROM_BLOCK_NUMBER(blockNumber);\r
485         VALIDATE_RV(blockIndex < FEE_NUM_OF_BLOCKS, FEE_INVALIDATE_BLOCK_ID, FEE_E_INVALID_BLOCK_NO, E_NOT_OK);\r
486 \r
487 \r
488         ModuleStatus = MEMIF_BUSY;\r
489         JobResult = MEMIF_JOB_PENDING;\r
490 \r
491         CurrentJob.BlockConfigPtr = &Fee_Config.BlockConfig[blockIndex];\r
492         CurrentJob.Length = 0;\r
493         CurrentJob.FlsBlockAddr = CurrentJob.BlockConfigPtr->PhysBaseAddress + GET_DATASET_FROM_BLOCK_NUMBER(blockNumber) * CurrentJob.BlockConfigPtr->BlockSize;               /** @req FEE024 */\r
494         CurrentJob.FlsBlockAdminAddr = CurrentJob.FlsBlockAddr + CurrentJob.BlockConfigPtr->BlockSize;\r
495         CurrentJob.RamPtr = NULL;\r
496         CurrentJob.State = FEE_INVALIDATE_REQUESTED;\r
497 \r
498         return E_OK;\r
499 }\r
500 \r
501 \r
502 /*\r
503  * Procedure:   Fee_EraseImmediateBlock\r
504  * Reentrant:   No\r
505  */\r
506 Std_ReturnType Fee_EraseImmediateBlock(uint16 blockNumber)\r
507 {\r
508         DET_REPORTERROR(MODULE_ID_FEE, 0, FEE_ERASE_IMMEDIATE_ID, FEE_E_NOT_IMPLEMENTED_YET);\r
509 \r
510         return E_NOT_OK;\r
511 }\r
512 \r
513 \r
514 /***************************************\r
515  *         Scheduled functions         *
516  ***************************************/\r
517 /*\r
518  * Procedure:   Fee_MainFunction\r
519  * Reentrant:   No\r
520  */\r
521 void Fee_MainFunction(void)\r
522 {\r
523         switch (CurrentJob.State) {\r
524         case FEE_UNINITIALIZED:\r
525         case FEE_IDLE:\r
526                 break;\r
527 \r
528         // Read states\r
529         case FEE_READ_REQUESTED:\r
530                 ReadStartJob();\r
531                 break;\r
532 \r
533         case FEE_READ_BLOCK_ADMIN_PENDING:\r
534                 PollFlsJobResult();\r
535                 if (FLASH_READY) {\r
536                         ReadCheckBlockAdminJob();\r
537                 }\r
538                 break;\r
539 \r
540         case FEE_READ_PENDING:\r
541                 PollFlsJobResult();\r
542                 if (FLASH_READY) {\r
543                         FinnishJob();\r
544                 }\r
545                 break;\r
546 \r
547         // Write states\r
548         case FEE_WRITE_REQUESTED:\r
549                 WriteStartJob();\r
550                 break;\r
551 \r
552         case FEE_WRITE_MAGIC_EREASE_PENDING:\r
553                 PollFlsJobResult();\r
554                 if (FLASH_READY) {\r
555                         WriteCheckMagicEraseJob();\r
556                 }\r
557                 break;\r
558 \r
559         case FEE_WRITE_EREASE_PENDING:\r
560                 PollFlsJobResult();\r
561                 if (FLASH_READY) {\r
562                         WriteCheckEraseJob();\r
563                 }\r
564                 break;\r
565 \r
566         case FEE_WRITE_PENDING:\r
567                 PollFlsJobResult();\r
568                 if (FLASH_READY) {\r
569                         WriteCheckWriteJob();\r
570                 }\r
571                 break;\r
572 \r
573         case FEE_WRITE_BLOCK_ADMIN_PENDING:\r
574                 PollFlsJobResult();\r
575                 if (FLASH_READY) {\r
576                         FinnishJob();\r
577                 }\r
578                 break;\r
579 \r
580         // Invalidate states\r
581         case FEE_INVALIDATE_REQUESTED:\r
582                 InvalidateStartJob();\r
583                 break;\r
584 \r
585         case FEE_INVALIDATE_PENDING:\r
586                 PollFlsJobResult();\r
587                 if (FLASH_READY) {\r
588                         FinnishJob();\r
589                 }\r
590                 break;\r
591 \r
592         // Other\r
593         default:\r
594                 break;\r
595         }\r
596 }\r
597 \r
598 \r
599 /***************************************\r
600  *  Call-back notifications functions  *
601  ***************************************/\r
602 #if (FEE_POLLING_MODE == STD_OFF)\r
603 /*\r
604  * Procedure:   Fee_JobEndNotification\r
605  * Reentrant:   No\r
606  */\r
607 void Fee_JobEndNotification(void)\r
608 {\r
609         FlsAdmin.State = FEE_FLS_STATE_READY;\r
610         FlsAdmin.ErrorStatus = E_OK;\r
611         FlsAdmin.JobResult = Fls_GetJobResult();\r
612 }\r
613 \r
614 \r
615 /*\r
616  * Procedure:   Fee_JobErrorNotification\r
617  * Reentrant:   No\r
618  */\r
619 void Fee_JobErrorNotification(void)\r
620 {\r
621         FlsAdmin.State = FEE_FLS_STATE_READY;\r
622         FlsAdmin.ErrorStatus = E_NOT_OK;\r
623         FlsAdmin.JobResult = Fls_GetJobResult();\r
624 }\r
625 #endif\r
626 \r
627 \r