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