]> rtime.felk.cvut.cz Git - arc.git/blob - memory/NvM/NvM.c
Updates after lint check
[arc.git] / memory / NvM / NvM.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  *  General requirements\r
21  */\r
22 /** @req NVM076 */\r
23 /** @req NVM552 */\r
24 /** @req NVM689 */\r
25 \r
26 \r
27 /*\r
28  * NB! Even though some code exist for handling crc, the functionality is not complete\r
29  * and shall not be used.
30  */\r
31 // 522 PC-Lint exception for empty functions\r
32 //lint -esym(522,CalcCrc)\r
33 //lint -emacro(904,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
34 \r
35 \r
36 #include "NvM.h"\r
37 #include "NvM_Cbk.h"\r
38 #include "Rte.h" // ???\r
39 #if defined(USE_DEM)\r
40 #include "Dem.h"\r
41 #endif\r
42 #include "MemIf.h"\r
43 //#include "SchM_NvM.h"\r
44 #include "MemMap.h"\r
45 //#include "Crc.h" // Optional\r
46 \r
47 /*\r
48  * Local definitions
49  */\r
50 #define NVM_SERVICE_ID          0x00            // TODO: What number shall this ID have?\r
51 \r
52 #if  ( NVM_DEV_ERROR_DETECT == STD_ON )\r
53 #include "Det.h"\r
54 #define VALIDATE(_exp,_api,_err ) \\r
55         if( !(_exp) ) { \\r
56           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
57         }\r
58 \r
59 /*\r
60 #define VALIDATE_RV(_exp,_api,_err,_rv ) \\r
61         if( !(_exp) ) { \\r
62           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
63           return _rv; \\r
64         }\r
65 */\r
66 \r
67 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
68         if( !(_exp) ) { \\r
69           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
70           return; \\r
71         }\r
72 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)\r
73 \r
74 #else\r
75 #define VALIDATE(_exp,_api,_err )\r
76 #define VALIDATE_RV(_exp,_api,_err,_rv )\r
77 #define VALIDATE_NO_RV(_exp,_api,_err )\r
78 #define DET_REPORTERROR(_module,_instance,_api,_err)\r
79 #endif\r
80 \r
81 #define BLOCK_BASE_AND_SET_TO_BLOCKNR(_blockbase, _set) ((uint16)(_blockbase << NVM_DATASET_SELECTION_BITS) | _set)\r
82 \r
83 \r
84 // State variable\r
85 typedef enum {\r
86   NVM_UNINITIALIZED = 0,\r
87   NVM_IDLE,\r
88   NVM_READ_ALL_REQUESTED,\r
89   NVM_READ_ALL_PROCESSING,\r
90   NVM_READ_ALL_PENDING,\r
91   NVM_WRITE_ALL_REQUESTED,\r
92   NVM_WRITE_ALL_PROCESSING,\r
93   NVM_WRITE_ALL_PENDING\r
94 } NvmStateType;\r
95 \r
96 typedef enum {\r
97         BLOCK_STATE_IDLE,\r
98         BLOCK_STATE_RECALC_CRC,\r
99         BLOCK_STATE_RECALC_CRC_DONE,\r
100         BLOCK_STATE_POSTCALC_CRC,\r
101         BLOCK_STATE_POSTCALC_CRC_DONE,\r
102 \r
103         BLOCK_STATE_LOAD_FROM_NV,\r
104 //      BLOCK_STATE_LOAD_FROM_NV_DONE,\r
105 //      BLOCK_STATE_LOAD_FROM_NV_REDUNDANT,\r
106 //      BLOCK_STATE_LOAD_FROM_ROM,\r
107 \r
108         BLOCK_STATE_WRITE_TO_NV\r
109 //      BLOCK_STATE_WRITE_TO_NV_DONE\r
110 } BlockStateType;\r
111 \r
112 \r
113 static NvmStateType nvmState = NVM_UNINITIALIZED;\r
114 \r
115 typedef struct {\r
116         BlockStateType                  BlockState;\r
117         uint8                                   DataIndex;                              // Selected data index if "Data Set" type\r
118         boolean                                 BlockWriteProtected;    // Block write protected?\r
119         NvM_RequestResultType   ErrorStatus;                    // Status of block\r
120         boolean                                 BlockChanged;                   // Block changed?\r
121         boolean                                 BlockValid;                             // Block valid?\r
122         uint8                                   NumberOfWriteFailed;    // Current write retry cycle\r
123 } AdministrativeBlockType;\r
124 \r
125 static AdministrativeBlockType AdminBlock[NVM_NUM_OF_NVRAM_BLOCKS];\r
126 \r
127 typedef struct {\r
128         NvM_RequestResultType   ErrorStatus;                    // Status from multi block requests i.e. Read/Write/CancelWrite-all\r
129 } AdministrativeMultiBlockType;\r
130 \r
131 static AdministrativeMultiBlockType AdminMultiBlock;\r
132 \r
133 /*\r
134  * This function needs to be implemented!
135  */\r
136 static void CalcCrc(void)\r
137 {\r
138         // TODO: Calculate CRC\r
139 }\r
140 \r
141 typedef struct {\r
142         boolean JobFinished;\r
143         Std_ReturnType JobStatus;\r
144         MemIf_JobResultType JobResult;\r
145         const NvM_BlockDescriptorType *BlockDescriptor;\r
146         AdministrativeBlockType *BlockAdmin;\r
147 } MemIfJobAdminType;\r
148 \r
149 static MemIfJobAdminType MemIfJobAdmin = {\r
150                 .JobFinished = TRUE,\r
151                 .JobStatus = E_OK,\r
152                 .JobResult = MEMIF_JOB_OK,\r
153                 .BlockDescriptor = NULL,\r
154                 .BlockAdmin = NULL\r
155 };\r
156 \r
157 typedef struct {\r
158         uint16                                  NextBlockIndex;         // Keeps track of next unfinished block\r
159         NvM_RequestResultType   PendingErrorStatus;     // Status from multi block requests i.e. Read/Write/CancelWrite-all\r
160 } AdminMultiReqType;\r
161 \r
162 static AdminMultiReqType AdminMultiReq;\r
163 \r
164 /*\r
165  * Set the MemIf job as busy
166  */\r
167 static void SetMemifJobBusy()\r
168 {\r
169         MemIfJobAdmin.JobFinished = FALSE;\r
170 }\r
171 \r
172 \r
173 #if (NVM_POLLING_MODE == STD_ON)\r
174 /*\r
175  * Check if the MemIf job is finished
176  */\r
177 static boolean CheckMemIfJobFinished(void)\r
178 {\r
179         MemIf_JobResultType jobResult;\r
180 \r
181         if (!MemIfJobAdmin.JobFinished) {\r
182                 jobResult = MemIf_GetJobResult();\r
183 \r
184                 if (jobResult == MEMIF_JOB_OK) {\r
185                         MemIfJobAdmin.JobFinished = TRUE;\r
186                         MemIfJobAdmin.JobStatus = E_OK;\r
187                         MemIfJobAdmin.JobResult = jobResult;\r
188                 } else if (jobResult != MEMIF_JOB_PENDING) {\r
189                         MemIfJobAdmin.JobFinished = TRUE;\r
190                         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
191                         MemIfJobAdmin.JobResult = jobResult;\r
192                 }\r
193         }\r
194 \r
195         return MemIfJobAdmin.JobFinished;\r
196 }\r
197 #else\r
198 /*\r
199  * Check if the MemIf job is finished\r
200  */\r
201 static boolean CheckMemIfJobFinished(void)\r
202 {\r
203         return MemIfJobAdmin.JobFinished;\r
204 }\r
205 #endif\r
206 \r
207 \r
208 /*\r
209  * Abort the MemIf job with E_NOT_OK\r
210  */\r
211 static void AbortMemIfJob(MemIf_JobResultType jobResult)\r
212 {\r
213         MemIfJobAdmin.JobFinished = TRUE;\r
214         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
215         MemIfJobAdmin.JobResult = jobResult;\r
216 }\r
217 \r
218 \r
219 /*\r
220  * Request a read of a block from MemIf
221  */\r
222 static void ReadBlock(const NvM_BlockDescriptorType *blockDescriptor, AdministrativeBlockType *adminBlock, uint8 setNumber, uint8 *destAddress)\r
223 {\r
224         Std_ReturnType returnCode;\r
225         uint16 blockOffset = 0; // TODO: How to calculate this?\r
226 \r
227         if (setNumber < blockDescriptor->NvBlockNum) {\r
228                 SetMemifJobBusy();\r
229                 MemIfJobAdmin.BlockAdmin = adminBlock;\r
230                 MemIfJobAdmin.BlockDescriptor = blockDescriptor;\r
231                 returnCode = MemIf_Read(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), blockOffset, destAddress, blockDescriptor->NvBlockLength);\r
232                 if (returnCode != E_OK) {\r
233                         AbortMemIfJob(MEMIF_JOB_FAILED);\r
234                 }\r
235         } else if (setNumber < blockDescriptor->NvBlockNum + blockDescriptor->RomBlockNum) {\r
236                 // TODO: Read from ROM\r
237         } else {\r
238                 // Error: setNumber out of range\r
239                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_READ_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);\r
240         }\r
241 }\r
242 \r
243 \r
244 /*\r
245  * Initiate the read all job
246  */\r
247 static void ReadAllInit(void)\r
248 {\r
249         /*\r
250          * Initiate the read all job
251          */\r
252         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
253         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
254         uint16 i;\r
255 \r
256         nvmState = NVM_READ_ALL_PROCESSING;\r
257         AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;\r
258         AdminMultiReq.NextBlockIndex = 0;\r
259 \r
260         for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
261                 if ((BlockDescriptorList->SelectBlockForReadall)\r
262 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)                                            /** @req NVM345 */\r
263                                 && ((!AdminBlockTable->BlockValid)                      // TODO: Check if this is to be done like this\r
264                                 || (!AdminBlockTable->BlockChanged))            // TODO: Check if this is to be done like this\r
265 #endif\r
266                                 ) {\r
267                         VALIDATE_NO_RV(BlockDescriptorList->RamBlockDataAddress != NULL, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);\r
268                         VALIDATE_NO_RV(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);\r
269                         if (BlockDescriptorList->CalcRamBlockCrc) {\r
270                                 VALIDATE(BlockDescriptorList->BlockUseCrc == STD_ON, NVM_READ_ALL_ID, NVM_E_BLOCK_CONFIG);\r
271                                 AdminBlockTable->BlockState = BLOCK_STATE_RECALC_CRC;\r
272                         } else {\r
273                                 AdminBlockTable->BlockState = BLOCK_STATE_LOAD_FROM_NV;\r
274                         }\r
275                 } else {\r
276                         AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED;\r
277                 }\r
278 \r
279                 AdminBlockTable++;\r
280                 BlockDescriptorList++;\r
281         }\r
282 }\r
283 \r
284 \r
285 /*\r
286  * Main function for the read all job
287  */\r
288 static void ReadAllMain(void)\r
289 {\r
290         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
291         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
292         uint16 i;\r
293 \r
294         // Search forward to first unfinished block\r
295         while ((AdminMultiReq.NextBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) && (AdminBlockTable[AdminMultiReq.NextBlockIndex].ErrorStatus != NVM_REQ_PENDING)) {\r
296                 AdminMultiReq.NextBlockIndex++;\r
297         }\r
298 \r
299         if (AdminMultiReq.NextBlockIndex == NVM_NUM_OF_NVRAM_BLOCKS) {\r
300                 // All block processed\r
301                 if (AdminMultiReq.PendingErrorStatus == NVM_REQ_OK) {\r
302                         AdminMultiBlock.ErrorStatus = NVM_REQ_OK;\r
303                 } else {\r
304                         AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;\r
305                 }\r
306 \r
307                 nvmState = NVM_IDLE;\r
308 \r
309                 if (NvM_Config.Common.MultiBlockCallback != NULL) {\r
310                         NvM_Config.Common.MultiBlockCallback(NVM_SERVICE_ID, AdminMultiBlock.ErrorStatus);\r
311                 }\r
312 \r
313         } else {\r
314                 for (i = AdminMultiReq.NextBlockIndex; (i < NVM_NUM_OF_NVRAM_BLOCKS) && (nvmState == NVM_READ_ALL_PROCESSING); i++) {\r
315                         switch (AdminBlockTable[i].BlockState) {\r
316                         case BLOCK_STATE_POSTCALC_CRC_DONE:\r
317                                 // TODO: Check CRC\r
318                                 break;\r
319 \r
320                         case BLOCK_STATE_RECALC_CRC_DONE:\r
321                                 // TODO: If CRC is ok do not reload from NVRAM\r
322                                 // TODO: else reload\r
323                                 break;\r
324 \r
325                         case BLOCK_STATE_LOAD_FROM_NV:\r
326                                 nvmState = NVM_READ_ALL_PENDING;\r
327                                 ReadBlock(&BlockDescriptorList[i], &AdminBlockTable[i], 0, BlockDescriptorList[i].RamBlockDataAddress);\r
328                                 break;\r
329 \r
330                         default:\r
331                                 break;\r
332                         } // Switch\r
333                 } // for\r
334         } // else\r
335 }\r
336 \r
337 \r
338 /*\r
339  * Handles the MemIf result of one block read
340  */\r
341 static void ReadAllCheckReadResult(void)\r
342 {\r
343         if (MemIfJobAdmin.JobStatus == E_OK) {\r
344                 if (MemIfJobAdmin.BlockDescriptor->BlockUseCrc) {\r
345                         MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_POSTCALC_CRC; /** @req NVM292 */\r
346                 } else {\r
347                         MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_IDLE;\r
348                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_OK;\r
349                         MemIfJobAdmin.BlockAdmin->BlockValid = TRUE;\r
350                         MemIfJobAdmin.BlockAdmin->BlockChanged = FALSE;\r
351 \r
352                         if (MemIfJobAdmin.BlockDescriptor->WriteBlockOnce) {\r
353                                 MemIfJobAdmin.BlockAdmin->BlockWriteProtected = TRUE;\r
354                         }\r
355 \r
356                         if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
357                                 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus); /** @req NVM281 */\r
358                         }\r
359                 }\r
360         } else {\r
361                 // TODO: Handle reread from NVRAM if type NVM_BLOCK_REDUNDANT\r
362                 // TODO: Handle read from ROM if available\r
363 \r
364                 // Read has failed\r
365                 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;\r
366 \r
367                 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_IDLE;\r
368                 MemIfJobAdmin.BlockAdmin->BlockValid = FALSE;\r
369                 MemIfJobAdmin.BlockAdmin->BlockChanged = FALSE;\r
370 \r
371                 switch (MemIfJobAdmin.JobResult ) {\r
372                 case MEMIF_BLOCK_INVALID:\r
373                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NV_INVALIDATED; /** @req NVM342 */\r
374                         break;\r
375 \r
376                 case MEMIF_BLOCK_INCONSISTENT:                                                                          /** @req NVM360 */\r
377                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;\r
378 #if defined(USE_DEM)\r
379                 Dem_ReportErrorStatus(NVM_E_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);\r
380 #endif\r
381                         break;\r
382 \r
383                 case MEMIF_JOB_FAILED:                                                                                          /** @req NVM361 */\r
384                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK;\r
385 #if defined(USE_DEM)\r
386                         Dem_ReportErrorStatus(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);\r
387 #endif\r
388                         break;\r
389 \r
390                 default:\r
391                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK;\r
392                         break;\r
393                 }\r
394 \r
395                 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
396                         (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus); /** @req NVM281 */\r
397                 }\r
398         }\r
399         nvmState = NVM_READ_ALL_PROCESSING;\r
400 }\r
401 \r
402 \r
403 /*\r
404  * Request writing of a block to MemIf
405  */\r
406 static void WriteBlock(const NvM_BlockDescriptorType *blockDescriptor, AdministrativeBlockType *adminBlock, uint8 setNumber, uint8 *sourceAddress)\r
407 {\r
408         Std_ReturnType returnCode;\r
409 \r
410         if (setNumber < blockDescriptor->NvBlockNum) {\r
411                 SetMemifJobBusy();\r
412                 MemIfJobAdmin.BlockAdmin = adminBlock;\r
413                 MemIfJobAdmin.BlockDescriptor = blockDescriptor;\r
414                 returnCode = MemIf_Write(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), sourceAddress);\r
415                 if (returnCode != E_OK) {\r
416                         AbortMemIfJob(MEMIF_JOB_FAILED);\r
417                 }\r
418         } else {\r
419                 // Error: setNumber out of range\r
420                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_WRITE_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);\r
421         }\r
422 }\r
423 \r
424 \r
425 /*\r
426  * Initiate the write all job\r
427  */\r
428 static void WriteAllInit(void)\r
429 {\r
430         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
431         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
432         uint16 i;\r
433 \r
434         nvmState = NVM_WRITE_ALL_PROCESSING;\r
435         AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;\r
436         AdminMultiReq.NextBlockIndex = 0;\r
437 \r
438         for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
439                 if ((BlockDescriptorList->RamBlockDataAddress != NULL)\r
440 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)                                            /** @req NVM344 */\r
441                                 && (AdminBlockTable->BlockValid)                                        /** @req NVM682 */\r
442                                 && (AdminBlockTable->BlockChanged)                                      /** @req NVM682 */\r
443 #endif\r
444                                 && (!AdminBlockTable->BlockWriteProtected)){                    /** @req NVM432 *//** @req NVM433 */\r
445                         if (BlockDescriptorList->BlockUseCrc) {\r
446                                 AdminBlockTable->BlockState = BLOCK_STATE_RECALC_CRC;   /** @req NVM253 */\r
447                         } else {\r
448                                 AdminBlockTable->BlockState = BLOCK_STATE_WRITE_TO_NV;\r
449                                 AdminBlockTable->NumberOfWriteFailed = 0;\r
450                         }\r
451                 } else {\r
452                         AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED;   /** @req NVM298 */\r
453                 }\r
454 \r
455                 AdminBlockTable++;\r
456                 BlockDescriptorList++;\r
457         }\r
458 }\r
459 \r
460 \r
461 /*\r
462  * Main function for the write all job\r
463  */\r
464 static void WriteAllMain(void)\r
465 {\r
466         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
467         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
468         uint16 i;\r
469 \r
470         // Search forward to first unfinished block\r
471         while ((AdminMultiReq.NextBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) && (AdminBlockTable[AdminMultiReq.NextBlockIndex].ErrorStatus != NVM_REQ_PENDING)) {\r
472                 AdminMultiReq.NextBlockIndex++;\r
473         }\r
474 \r
475         if (AdminMultiReq.NextBlockIndex == NVM_NUM_OF_NVRAM_BLOCKS) {\r
476                 // All block processed\r
477                 if (AdminMultiReq.PendingErrorStatus == NVM_REQ_OK) {\r
478                         AdminMultiBlock.ErrorStatus = NVM_REQ_OK;\r
479                 } else {\r
480                         AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;\r
481                 }\r
482 \r
483                 nvmState = NVM_IDLE;\r
484 \r
485                 if (NvM_Config.Common.MultiBlockCallback != NULL) {\r
486                         NvM_Config.Common.MultiBlockCallback(NVM_SERVICE_ID, AdminMultiBlock.ErrorStatus);\r
487                 }\r
488 \r
489         } else {\r
490                 for (i = AdminMultiReq.NextBlockIndex; (i < NVM_NUM_OF_NVRAM_BLOCKS) && (nvmState == NVM_WRITE_ALL_PROCESSING); i++) {\r
491                         switch (AdminBlockTable[i].BlockState) {\r
492                         case BLOCK_STATE_POSTCALC_CRC_DONE:\r
493                                 // TODO: Check CRC\r
494                                 break;\r
495 \r
496                         case BLOCK_STATE_RECALC_CRC_DONE:\r
497                                 // TODO: If CRC is ok do not reload from NVRAM\r
498                                 // TODO: else reload\r
499                                 break;\r
500 \r
501                         case BLOCK_STATE_WRITE_TO_NV:\r
502                                 nvmState = NVM_WRITE_ALL_PENDING;\r
503                                 WriteBlock(&BlockDescriptorList[i], &AdminBlockTable[i], 0, BlockDescriptorList[i].RamBlockDataAddress);\r
504                                 break;\r
505 \r
506                         default:\r
507                                 break;\r
508                         } // Switch\r
509                 } // for\r
510         } // else\r
511 }\r
512 \r
513 \r
514 /*\r
515  * Handles the result of one MemIf block write\r
516  */\r
517 static void WriteAllCheckWriteResult(void)\r
518 {\r
519         if (MemIfJobAdmin.JobStatus == E_OK) {\r
520                 // TODO: Check if redundant block shall be written NVM337\r
521 \r
522                 if (MemIfJobAdmin.BlockDescriptor->WriteBlockOnce) {\r
523                         MemIfJobAdmin.BlockAdmin->BlockWriteProtected = TRUE;   /** @req NVM329 */\r
524                 }\r
525                 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_IDLE;\r
526                 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_OK;\r
527 \r
528                 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
529                         (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);\r
530                 }\r
531         } else {\r
532                 MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed++;\r
533                 if (MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES) {\r
534                         // TODO: Check if redundant block shall be written NVM337\r
535 \r
536                         // Write has failed\r
537                         AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;\r
538 \r
539                         MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_IDLE;\r
540                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK; /** @req NVM296 */\r
541 #if defined(USE_DEM)\r
542                         Dem_ReportErrorStatus(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);\r
543 #endif\r
544 \r
545                         if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
546                                 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);\r
547                         }\r
548                 }\r
549         }\r
550         nvmState = NVM_WRITE_ALL_PROCESSING;\r
551 }\r
552 \r
553 \r
554 /***************************************\r
555  *    External accessible functions    *\r
556  ***************************************/\r
557 /*\r
558  * Procedure:   NvM_Init\r
559  * Reentrant:   No\r
560  */\r
561 void NvM_Init(void)\r
562 {\r
563         /** @req NVM399 *//** @req NVM193 */\r
564         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
565         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
566         uint16 i;\r
567 \r
568         // Initiate the administration blocks\r
569         for (i = 0; i< NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
570                 if (BlockDescriptorList->BlockManagementType == NVM_BLOCK_DATASET) {\r
571                         AdminBlockTable->DataIndex = 0; /** @req NVM192 */\r
572                 }\r
573                 AdminBlockTable->BlockWriteProtected = BlockDescriptorList->BlockWriteProt;\r
574                 AdminBlockTable->ErrorStatus = NVM_REQ_NOT_OK;\r
575                 AdminBlockTable->BlockChanged = FALSE;\r
576                 AdminBlockTable->BlockValid = FALSE;\r
577                 AdminBlockTable->NumberOfWriteFailed = 0;\r
578 \r
579                 AdminBlockTable++;\r
580                 BlockDescriptorList++;\r
581         }\r
582 \r
583         AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;\r
584 \r
585         // Set status to initialized\r
586         nvmState = NVM_IDLE;    /** @req NVM399 */\r
587 }\r
588 \r
589 \r
590 /*\r
591  * Procedure:   NvM_ReadAll\r
592  * Reentrant:   No\r
593  */\r
594 void NvM_ReadAll(void)\r
595 {\r
596         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
597         uint16 i;\r
598 \r
599         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);\r
600         // Check queue\r
601         // TODO: Check queue\r
602 \r
603         // Check state\r
604         if (nvmState == NVM_IDLE) {\r
605                 nvmState = NVM_READ_ALL_REQUESTED;              /** @req NVM243 */\r
606 \r
607                 // Set status to pending in the administration blocks\r
608                 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;\r
609 \r
610                 for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
611                         AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;\r
612                         AdminBlockTable++;\r
613                 }\r
614         }\r
615 }\r
616 \r
617 \r
618 /*\r
619  * Procedure:   NvM_WriteAll\r
620  * Reentrant:   No\r
621  */\r
622 void NvM_WriteAll(void)\r
623 {\r
624         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
625         uint16 i;\r
626 \r
627         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);\r
628         // Check queue\r
629         // TODO: Check queue\r
630 \r
631         // Check state\r
632         if (nvmState == NVM_IDLE) {\r
633                 nvmState = NVM_WRITE_ALL_REQUESTED;             /** @req NVM254 */\r
634 \r
635                 // Set status to pending in the administration blocks\r
636                 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;\r
637 \r
638                 for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
639                         AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;         /** @req NVM549 */\r
640                         AdminBlockTable++;\r
641                 }\r
642         }\r
643 }\r
644 \r
645 \r
646 /*\r
647  * Procedure:   NvM_CancelWriteAll\r
648  * Reentrant:   No\r
649  */\r
650 void NvM_CancelWriteAll(void)\r
651 {\r
652         \r
653 }\r
654 \r
655 \r
656 /*\r
657  * Procedure:   NvM_GetErrorStatus\r
658  * Reentrant:   Yes\r
659  */\r
660 void NvM_GetErrorStatus(NvM_BlockIdType blockId, uint8 *requestResultPtr)\r
661 {\r
662         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_GET_ERROR_STATUS_ID, NVM_E_NOT_INITIALIZED);\r
663         VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_GET_ERROR_STATUS_ID, NVM_E_PARAM_BLOCK_ID);\r
664 \r
665         if (blockId == 0) {\r
666                 // Multiblock ID\r
667                 *requestResultPtr = AdminMultiBlock.ErrorStatus;\r
668         } else {\r
669                 *requestResultPtr = AdminBlock[blockId-1].ErrorStatus;\r
670         }\r
671 \r
672 }\r
673 \r
674 \r
675 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)    /** @req NVM408 */\r
676 /*\r
677  * Procedure:   Nvm_SetRamBlockStatus\r
678  * Reentrant:   Yes\r
679  */\r
680 void Nvm_SetRamBlockStatus(NvM_BlockIdType blockId, boolean blockChanged)\r
681 {\r
682         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
683 \r
684         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_NOT_INITIALIZED);      /** @req NVM497 */\r
685         VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);\r
686         VALIDATE_NO_RV(blockId > 1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);\r
687 \r
688         if (BlockDescriptorList[blockId-1].RamBlockDataAddress != NULL) {       /** @req NVM240 */\r
689                 if (blockChanged) {\r
690                         AdminBlock[blockId-1].BlockChanged = TRUE;      /** @req NVM406 */\r
691                         AdminBlock[blockId-1].BlockValid = TRUE;        /** @req NVM241 */\r
692                         if (BlockDescriptorList[blockId-1].BlockUseCrc) {\r
693                                 AdminBlock[blockId-1].BlockState = BLOCK_STATE_RECALC_CRC;      /** @req NVM121 */\r
694                         }\r
695                 } else {\r
696                         AdminBlock[blockId-1].BlockChanged = FALSE;     /** @req NVM405 */\r
697                         AdminBlock[blockId-1].BlockValid = FALSE;\r
698                 } // else blockChanged\r
699         } // if permanent block\r
700 }\r
701 #endif\r
702 \r
703 \r
704 /***************************************\r
705  *         Scheduled functions         *\r
706  ***************************************/\r
707 /*\r
708  * Procedure:   NvM_MainFunction\r
709  * Reentrant:   No\r
710  */\r
711 void NvM_MainFunction(void)\r
712 {\r
713         switch (nvmState) {\r
714         case NVM_UNINITIALIZED:\r
715                 break;\r
716 \r
717         case NVM_IDLE:\r
718                 CalcCrc();\r
719                 break;\r
720 \r
721         case NVM_READ_ALL_REQUESTED:\r
722                 ReadAllInit();\r
723                 break;\r
724 \r
725         case NVM_READ_ALL_PROCESSING:\r
726                 if (MemIf_GetStatus() == MEMIF_IDLE) {\r
727                         ReadAllMain();\r
728                 }\r
729                 CalcCrc();\r
730                 break;\r
731 \r
732         case NVM_READ_ALL_PENDING:\r
733                 if (CheckMemIfJobFinished()) {\r
734                         ReadAllCheckReadResult();\r
735                 }\r
736                 CalcCrc();\r
737                 break;\r
738 \r
739         case NVM_WRITE_ALL_REQUESTED:\r
740                 WriteAllInit();\r
741                 break;\r
742 \r
743         case NVM_WRITE_ALL_PROCESSING:\r
744                 if (MemIf_GetStatus() == MEMIF_IDLE) {\r
745                         WriteAllMain();\r
746                 }\r
747                 CalcCrc();\r
748                 break;\r
749 \r
750         case NVM_WRITE_ALL_PENDING:\r
751                 if (CheckMemIfJobFinished()) {\r
752                         WriteAllCheckWriteResult();\r
753                 }\r
754                 CalcCrc();\r
755                 break;\r
756 \r
757         default:\r
758                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_MAIN_FUNCTION_ID, NVM_UNEXPECTED_STATE);\r
759                 break;\r
760         }\r
761 }\r
762 \r
763 \r
764 /***************************************\r
765  *  Call-back notifications functions  *\r
766  ***************************************/\r
767 #if (NVM_POLLING_MODE == STD_OFF)\r
768 /*\r
769  * Procedure:   NvM_JobEndNotification\r
770  * Reentrant:   No\r
771  */\r
772 void NvM_JobEndNotification(void)\r
773 {\r
774         MemIfJobAdmin.JobFinished = TRUE;\r
775         MemIfJobAdmin.JobStatus = E_OK;\r
776         MemIfJobAdmin.JobResult = MemIf_GetJobResult();\r
777 }\r
778 \r
779 /*\r
780  * Procedure:   NvM_JobErrorNotification\r
781  * Reentrant:   No\r
782  */\r
783 void NvM_JobErrorNotification(void)\r
784 {\r
785         MemIfJobAdmin.JobFinished = TRUE;\r
786         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
787         MemIfJobAdmin.JobResult = MemIf_GetJobResult();\r
788 }\r
789 #endif\r
790 \r