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