]> rtime.felk.cvut.cz Git - arc.git/blob - memory/NvM/NvM.c
Correction to non-aligned IO read/write.
[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  * Author: Peter+mahi\r
19  *\r
20  * Part of Release:\r
21  *   3.1.5\r
22  *\r
23  * Description:\r
24  *   Implements the NVRAM Manager module.\r
25  *\r
26  * Support:\r
27  *   General                  Have Support\r
28  *   -------------------------------------------\r
29  *   NVM_API_CONFIG_CLASS           Y NVM_API_CONFIG_CLASS_1 and NVM_API_CONFIG_CLASS_2\r
30  *   NVM_COMPILED_CONFIG_ID                     N\r
31  *   NVM_CRC_NUM_OF_BYTES               N\r
32  *   NVM_DATASET_SELECTION_BITS     Y\r
33  *   NVM_DEV_ERROR_DETECT           Y\r
34  *   NVM_DRV_MODE_SWITCH            N\r
35  *   NVM_DYNAMIC_CONFIGURATION      N\r
36  *   NVM_JOB_PRIORITIZATION         N\r
37  *   NVM_MULTI_BLOCK_CALLBACK       Y\r
38  *   NVM_POLLING_MODE               N\r
39  *   NVM_SET_RAM_BLOCK_STATUS_API   Y\r
40  *   NVM_SIZE_IMMEDIATE_JOB_QUEUE   N\r
41  *   NVM_SIZE_STANDARD_JOB_QUEUE    Y\r
42  *   NVM_VERSION_INFO_API           Y\r
43  *\r
44  *   NvmBlockDescriptor        Have Support\r
45  *   -------------------------------------------\r
46  *   NvmBlockCRCType                    Y\r
47  *   NvmBlockJobPriority                        N\r
48  *   NvmBlockManagementType             Y, All blocks supported\r
49  *   NvmBlockUseCrc                             Y\r
50  *   NvmBlockWriteProt                          N\r
51  *   NvmCalcRamBlockCrc                         Y\r
52  *   NvmInitBlockCallback                       Y\r
53  *   NvmNvBlockBaseNumber                       Y\r
54  *   NvmNvBlockLength                           Y\r
55  *   NvmNvBlockNum                                      Y\r
56  *   NvmNvramBlockIdentifier            Y\r
57  *   NvmNvramDeviceId                           N (always device Id 0)\r
58  *   NvmResistantToChangedSw            N\r
59  *   NvmRomBlockDataAddress                     Y\r
60  *   NvmRomBlockNum                                     Y\r
61  *   NvmSelectBlockForReadall           Y\r
62  *   NvmSingleBlockCallback             Y\r
63  *   NvmWriteBlockOnce                          N\r
64  *\r
65  *  Implementation notes:\r
66  *   - The Configuration ID NV Block is generated to the configuration but can't be configured.\r
67  *     The Editor should really force you to pick a block in Ea/Fee that should hold the configuration\r
68  *     ID. The NVM_COMPILED_CONFIG_ID is always generated as 0 now.\r
69  *   - You can ONLY configure one block type for the entire NvM since NvmNvramDeviceId is not supported.\r
70  *     ie "Target Block" must all be eihter FEE or EA blocks.\r
71  *   - Differences from 3.1.5 Release (Follow release 4.0.2 here)\r
72  *     NvM_SetDataIndex(), NvM_GetDataIndex, NvM_SetBlockProtection, NvM_GetErrorStatus, NvM_SetRamBlockStatus,\r
73  *     etc....all return Std_ReturnType instead of void since the RTE expects it.\r
74  *   - NvM_GetErrorStatus() uses NvM_GetErrorStatus instead of uint8 *\r
75  */\r
76 \r
77 /*\r
78  * RamBlockDataAddress\r
79  *   NULL is no permanent RAM block. Otherwise allocate the number of bytes in space (like the stack)\r
80  *\r
81  *\r
82  * Understanding block numbering:\r
83  *\r
84  *  NVM_DATASET_SELECTION_BIT=2\r
85  *\r
86  *    NvBlockBaseNumber\r
87  *          0     Reserved (NVM478)\r
88  *          1     NVM_BLOCK_NATIVE,    NvBlockNum=1\r
89  *          2     NVM_BLOCK_REDUNDANT, NvBlockNum=2\r
90  *          3     NVM_BLOCK_DATASET,   NvBlockNum=4\r
91  *\r
92  *   NvM_ReadBlock( 0, ... )    - Reserved for "multi block requests"\r
93  *   NvM_ReadBlock( 1, ... )    - Reserved for redundant NVRAM block which holds the configuration ID.\r
94  *   NvM_ReadBlock( 2--x, ... ) - "Normal" blocks\r
95  *\r
96  *\r
97  *  NvM_BlockIdType*)  NvBlockBaseNumber   EA_BLOCK_NUMBER\r
98  *      0**)\r
99  *      1**)                ***)\r
100  *      2                   1                           4, (5,6,7)  ****)\r
101  *      3                   2                           8, R9,(10,11)  ****)\r
102  *      4                   3                           12, D13,D14,D15 ****)\r
103  *\r
104  *  Should\r
105  *\r
106  *\r
107  *  *) Type used in the API.\r
108  *  **)   Reserved ID's ( 0 - multiblock, 1 - redundant NVRAM block which hold configuration ID)\r
109  *  ***)  Reserved ID\r
110  *  ****) FEE/EA_BLOCK_NUMBER = NvBlockBaseNumber << NvmDatasetSelectionBits = NvBlockBaseNumber * 4\r
111  *        () - Cannot be accesses due to NvBlockNum\r
112  *        R9 - Redundant block\r
113  *        Dx - Data blocks\r
114  *\r
115  *    SIZES\r
116  *      Both NvM and EA/FEE have block sizes. NvM have NvNvmBlockLength (NVM479) and FEE/EA have EaBlockSize.\r
117  *      FEE/EA also have virtual page that is the alignment of a block, with the smallest block=size of the virtual page.\r
118  *\r
119  *      So, who allocates space for this. FEE/EA only have EaBlockSize.\r
120  *      NvM have NvmRamBlockDataAddress, NvmRomBlockDataAddress and mapping to a MemIf Blocks (FEE/EA blocks)\r
121  *\r
122  *      ASSUME: I can't really see a point for the FEE/EA EaBlockSize.. it will just a multiple of NvNvmBlockLength*NvBlockNum + overhead?\r
123  *              Click-box in EA/FEE that leaves the size calculation to NvM?\r
124  *              This also means that enabling NvmBlockUseCrc or set a block from NVM_BLOCK_NATIVE to NVM_BLOCK_DATASET would be "automatic"\r
125  *              in calculation of the EaBlockSize.\r
126  *\r
127  *      So how much data should be read from MemIf if a CRC checksum is used. Assuming that we use a physical layout where the CRC is located\r
128  *      after the NV Block it would be BALIGN(NvNvmBlockLength,4) + 4 bytes. The same applies to the RAM block (ROM block to not have CRC, NVM127)\r
129  *\r
130  * CRC\r
131  *   NVM121: NvM_SetRamBlockStatus(), calculate CRC in background if NvmCalcRamBlockCrc==TRUE\r
132  *   NVM362: NvM_ReadAll() , if (NvmCalcRamBlockCrc == TRUE && permanent RAM block) re-calc CRC.\r
133  *\r
134  *     NvmBlockUseCrc     - Global CRC switch. Space is allocated in both RAM and NV block\r
135  *     NvmCalcRamBlockCrc - CRC re-calculation. For example during startup, you may don't want\r
136  *                          to verify all the checksums again, but instead just copy from NV\r
137  *                          to RAM.\r
138  *\r
139  *     There is also explicit RAM checksum calculations for example NVM253 (Nvm_WriteAll()) where a CRC calculation\r
140  *     is requested (although not stated should be dependent on NvmBlockUseCrc only, not NvmCalcRamBlockCrc).\r
141  *     You have to calculate the checksum at some point....\r
142  *\r
143  * QUEUES\r
144  *   NVM185: Says "successful enqueueing a request".."set to NVM_REQ_PENDING"\r
145  *   NVM380: The queue length for multi block request shall be one (NvM_ReadAll, NvM_WriteAll)\r
146  *   NVM381+NVM567 : Multi block requests shall not be interrupted.\r
147  *   NVM243+NVM245: Do not unqueue the multi block request until all single block queues are empty.\r
148  *     So, when NvmState==IDLE and we have a multi-request\r
149  *\r
150  *\r
151  *\r
152  *\r
153  *\r
154  * SPEED\r
155  *   To get some speed into this multiple thing must be done in the same MainFunction loop.\r
156  *\r
157  * MEMIF\r
158  *   The interface is actually quite strange, so you may read from any address (through MemIf_Read())\r
159  *   but MemIf_Write(..) only takes a logical block and a pointer to the data to write.\r
160  *\r
161  *   See two alternatives here:\r
162  *    1. If the NVBlock also contains the checksum after the data then writing the data needs a\r
163  *       RAM that is as big as the biggest RAM block + room for checksum.\r
164  *    2. If checksums would be kept in a separate EA/FEE block the ALL the checksum need to be written.\r
165  *       For example after a NvM_WriteBlock() the checksum block would need to be written. This\r
166  *       will probably lead consistency problems also... what happens if we fail to write the checksum\r
167  *       block?\r
168  *\r
169  *\r
170  *\r
171  * MANUAL\r
172  *\r
173  *\r
174  *\r
175  *   Provide Data for the first/initial read\r
176  *     When a block have no\r
177  *\r
178  *     NVM085\r
179  *     NVM061\r
180  *     NVM083\r
181  *\r
182  *   Configuring CRCs\r
183  *     BlockUseCrc (A):      If the block (both RAM and NV) should use CRC\r
184  *     CalcRamBlockCrc (B):  If the permanent RAM block should re-calculate it's CRC.\r
185  *\r
186  *     A B\r
187  *     ------------\r
188  *     0 0  No error detection or recovery\r
189  *     0 1  N/A\r
190  *     1 0  ?\r
191  *     1 1  ?\r
192  *\r
193  * RAM BLOCK VALID/UNCHANGED\r
194  *   Figure 8 and 9 in 3.1.5/NVM is more confusing than good.\r
195  *   What we have to know is:\r
196  *    1. Initially the RAM block is in INVALID/UNCHANGED\r
197  *    ALT 2. After a NvM_ReadAll() and all is well the state goes to VALID/UNCHANGED\r
198  *    ALT 2. If ROM values are used we go to VALID/CHANGED (We failed to read from NVRAM)\r
199  *\r
200  *   For NvM_WriteAll()\r
201  *   1. A block that is INVALID can't be written\r
202  *   2. A block that is UNCHANGED should not be written.\r
203  *   -> Write only blocks that are VALID/CHANGED.\r
204  *\r
205  *   VALID/UNCHANGED - RAM == NV\r
206  *   VALID/CHANGED   - RAM != NV   (analog to cache memories, "dirty")\r
207  *\r
208  *   Analog to cache\r
209  *     VALID/CHANGED state - Dirty (since RAM != NV)\r
210  *     WriteBlock          - Flush (Flush the RAM block to NV)\r
211  *     ReadBlock           - Invalidate (NV block is read to RAM)\r
212  */\r
213 \r
214 \r
215 /*\r
216  *  General requirements\r
217  */\r
218 /** @req NVM076 */\r
219 /** @req NVM552 */\r
220 /** @req NVM689 */\r
221 \r
222 \r
223 /*\r
224  * NB! Even though some code exist for handling RamCrc, the functionality is not complete\r
225  * and shall not be used.
226  */\r
227 \r
228 //lint -esym(522,CalcCrc) // 522 PC-Lint exception for empty functions\r
229 //lint -emacro(904,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).\r
230 \r
231 // Exception made as a result of that NVM_DATASET_SELECTION_BITS can be zero\r
232 //lint -emacro(835, BLOCK_BASE_AND_SET_TO_BLOCKNR) // 835 PC-lint: A zero has been given as right argument to operator '<<' or '>>'\r
233 \r
234 \r
235 /* ----------------------------[includes]------------------------------------*/\r
236 \r
237 #include <assert.h>\r
238 #include "NvM.h"\r
239 #include "NvM_Cbk.h"\r
240 #if defined(CFG_NVM_USE_SERVICE_PORTS)\r
241 #include "Rte.h" // ???\r
242 #endif\r
243 #if defined(USE_DEM)\r
244 #include "Dem.h"\r
245 #endif\r
246 #include "MemIf.h"\r
247 //#include "SchM_NvM.h"\r
248 #include "MemMap.h"\r
249 #include "cirq_buffer.h"\r
250 #include "Modules.h"\r
251 #include <stdio.h>\r
252 #include "io.h"\r
253 #include "Crc.h"\r
254 #include <string.h>\r
255 #include "Cpu.h"\r
256 \r
257 #define FIXME           0\r
258 \r
259 //#define DEBUG_BLOCK   1\r
260 #if defined(DEBUG_BLOCK)\r
261 #define DEBUG_BLOCK_STATE(_str,_block,_state)       printf("%s BLOCK NR:%d STATE:%d\n",_str,_block, _state); fflush(stdout);\r
262 #define DEBUG_STATE(_state,_substate)                           printf("MAIN_STATE:%s/%d\n",StateToStr[_state],_substate); fflush(stdout);\r
263 #define DEBUG_PRINTF(format,...)                                        printf(format,## __VA_ARGS__ ); fflush(stdout);\r
264 #define DEBUG_CHECKSUM(_str,_crc)                                       printf("%s crc=%x\n",_str,_crc);\r
265 #else\r
266 #define DEBUG_BLOCK_STATE(_str,_block,_state)\r
267 #define DEBUG_STATE(_state,_substate)\r
268 #define DEBUG_PRINTF(format,...)\r
269 #define DEBUG_CHECKSUM(_str,_crc)\r
270 #endif\r
271 \r
272 \r
273 /* ----------------------------[private define]------------------------------*/\r
274 \r
275 \r
276 \r
277 #define NVM_BLOCK_ALIGNMENT                     4\r
278 #define NVM_CHECKSUM_LENGTH                     4\r
279 \r
280 #define NVM_BLOCK_OFFSET                2\r
281 \r
282 \r
283 \r
284 \r
285 \r
286 /* ----------------------------[private macro]-------------------------------*/\r
287 \r
288 #if defined(DEBUG_BLOCK)\r
289 #define NVM_ASSERT(_exp)                if( !(_exp) ) { assert(_exp); } //\r
290 #else\r
291 #define NVM_ASSERT(_exp)                if( !(_exp) ) { while(1) {}; } //assert(_exp)\r
292 #endif\r
293 \r
294 \r
295 #if  ( NVM_DEV_ERROR_DETECT == STD_ON )\r
296 #define DET_REPORT_ERROR( _api, _err) Det_ReportError(MODULE_ID_NVM, 0, _api, _err);\r
297 #else\r
298 #define DET_REPORT_ERROR( _api, _err)\r
299 #endif\r
300 \r
301 #if  ( NVM_DEV_ERROR_DETECT == STD_ON )\r
302 #include "Det.h"\r
303 #define VALIDATE(_exp,_api,_err ) \\r
304         if( !(_exp) ) { \\r
305           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
306         }\r
307 \r
308 \r
309 #define VALIDATE_RV(_exp,_api,_err,_rv ) \\r
310         if( !(_exp) ) { \\r
311           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
312           return _rv; \\r
313         }\r
314 \r
315 #define VALIDATE_NO_RV(_exp,_api,_err ) \\r
316         if( !(_exp) ) { \\r
317           Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \\r
318           return; \\r
319         }\r
320 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)\r
321 \r
322 #else\r
323 #define VALIDATE(_exp,_api,_err )\r
324 #define VALIDATE_RV(_exp,_api,_err,_rv )\r
325 #define VALIDATE_NO_RV(_exp,_api,_err )\r
326 #define DET_REPORTERROR(_module,_instance,_api,_err)\r
327 #endif\r
328 \r
329 #define BLOCK_BASE_AND_SET_TO_BLOCKNR(_blockbase, _set) ((uint16)(_blockbase) | _set)\r
330 \r
331 #if defined(USE_DEM)\r
332 #define DEM_REPORTERRORSTATUS(_err,_ev ) Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED);\r
333 #else\r
334 #define DEM_REPORTERRORSTATUS(_err,_ev )\r
335 #endif\r
336 \r
337 \r
338 #define BLOCK_NR_FROM_PTR(_bptr)                (((_bptr) - NvM_Config.BlockDescriptor + 1))   // sizeof(NvM_BlockDescriptorType))\r
339 \r
340 #define CREATE_ENTRY(_val)      [_val] = #_val\r
341 \r
342 \r
343 \r
344 \r
345 /* ----------------------------[private typedef]-----------------------------*/\r
346 \r
347 // State variable\r
348 typedef enum {\r
349   NVM_UNINITIALIZED = 0,\r
350   NVM_IDLE,\r
351   NVM_READ_ALL,\r
352   NVM_WRITE_ALL,\r
353   NVM_READ_BLOCK,\r
354   NVM_WRITE_BLOCK,\r
355   NVM_RESTORE_BLOCK_DEFAULTS,\r
356   NVM_SETDATAINDEX,\r
357   NVM_GETDATAINDEX,\r
358   NVM_SETRAMBLOCKSTATUS,\r
359 } NvmStateType;\r
360 \r
361 char *StateToStr[20] = {\r
362         CREATE_ENTRY(NVM_UNINITIALIZED),\r
363         CREATE_ENTRY(NVM_IDLE),\r
364         CREATE_ENTRY(NVM_READ_ALL),\r
365         CREATE_ENTRY(NVM_WRITE_ALL),\r
366         CREATE_ENTRY(NVM_READ_BLOCK),\r
367         CREATE_ENTRY(NVM_WRITE_BLOCK),\r
368         CREATE_ENTRY(NVM_RESTORE_BLOCK_DEFAULTS),\r
369         CREATE_ENTRY(NVM_SETDATAINDEX),\r
370         CREATE_ENTRY(NVM_GETDATAINDEX),\r
371         CREATE_ENTRY(NVM_SETRAMBLOCKSTATUS),\r
372  };\r
373 \r
374 \r
375 typedef enum {\r
376         BLOCK_STATE_MEMIF_REQ,\r
377 //      BLOCK_STATE_START,\r
378         BLOCK_STATE_MEMIF_PROCESS,\r
379 //      BLOCK_STATE_MEMIF_CRC_PROCESS,\r
380         BLOCK_STATE_CALC_CRC,\r
381 //      BLOCK_STATE_MEMIF_PROCESS_CRC,\r
382         BLOCK_STATE_CALC_CRC_WRITE,\r
383         BLOCK_STATE_CALC_CRC_READ,\r
384 //      BLOCK_STATE_LOAD_FROM_NV,\r
385 } BlockStateType;\r
386 \r
387 \r
388 typedef enum {\r
389         BLOCK_SUBSTATE_0,\r
390         BLOCK_SUBSTATE_1,\r
391 } BlockSubStateType;\r
392 \r
393 \r
394 typedef enum {\r
395         NS_INIT = 0,\r
396         NS_PROSSING,\r
397 //      RB_PROCESSING,\r
398 } Nvm_SubStates;\r
399 \r
400 \r
401 union Nvm_CRC {\r
402         uint16 crc16;\r
403         uint32 crc32;\r
404 };\r
405 \r
406 \r
407 typedef struct {\r
408         NvM_RequestResultType   ErrorStatus;                    // Status from multi block requests i.e. Read/Write/CancelWrite-all\r
409 } AdministrativeMultiBlockType;\r
410 \r
411 typedef struct {\r
412         BlockStateType                  BlockState;\r
413         BlockSubStateType       BlockSubState;\r
414         uint8                                   DataIndex;                              // Selected data index if "Data Set" type\r
415         boolean                                 BlockWriteProtected;    // Block write protected?\r
416         NvM_RequestResultType   ErrorStatus;                    // Status of block\r
417         boolean                                 BlockChanged;                   // Block changed?\r
418         boolean                                 BlockValid;                             // Block valid? (RAM block only?)\r
419         uint8                                   NumberOfWriteFailed;    // Current write retry cycle\r
420         union Nvm_CRC                   RamCrc;\r
421         union Nvm_CRC                   NvCrc;                                  // The CRC of this block, read from NV\r
422         void *                                  savedDataPtr;                   //\r
423         uint8                                   crcLen;\r
424         uint8                                   flags;                                  // Used for all sorts of things.\r
425 } AdministrativeBlockType;\r
426 \r
427 /*\r
428 typedef enum {\r
429         NVM_OP_READ_BLOCK,\r
430         NVM_OP_WRITE_BLOCK,\r
431         NVM_OP_RESTORE_BLOCK_DEFAULTS,\r
432 } Nvm_OpType;\r
433 */\r
434 #define OP_READ         0\r
435 #define OP_WRITE        1\r
436 #define NO_MULTIBLOCK   0\r
437 #define MULTIBLOCK              1\r
438 \r
439 \r
440 typedef struct {\r
441         NvmStateType            op;\r
442         NvM_BlockIdType blockId;\r
443         uint8 *                 dataPtr;        /* Src or Dest ptr */\r
444         uint8           dataIndex;\r
445         boolean         blockChanged;\r
446 } Nvm_QueueType;\r
447 \r
448 \r
449 \r
450 /* ----------------------------[private function prototypes]-----------------*/\r
451 /* ----------------------------[private variables]---------------------------*/\r
452 \r
453 static NvmStateType                             nvmState = NVM_UNINITIALIZED;\r
454 \r
455 #define RB_START                        0\r
456 #define RB_WAIT_READ            1\r
457 #define RB_CALC_CHECKSUM        2\r
458 \r
459 static int                                                      nvmSubState = 0;\r
460 //static int nvmSetNr;\r
461 static AdministrativeBlockType          AdminBlock[NVM_NUM_OF_NVRAM_BLOCKS];\r
462 static AdministrativeMultiBlockType AdminMultiBlock;\r
463 \r
464 \r
465 //static Nvm_QueueType  nvmQueueImmData[NVM_SIZE_IMMEDIATE_JOB_QUEUE];\r
466 static Nvm_QueueType  nvmQueueData[NVM_SIZE_STANDARD_JOB_QUEUE];\r
467 \r
468 uint8 Nvm_WorkBuffer[NVM_MAX_BLOCK_LENGTH+4]; /* +4 to make place for max crc length */\r
469 \r
470 #if (NVM_SIZE_STANDARD_JOB_QUEUE == 0)\r
471 #error NVM_SIZE_STANDARD_JOB_QUEUE have size 0\r
472 #endif\r
473 \r
474 \r
475 CirqBufferType nvmQueue;\r
476 \r
477 \r
478 /* ----------------------------[private functions]---------------------------*/\r
479 \r
480 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,\r
481                                                 AdministrativeBlockType *adminBlock,\r
482                                                 uint8 setNumber,\r
483                                                 uint8 *sourceAddress);\r
484 \r
485 static void setRamBlockStatus( const NvM_BlockDescriptorType    *bPtr,\r
486                                                                 AdministrativeBlockType *admPtr,\r
487                                                                 boolean blockChanged );\r
488 \r
489 \r
490 /* ----------------------------[public functions]----------------------------*/\r
491 \r
492 \r
493 \r
494 /*\r
495  * This function needs to be implemented!
496  */\r
497 static void CalcCrc(void)\r
498 {\r
499         // TODO: Calculate CRC\r
500 }\r
501 \r
502 typedef struct {\r
503         boolean                                                 JobFinished;\r
504         Std_ReturnType                                  JobStatus;\r
505         MemIf_JobResultType                     JobResult;\r
506         const NvM_BlockDescriptorType * BlockDescriptor;\r
507         AdministrativeBlockType *               BlockAdmin;\r
508 } MemIfJobAdminType;\r
509 \r
510 static MemIfJobAdminType MemIfJobAdmin = {\r
511                 .JobFinished = TRUE,\r
512                 .JobStatus = E_OK,\r
513                 .JobResult = MEMIF_JOB_OK,\r
514                 .BlockDescriptor = NULL,\r
515                 .BlockAdmin = NULL\r
516 };\r
517 \r
518 enum Nvm_MultiBlockReq {\r
519         MB_REQ_NONE,\r
520         MB_REQ_READ_ALL,\r
521         MB_REQ_WRITE_ALL,\r
522 };\r
523 \r
524 typedef struct {\r
525         NvmStateType                    state;\r
526         uint16                                  currBlockIndex;         // Keeps track of next unfinished block\r
527         NvM_RequestResultType   PendingErrorStatus;     // Status from multi block requests i.e. Read/Write/CancelWrite-all\r
528 } AdminMultiReqType;\r
529 \r
530 static AdminMultiReqType AdminMultiReq;\r
531 \r
532 \r
533 /*\r
534  * Set the MemIf job as busy
535  */\r
536 static void SetMemifJobBusy()\r
537 {\r
538         MemIfJobAdmin.JobFinished = FALSE;\r
539 }\r
540 \r
541 \r
542 #if (NVM_POLLING_MODE == STD_ON)\r
543 /*\r
544  * Check if the MemIf job is finished
545  */\r
546 static boolean CheckMemIfJobFinished(void)\r
547 {\r
548         MemIf_JobResultType jobResult;\r
549 \r
550         if (!MemIfJobAdmin.JobFinished) {\r
551                 jobResult = MemIf_GetJobResult(FIXME);\r
552 \r
553                 if (jobResult == MEMIF_JOB_OK) {\r
554                         MemIfJobAdmin.JobFinished = TRUE;\r
555                         MemIfJobAdmin.JobStatus = E_OK;\r
556                         MemIfJobAdmin.JobResult = jobResult;\r
557                 } else if (jobResult != MEMIF_JOB_PENDING) {\r
558                         MemIfJobAdmin.JobFinished = TRUE;\r
559                         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
560                         MemIfJobAdmin.JobResult = jobResult;\r
561                 }\r
562         }\r
563 \r
564         return MemIfJobAdmin.JobFinished;\r
565 }\r
566 #else\r
567 /*\r
568  * Check if the MemIf job is finished\r
569  */\r
570 \r
571 static boolean CheckMemIfJobFinished(void)\r
572 {\r
573         return MemIfJobAdmin.JobFinished;\r
574 }\r
575 \r
576 #endif\r
577 \r
578 \r
579 /*\r
580  * Abort the MemIf job with E_NOT_OK\r
581  */\r
582 static void AbortMemIfJob(MemIf_JobResultType jobResult)\r
583 {\r
584         MemIfJobAdmin.JobFinished = TRUE;\r
585         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
586         MemIfJobAdmin.JobResult = jobResult;\r
587 }\r
588 \r
589 #if 0\r
590 static boolean CheckJobFailed( void ) {\r
591         return CheckMemIfJobFinished() && (MemIfJobAdmin.JobResult == MEMIF_JOB_FAILED);\r
592 }\r
593 #endif\r
594 \r
595 /*\r
596  * Request a read of a block from MemIf
597  */\r
598 static Std_ReturnType ReadBlock(const NvM_BlockDescriptorType *blockDescriptor,\r
599                                                         AdministrativeBlockType *adminBlock,\r
600                                                         uint8 setNumber,\r
601                                                         uint16 blockOffset,\r
602                                                         uint8 *destAddress,\r
603                                                         uint16 length )\r
604 {\r
605         Std_ReturnType returnCode;\r
606 \r
607         if (setNumber < blockDescriptor->NvBlockNum) {\r
608                 SetMemifJobBusy();\r
609                 MemIfJobAdmin.BlockAdmin = adminBlock;\r
610                 MemIfJobAdmin.BlockDescriptor = blockDescriptor;\r
611                 returnCode = MemIf_Read(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), blockOffset, destAddress, length );\r
612                 if (returnCode != E_OK) {\r
613                         AbortMemIfJob(MEMIF_JOB_FAILED);\r
614                 }\r
615         } else if (setNumber < blockDescriptor->NvBlockNum + blockDescriptor->RomBlockNum) {\r
616                 // TODO: Read from ROM\r
617         } else {\r
618                 // Error: setNumber out of range\r
619                 returnCode = E_NOT_OK;\r
620                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_READ_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);\r
621         }\r
622 \r
623         return returnCode;\r
624 }\r
625 \r
626 \r
627 /*\r
628  * Initiate the read all job
629  */\r
630 static boolean ReadAllInit(void)\r
631 {\r
632         /*\r
633          * Initiate the read all job
634          */\r
635         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
636         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
637         uint16 i;\r
638         boolean needsProcessing = FALSE;\r
639 \r
640         // Set status to pending in the administration blocks\r
641         AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING; /** @req 3.1.5/NVM304 */\r
642         AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;\r
643         AdminMultiReq.currBlockIndex = 0;\r
644 \r
645         for (i = 0; i < ( NVM_NUM_OF_NVRAM_BLOCKS ); i++) {\r
646                 if ((BlockDescriptorList->SelectBlockForReadall)\r
647 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)                                            /** @req NVM345 */\r
648                                 && ((!AdminBlockTable->BlockValid)                      // TODO: Check if this is to be done like this\r
649                                 || (!AdminBlockTable->BlockChanged))            // TODO: Check if this is to be done like this\r
650 #endif\r
651                                 ) {\r
652                         NVM_ASSERT(BlockDescriptorList->RamBlockDataAddress != NULL);\r
653                         VALIDATE_RV(BlockDescriptorList->RamBlockDataAddress != NULL, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG, FALSE );\r
654                         /* 3.1.5/NVM245 */\r
655                         NVM_ASSERT(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET);\r
656                         VALIDATE_RV(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG, FALSE );\r
657 \r
658                         AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;\r
659                         AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;\r
660                         needsProcessing = TRUE;\r
661                 } else {\r
662                         AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED;   /* @req 3.1.5/NVM287 */\r
663                 }\r
664 \r
665                 AdminBlockTable++;\r
666                 BlockDescriptorList++;\r
667         }\r
668 \r
669         return needsProcessing;\r
670 }\r
671 \r
672 \r
673 static void writeCrcToBuffer(   void *bufPtr,\r
674                                                                 const NvM_BlockDescriptorType *bPtr,\r
675                                                                 AdministrativeBlockType *admPtr )\r
676 {\r
677         if( bPtr->BlockUseCrc ) {\r
678                 if(bPtr->BlockCRCType == NVM_CRC16) {\r
679                         WRITE16_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc16);\r
680                 } else {\r
681                         WRITE32_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc32);\r
682                 }\r
683         }\r
684 }\r
685 \r
686 \r
687 /*\r
688  * Drive the read state-machine\r
689  *\r
690  *\r
691  *\r
692  */\r
693 \r
694 static void DriveBlock( const NvM_BlockDescriptorType   *bPtr,\r
695                                                         AdministrativeBlockType *admPtr,\r
696                                                         void *dataPtr,\r
697                                                         boolean write,\r
698                                                         boolean multiBlock,\r
699                                                         boolean restoreFromRom )\r
700 {\r
701         bool blockDone = 0;\r
702 \r
703         DEBUG_BLOCK_STATE("DriveBlock", BLOCK_NR_FROM_PTR(bPtr), admPtr->BlockState );\r
704 \r
705         NVM_ASSERT( admPtr->ErrorStatus == NVM_REQ_PENDING);\r
706 \r
707         switch (admPtr->BlockState) {\r
708         case BLOCK_STATE_MEMIF_REQ:\r
709         {\r
710                 void *ramData = (dataPtr != NULL) ?  dataPtr : bPtr->RamBlockDataAddress;\r
711 \r
712                 admPtr->savedDataPtr = ramData;\r
713 \r
714                 if( write ) {\r
715                         if( multiBlock && (dataPtr!=NULL)) {\r
716                                 NVM_ASSERT(0);\r
717                         }\r
718                         /* Copy to work buffer */\r
719                         memcpy( Nvm_WorkBuffer, ramData, bPtr->NvBlockLength );\r
720                         /* Add the CRC to write */\r
721                         writeCrcToBuffer(Nvm_WorkBuffer, bPtr, admPtr );\r
722                         WriteBlock(bPtr, admPtr, admPtr->DataIndex, Nvm_WorkBuffer);\r
723                 } else {\r
724                         uint8 crcLen = 0;\r
725                         /* Read to workbuffer */\r
726                         if( bPtr->BlockUseCrc ) {\r
727                                 crcLen = (bPtr->BlockCRCType == NVM_CRC16) ? 2: 4;\r
728                         }\r
729 \r
730                         if( restoreFromRom ) {\r
731                                 NVM_ASSERT( bPtr->RomBlockDataAdress != NULL );\r
732                                 /* No CRC on the ROM block */\r
733                                 memcpy(ramData,bPtr->RomBlockDataAdress,bPtr->NvBlockLength);\r
734 \r
735                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
736                                 blockDone = 1;\r
737                                 break;          /* Do NOT advance to next state */\r
738                         } else {\r
739 \r
740                                 if( ReadBlock(bPtr, admPtr, admPtr->DataIndex, 0, Nvm_WorkBuffer, bPtr->NvBlockLength+crcLen) != E_OK ) {\r
741                                         /* Fail the job */\r
742                                         admPtr->ErrorStatus = NVM_REQ_NOT_OK;\r
743                                         blockDone = 1;\r
744                                         break; /* Do NOT advance to next state */\r
745                                 }\r
746                         }\r
747                 }\r
748 \r
749                 admPtr->BlockState = BLOCK_STATE_MEMIF_PROCESS;\r
750                 break;\r
751         }\r
752 \r
753         case BLOCK_STATE_MEMIF_PROCESS:\r
754         {\r
755                 /* Check read */\r
756                 MemIf_JobResultType jobResult = MemIf_GetJobResult(FIXME);\r
757 \r
758                 if( MEMIF_JOB_PENDING == jobResult ) {\r
759                         /* Keep on waiting */\r
760                 } else if( MEMIF_JOB_OK == jobResult ) {\r
761                         /* We are done */\r
762 \r
763 #if 0\r
764                         if( BLOCK_STATE_MEMIF_CRC_PROCESS == admPtr->BlockState ) {\r
765                                 /* @req 3.1.5/NVM362 NvM_ReadAll*/\r
766                                 DEBUG_CHECKSUM("RAM CRC", (bPtr->BlockCRCType == NVM_CRC16) ?  admPtr->RamCrc.crc16 : admPtr->RamCrc.crc32);\r
767                                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;\r
768                                 break;\r
769                         }\r
770 #endif\r
771 \r
772                         if( write ) {\r
773                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
774                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
775                                 blockDone = 1;\r
776 \r
777 #if 0\r
778                                 if( bPtr->BlockUseCrc ) {\r
779                                         /* Explicit CRC calc (not dependent on NvmCalcRamBlockCrc) */\r
780                                         /* @req 3.1.5/NVM212 NvM_WriteBlock */\r
781                                         /* @req 3.1.5/NVM253 NvM_WriteAll   */\r
782                                         admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;\r
783                                 } else {\r
784                                         /* Done */\r
785                                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
786                                         admPtr->ErrorStatus = NVM_REQ_OK;\r
787                                         blockDone = 1;\r
788                                 }\r
789 #endif\r
790                         } else {\r
791                                 /* read */\r
792                                 uint8 crcLen = 0;\r
793                                 if( bPtr->BlockUseCrc ) {\r
794 \r
795                                         /* The read data is in the work buffer, read the CRC */\r
796                                         if( bPtr->BlockCRCType == NVM_CRC16) {\r
797                                                 admPtr->NvCrc.crc16 = READ16_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );\r
798                                                 crcLen = 2;\r
799                                                 DEBUG_PRINTF(">> Nv CRC %04x\n",admPtr->NvCrc.crc16);\r
800                                                 admPtr->RamCrc.crc16 = admPtr->NvCrc.crc16;     /* Set RAM CRC = NvRAM CRC */\r
801                                         } else {\r
802                                                 admPtr->NvCrc.crc32 = READ32_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );\r
803                                                 crcLen = 4;\r
804                                                 DEBUG_PRINTF(">> Nv CRC %08x\n",admPtr->NvCrc.crc16);\r
805                                                 admPtr->RamCrc.crc32 = admPtr->NvCrc.crc32;     /* Set RAM CRC = NvRAM CRC */\r
806                                         }\r
807 \r
808                                         /* 3.1.5/NVM201 + 3.1.5/NVM292 NvM_ReadBlock() + NvM_ReadAll() should request\r
809                                          * recalculation of the RAM block data if configured with CRC.\r
810                                          */\r
811 \r
812                                         /* savedDataPtr points to the real data buffers and they do no contain the\r
813                                          * crcLen */\r
814                                         memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength  );\r
815 \r
816                                         /* Check if we should re-calculate the RAM checksum now when it's in RAM\r
817                                          * 3.1.5/NVM165 */\r
818                                         if( bPtr->CalcRamBlockCrc ) {\r
819                                                 /* This block want its RAM block CRC checked */\r
820                                                 DEBUG_PRINTF(">> Recalculation of RAM checksum \n",admPtr->NvCrc.crc16);\r
821                                                 assert( bPtr->BlockUseCrc == 1);\r
822                                                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;\r
823                                                 admPtr->BlockSubState = BLOCK_SUBSTATE_0;\r
824                                         } else {\r
825                                                 /* Done */\r
826                                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
827                                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
828                                                 blockDone = 1;\r
829                                         }\r
830 \r
831                                 } else {\r
832                                         DEBUG_PRINTF(">> Block have NO CRC\n");\r
833 \r
834                                         memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength  + crcLen );\r
835                                         /* Done */\r
836                                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
837                                         admPtr->ErrorStatus = NVM_REQ_OK;\r
838                                         blockDone = 1;\r
839                                 }\r
840 \r
841                                 /* Copy from Workbuffer to the real buffer */\r
842 \r
843                         }\r
844                         break;\r
845                 } else {\r
846                         /* Something failed */\r
847                         if( write ) {\r
848                                 DEBUG_PRINTF(">> Write FAILED\n");\r
849                                 admPtr->NumberOfWriteFailed++;\r
850                                 if( admPtr->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES ) {\r
851                                         DEBUG_PRINTF(">> Write FAILED COMPLETELY (all retries)\n");\r
852                                         blockDone = 1;\r
853                                 }\r
854                         } else {\r
855                                 blockDone = 1;\r
856                         }\r
857 \r
858                         if( blockDone == 1 ) {\r
859                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ; /* TODO, this really true for all result below */\r
860                                 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;\r
861 \r
862                                 switch( jobResult ) {\r
863                                 case MEMIF_BLOCK_INVALID:\r
864                                         /* @req 3.1.5/NVM342 */\r
865                                         admPtr->ErrorStatus = NVM_REQ_NV_INVALIDATED;\r
866                                         break;\r
867                                 case MEMIF_BLOCK_INCONSISTENT:\r
868                                         /* @req 3.1.5/NVM360 */\r
869                                         admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;\r
870                                         DEM_REPORTERRORSTATUS(NVM_E_REQ_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);\r
871                                         break;\r
872                                 case MEMIF_JOB_FAILED:\r
873                                         /* @req 3.1.5/NVM361 */\r
874                                         admPtr->ErrorStatus = NVM_REQ_NOT_OK;\r
875                                         DEM_REPORTERRORSTATUS(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);\r
876                                         break;\r
877                                 default:\r
878                                         DEBUG_PRINTF("## Unexpected jobResult:%d\n",jobResult);\r
879                                         NVM_ASSERT(0);\r
880                                         break;\r
881                                 }\r
882                         }\r
883                 }\r
884                 break;\r
885         }\r
886 \r
887         case BLOCK_STATE_CALC_CRC:\r
888                 NVM_ASSERT(0);\r
889                 break;\r
890 \r
891         case BLOCK_STATE_CALC_CRC_WRITE:\r
892         {\r
893                 uint16 crc16;\r
894                 uint32 crc32;\r
895                 void *ramData;\r
896 \r
897                 if( bPtr->RamBlockDataAddress == NULL ) {\r
898                         /* If we have no buffer to work with something is very very wrong */\r
899                         NVM_ASSERT(dataPtr != NULL );\r
900                         ramData = dataPtr;\r
901                 } else {\r
902                         ramData = bPtr->RamBlockDataAddress;\r
903                 }\r
904 \r
905                 admPtr->savedDataPtr = ramData;\r
906 \r
907                 /* Calculate RAM CRC checksum */\r
908                 if( bPtr->BlockCRCType == NVM_CRC16 ) {\r
909 \r
910                         crc16 = Crc_CalculateCRC16(ramData,bPtr->NvBlockLength,0xffff);\r
911                         DEBUG_CHECKSUM("RAM",crc16);\r
912 \r
913                         /* Just save the checksum */\r
914                         admPtr->RamCrc.crc16 = crc16;\r
915 \r
916                         /* Write the block */\r
917                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
918                 } else {\r
919                         /* @req 3.1.5/NVM253 */\r
920                         crc32 = Crc_CalculateCRC32(ramData,bPtr->NvBlockLength,0xffffffffUL);\r
921                         DEBUG_CHECKSUM("RAM",crc32);\r
922 \r
923                         admPtr->RamCrc.crc32 = crc32;\r
924                 }\r
925                 /* Write the block */\r
926                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
927 \r
928                 break;\r
929         }\r
930         case BLOCK_STATE_CALC_CRC_READ:\r
931         {\r
932                 //NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );\r
933                 NVM_ASSERT(bPtr->CalcRamBlockCrc == true );\r
934                 uint16 crc16;\r
935                 uint32 crc32;\r
936                 boolean checksumOk;\r
937 \r
938 \r
939                 /* @req 3.1.5/NVM253 */\r
940                 /* Calculate CRC on the data we just read to RAM. Compare with CRC that is located in NV block */\r
941 \r
942                 if( bPtr->BlockCRCType == NVM_CRC16 ) {\r
943                         crc16 = Crc_CalculateCRC16(admPtr->savedDataPtr,bPtr->NvBlockLength,0xffff);\r
944                 } else {\r
945                         crc32 = Crc_CalculateCRC32(admPtr->savedDataPtr,bPtr->NvBlockLength,0xffffffffUL);\r
946                 }\r
947 \r
948                 switch( admPtr->BlockSubState ) {\r
949                 case BLOCK_SUBSTATE_0:\r
950 \r
951                         checksumOk = ( bPtr->BlockCRCType == NVM_CRC16 ) ? ( crc16 ==  admPtr->RamCrc.crc16 ) : ( crc32 ==  admPtr->RamCrc.crc32 );\r
952 \r
953                         /* @req 3.1.5/NVM387 */\r
954                         if( checksumOk ) {\r
955                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
956 \r
957                                 DEBUG_CHECKSUM("RAM checksum ok with ", ( bPtr->BlockCRCType == NVM_CRC16 ) ? crc16 : crc32 );\r
958                                 admPtr->ErrorStatus = NVM_REQ_OK;\r
959                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
960                                 blockDone = 1;\r
961 \r
962                         } else {\r
963                                 /* NVM387, NVM388\r
964                                  * Corrupt CRC, what choices are there:\r
965                                  * 1. Default data (=ROM) configured, just copy it.\r
966                                  * 2. Data redundancy, get it.\r
967                                  * 3. None of the above. Catastrophic failure. (NVM203)\r
968                                  */\r
969 \r
970                                 if( (admPtr->flags != 2) && bPtr->BlockManagementType == NVM_BLOCK_REDUNDANT ) {\r
971                                         /* According to 3.1.5/NVM137 we have 2 NV Blocks and 0..1 ROM Blocks */\r
972                                         /* Req 3.1.5/NVM199 , 3.1.5/NVM279 , 3.1.5/NVM317\r
973                                          * 3.1.5/NVM288, 3.1.5/NVM315\r
974                                          * */\r
975                                         NVM_ASSERT(bPtr->NvBlockNum == 2);              /* Configuration error */\r
976                                         if( admPtr->DataIndex == 0) {\r
977                                                 admPtr->DataIndex = 1;\r
978                                         } else {\r
979                                                 admPtr->DataIndex = 0;\r
980                                         }\r
981                                         admPtr->flags++;\r
982                                         if( admPtr->flags == 2 ) {\r
983                                                 /* We have failed both NV Blocks */\r
984                                                 DEBUG_PRINTF(" # Both redundant NV blocks failed\n");\r
985                                                 admPtr->flags = 0;\r
986                                         } else {\r
987                                                 /* Start over again with the other NV block */\r
988                                                 DEBUG_PRINTF(" # First redundant NV block failed\n");\r
989                                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
990                                                 break;  /* Break from BLOCK_SUBSTATE_0 */\r
991                                         }\r
992                                 }\r
993 \r
994                                 if( bPtr->RomBlockDataAdress != NULL ) {\r
995                                         DEBUG_PRINTF("Copying ROM data to block\n");\r
996                                         memcpy(bPtr->RamBlockDataAddress, bPtr->RomBlockDataAdress,bPtr->NvBlockLength);\r
997                                         admPtr->BlockSubState = BLOCK_SUBSTATE_1;\r
998                                 } else {\r
999 \r
1000                                         /* @req 3.1.5/NVM469 */\r
1001                                         if( bPtr->InitBlockCallback != NULL ) {\r
1002 \r
1003                                                 DEBUG_PRINTF("Filling block with default data\n");\r
1004                                                 bPtr->InitBlockCallback();\r
1005                                                 admPtr->BlockSubState = BLOCK_SUBSTATE_1;\r
1006 \r
1007                                                 /* NVM085 is very vague here, but the says the application should be\r
1008                                                  * able distinguish between when the init-callback have been called\r
1009                                                  * or CRC is corrupt.\r
1010                                                  */\r
1011 \r
1012                                                 /* The RAM CRC is at this point not calculated...so we must do this\r
1013                                                  * .. so just stay in this state one more MainFunction.\r
1014                                                  * */\r
1015 \r
1016                                         } else {\r
1017 \r
1018                                                 DEBUG_PRINTF("### Block FAILED with NVM_REQ_INTEGRITY_FAILED\n");\r
1019 \r
1020 \r
1021                                                 /* @req 3.1.5/NVM203 */\r
1022                                                 DEM_REPORTERRORSTATUS(NVM_E_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);\r
1023                                                 /* @req 3.1.5/NVM204 */\r
1024                                                 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;\r
1025                                                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1026                                                 blockDone = 1;\r
1027                                         }\r
1028                                 }\r
1029                         }\r
1030                         break;\r
1031                 case BLOCK_SUBSTATE_1:\r
1032                         /* The checksum is on the ROM data so just save it */\r
1033                         DEBUG_CHECKSUM("RAM checksum after ROM copy ", ( bPtr->BlockCRCType == NVM_CRC16 ) ? crc16 : crc32 );\r
1034 \r
1035                         if( bPtr->BlockCRCType == NVM_CRC16 ) {\r
1036                                 admPtr->RamCrc.crc16 = crc16;\r
1037                         } else  {\r
1038                                 admPtr->RamCrc.crc32 = crc32;\r
1039                         }\r
1040                         admPtr->BlockSubState = BLOCK_SUBSTATE_0;\r
1041                         admPtr->ErrorStatus = NVM_REQ_OK;\r
1042                         admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1043                         blockDone = 1;\r
1044                         break;\r
1045                 default:\r
1046                         break;\r
1047                 }\r
1048 \r
1049                 break;\r
1050         }\r
1051         default:\r
1052                 NVM_ASSERT(0);\r
1053                 break;\r
1054         }\r
1055 \r
1056         if( blockDone  ) {\r
1057 \r
1058                 DEBUG_PRINTF("# Block Done\n");\r
1059 \r
1060                 if( admPtr->ErrorStatus == NVM_REQ_OK ) {\r
1061                         admPtr->BlockChanged = FALSE;\r
1062                         admPtr->BlockValid = TRUE;\r
1063                 }\r
1064 \r
1065 \r
1066                 /*  @req 3.1.5/NVM281 */\r
1067                 if( bPtr->SingleBlockCallback != NULL ) {\r
1068                         bPtr->SingleBlockCallback(NVM_READ_ALL_ID, admPtr->ErrorStatus);\r
1069                 }\r
1070 \r
1071                 if( multiBlock ) {\r
1072                         AdminMultiReq.currBlockIndex++;\r
1073                         if( AdminMultiReq.currBlockIndex >= NVM_NUM_OF_NVRAM_BLOCKS ) {\r
1074                                 AdminMultiReq.currBlockIndex = 0;\r
1075 \r
1076                                 /* @req 3.1.5/NVM301 */\r
1077                                 if( NVM_REQ_NOT_OK == AdminMultiReq.PendingErrorStatus ) {\r
1078                                         AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;\r
1079                                 } else {\r
1080                                         AdminMultiBlock.ErrorStatus = NVM_REQ_OK;\r
1081                                 }\r
1082                                 nvmState = NVM_IDLE;\r
1083                                 nvmSubState = 0;\r
1084                         }\r
1085                 } else {\r
1086                         nvmState = NVM_IDLE;\r
1087                         nvmSubState = 0;\r
1088 \r
1089                 }\r
1090         }\r
1091 }\r
1092 \r
1093 /*\r
1094  * Main function for the read all job
1095  */\r
1096 static void ReadAllMain(void)\r
1097 {\r
1098 \r
1099         /* Cases:\r
1100          * 1. We process each block until it's finished\r
1101          * 2. We start to process a lot of blocks. The blocks may use different devices\r
1102          *    and should be able to read a lot of them. This includes CRC.\r
1103          *\r
1104          *    1) is much simpler and 2) probably much faster.\r
1105          *    This implementation will use 1) since it's simpler and maximum time that is\r
1106          *    spent in MainFunction() can be controlled much better.\r
1107          */\r
1108 \r
1109         /* Skip blocks that are skipped */\r
1110 \r
1111         while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {\r
1112                 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {\r
1113                         AdminMultiReq.currBlockIndex++;\r
1114                 } else {\r
1115                         return;\r
1116                 }\r
1117         }\r
1118 \r
1119         DriveBlock(     &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],\r
1120                                         &AdminBlock[AdminMultiReq.currBlockIndex],\r
1121                                         NULL,\r
1122                                         false,\r
1123                                         true, false);\r
1124 }\r
1125 \r
1126 \r
1127 /*\r
1128  * Request writing of a block to MemIf
1129  */\r
1130 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,\r
1131                                                 AdministrativeBlockType *adminBlock,\r
1132                                                 uint8 setNumber,\r
1133                                                 uint8 *sourceAddress)\r
1134 {\r
1135         Std_ReturnType returnCode;\r
1136 \r
1137         if (setNumber < blockDescriptor->NvBlockNum) {\r
1138                 SetMemifJobBusy();\r
1139                 MemIfJobAdmin.BlockAdmin = adminBlock;\r
1140                 MemIfJobAdmin.BlockDescriptor = blockDescriptor;\r
1141                 returnCode = MemIf_Write(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), sourceAddress);\r
1142                 if (returnCode != E_OK) {\r
1143                         AbortMemIfJob(MEMIF_JOB_FAILED);\r
1144                 }\r
1145         } else {\r
1146                 // Error: setNumber out of range\r
1147                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_WRITE_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);\r
1148         }\r
1149 }\r
1150 \r
1151 \r
1152 \r
1153 /*\r
1154  * Initiate the write all job\r
1155  */\r
1156 static boolean WriteAllInit(void)\r
1157 {\r
1158         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
1159         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
1160         uint16 i;\r
1161         boolean needsProcessing = FALSE;\r
1162 \r
1163 //      nvmState = NVM_WRITE_ALL_PROCESSING;\r
1164         AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;\r
1165         AdminMultiReq.currBlockIndex = 0;\r
1166 \r
1167         for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
1168                 if ((BlockDescriptorList->RamBlockDataAddress != NULL)\r
1169 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)                                            /** @req NVM344 */\r
1170                                 && (AdminBlockTable->BlockValid)                                        /** @req NVM682 */\r
1171                                 && (AdminBlockTable->BlockChanged)                                      /** @req NVM682 */\r
1172 #endif\r
1173                                 && (!AdminBlockTable->BlockWriteProtected))                     /** @req NVM432 *//** @req NVM433 */\r
1174                 {\r
1175                         AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;\r
1176 \r
1177                         if (BlockDescriptorList->BlockUseCrc) {\r
1178                                 AdminBlockTable->BlockState = BLOCK_STATE_CALC_CRC_WRITE;       /** @req NVM253 */\r
1179                         } else {\r
1180                                 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1181                                 AdminBlockTable->NumberOfWriteFailed = 0;\r
1182                         }\r
1183                         needsProcessing = TRUE;\r
1184                 } else {\r
1185                         AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED;   /** @req NVM298 */\r
1186                 }\r
1187 \r
1188                 AdminBlockTable++;\r
1189                 BlockDescriptorList++;\r
1190         }\r
1191         return needsProcessing;\r
1192 }\r
1193 \r
1194 \r
1195 \r
1196 /*\r
1197  * Main function for the write all job\r
1198  */\r
1199 static void WriteAllMain(void)\r
1200 {\r
1201 \r
1202         while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {\r
1203                 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {\r
1204                         AdminMultiReq.currBlockIndex++;\r
1205                 } else {\r
1206                         return;\r
1207                 }\r
1208         }\r
1209 \r
1210         DriveBlock(     &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],\r
1211                                         &AdminBlock[AdminMultiReq.currBlockIndex],\r
1212                                         NULL,\r
1213                                         true,\r
1214                                         true, false );\r
1215 \r
1216 }\r
1217 \r
1218 \r
1219 #if 0\r
1220 /*\r
1221  * Handles the result of one MemIf block write\r
1222  */\r
1223 static void WriteAllCheckWriteResult(void)\r
1224 {\r
1225         if (MemIfJobAdmin.JobStatus == E_OK) {\r
1226                 // TODO: Check if redundant block shall be written NVM337\r
1227 \r
1228                 if (MemIfJobAdmin.BlockDescriptor->WriteBlockOnce) {\r
1229                         MemIfJobAdmin.BlockAdmin->BlockWriteProtected = TRUE;   /** @req NVM329 */\r
1230                 }\r
1231                 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1232                 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_OK;\r
1233 \r
1234                 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
1235                         (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);\r
1236                 }\r
1237         } else {\r
1238                 MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed++;\r
1239                 if (MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES) {\r
1240                         // TODO: Check if redundant block shall be written NVM337\r
1241 \r
1242                         // Write has failed\r
1243                         AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;\r
1244 \r
1245                         MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1246                         MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK; /** @req NVM296 */\r
1247 #if defined(USE_DEM)\r
1248                         Dem_ReportErrorStatus(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);\r
1249 #endif\r
1250 \r
1251                         if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {\r
1252                                 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);\r
1253                         }\r
1254                 }\r
1255         }\r
1256         nvmState = NVM_WRITE_ALL_PROCESSING;\r
1257 }\r
1258 #endif\r
1259 \r
1260 \r
1261 \r
1262 /***************************************\r
1263  *    External accessible functions    *\r
1264  ***************************************/\r
1265 /*\r
1266  * Procedure:   NvM_Init\r
1267  * Reentrant:   No\r
1268  */\r
1269 void NvM_Init(void)\r
1270 {\r
1271         /** @req NVM399 *//** @req NVM193 */\r
1272         const NvM_BlockDescriptorType   *BlockDescriptorList = NvM_Config.BlockDescriptor;\r
1273         AdministrativeBlockType *AdminBlockTable = AdminBlock;\r
1274         uint16 i;\r
1275 \r
1276 \r
1277         CirqBuff_Init(&nvmQueue,nvmQueueData,sizeof(nvmQueueData)/sizeof(Nvm_QueueType),sizeof(Nvm_QueueType));\r
1278 \r
1279         // Initiate the administration blocks\r
1280         for (i = 0; i< NVM_NUM_OF_NVRAM_BLOCKS; i++) {\r
1281                 if (BlockDescriptorList->BlockManagementType == NVM_BLOCK_DATASET) {\r
1282                         AdminBlockTable->DataIndex = 0; /** @req NVM192 */\r
1283                 }\r
1284                 AdminBlockTable->BlockWriteProtected = BlockDescriptorList->BlockWriteProt;\r
1285                 AdminBlockTable->ErrorStatus = NVM_REQ_NOT_OK;\r
1286                 AdminBlockTable->BlockChanged = FALSE;\r
1287                 AdminBlockTable->BlockValid = FALSE;\r
1288                 AdminBlockTable->NumberOfWriteFailed = 0;\r
1289 \r
1290                 AdminBlockTable++;\r
1291                 BlockDescriptorList++;\r
1292         }\r
1293 \r
1294         AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;\r
1295 \r
1296         // Set status to initialized\r
1297         nvmState = NVM_IDLE;    /** @req 3.1.5/NVM399 */\r
1298 }\r
1299 \r
1300 \r
1301 /**\r
1302  *\r
1303  * Note!\r
1304  *   NvM_ReadAll() does not set status here or need to check status of the\r
1305  *   any blocks since it's done after all single reads are done.\r
1306  */\r
1307 void NvM_ReadAll(void)\r
1308 {\r
1309     imask_t state;\r
1310         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);\r
1311 \r
1312         NVM_ASSERT(nvmState == NVM_IDLE);\r
1313 \r
1314         Irq_Save(state);\r
1315         AdminMultiReq.state = NVM_READ_ALL;\r
1316         AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;\r
1317         Irq_Restore(state);\r
1318 }\r
1319 \r
1320 \r
1321 \r
1322 /*\r
1323  * Procedure:   NvM_WriteAll\r
1324  * Reentrant:   No\r
1325  */\r
1326 void NvM_WriteAll(void)\r
1327 {\r
1328     imask_t state;\r
1329         VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);\r
1330 \r
1331         NVM_ASSERT(nvmState == NVM_IDLE);\r
1332 \r
1333         Irq_Save(state);\r
1334         AdminMultiReq.state = NVM_WRITE_ALL;\r
1335         AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;\r
1336         Irq_Restore(state);\r
1337 }\r
1338 \r
1339 \r
1340 /*\r
1341  * Procedure:   NvM_CancelWriteAll\r
1342  * Reentrant:   No\r
1343  */\r
1344 void NvM_CancelWriteAll(void)\r
1345 {\r
1346         \r
1347 }\r
1348 \r
1349 \r
1350 /*\r
1351  * Procedure:   NvM_GetErrorStatus\r
1352  * Reentrant:   Yes\r
1353  */\r
1354 Std_ReturnType NvM_GetErrorStatus(NvM_BlockIdType blockId, uint8 *requestResultPtr)\r
1355 {\r
1356         VALIDATE_RV(nvmState != NVM_UNINITIALIZED, NVM_GET_ERROR_STATUS_ID, NVM_E_NOT_INITIALIZED, E_NOT_OK );\r
1357         VALIDATE_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_GET_ERROR_STATUS_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK );\r
1358 \r
1359         if (blockId == 0) {\r
1360                 // Multiblock ID\r
1361                 *requestResultPtr = AdminMultiBlock.ErrorStatus;\r
1362         } else if (blockId == 1) {\r
1363                 /* TODO Configuration ID */\r
1364           *requestResultPtr = NVM_REQ_OK;\r
1365         } else {\r
1366                 *requestResultPtr = AdminBlock[blockId-1].ErrorStatus;\r
1367         }\r
1368         return E_OK;\r
1369 }\r
1370 \r
1371 \r
1372 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON)    /** @req NVM408 */\r
1373 /*\r
1374  * Procedure:   Nvm_SetRamBlockStatus\r
1375  * Reentrant:   Yes\r
1376  */\r
1377 Std_ReturnType NvM_SetRamBlockStatus(NvM_BlockIdType blockId, boolean blockChanged)\r
1378 {\r
1379         const NvM_BlockDescriptorType * bPtr;\r
1380         AdministrativeBlockType *               admPtr;\r
1381         Nvm_QueueType qEntry;\r
1382         int rv;\r
1383 \r
1384         VALIDATE_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK);\r
1385 \r
1386         bPtr = &NvM_Config.BlockDescriptor[blockId-1];\r
1387         admPtr = &AdminBlock[blockId-1];\r
1388 \r
1389         VALIDATE_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_NOT_INITIALIZED, E_NOT_OK);       /** @req NVM497 */\r
1390         VALIDATE_RV(blockId > 1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK );\r
1391         VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );\r
1392 \r
1393         qEntry.blockId = blockId;\r
1394         qEntry.op = NVM_SETRAMBLOCKSTATUS;\r
1395         qEntry.blockChanged = blockChanged;\r
1396         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1397         NVM_ASSERT(rv == 0 );\r
1398 \r
1399         /* req 3.1.5/NVM185 */\r
1400         admPtr->ErrorStatus = NVM_REQ_PENDING;\r
1401 \r
1402         return E_OK;\r
1403 }\r
1404 #endif\r
1405 \r
1406 static void setRamBlockStatus( const NvM_BlockDescriptorType    *bPtr, AdministrativeBlockType *admPtr, boolean blockChanged ) {\r
1407 \r
1408         if (bPtr->RamBlockDataAddress != NULL) {        /** @req NVM240 */\r
1409                 if (blockChanged) {\r
1410                         admPtr->BlockChanged = TRUE;    /** @req NVM406 */\r
1411                         admPtr->BlockValid = TRUE;      /** @req NVM241 */\r
1412 //      TODO?   if (bPtr->BlockUseCrc) {\r
1413 //                              admPtr->BlockState = BLOCK_STATE_CALC_CRC;      /** @req NVM121 */\r
1414 //                      }\r
1415                 } else {\r
1416                         admPtr->BlockChanged = FALSE;   /** @req NVM405 */\r
1417                         admPtr->BlockValid = FALSE;\r
1418                 } // else blockChanged\r
1419         } // if permanent block\r
1420 }\r
1421 \r
1422 void NvM_SetBlockLockStatus( NvM_BlockIdType blockId, boolean blockLocked ) {\r
1423         (void)blockId;\r
1424         (void)blockLocked;\r
1425 }\r
1426 \r
1427 \r
1428 /**\r
1429  * Restore default data to its corresponding RAM block.\r
1430  *
1431  * @param BlockId               NVRAM block identifier.
1432  * @param NvM_DestPtr   Pointer to the RAM block
1433  * @return
1434  */\r
1435 Std_ReturnType NvM_RestoreBlockDefaults( NvM_BlockIdType blockId, uint8* NvM_DestPtr )\r
1436 {\r
1437         /* !req 3.1.5/NVM012 */ /* !req 3.1.5/NVM267 */ /* !req 3.1.5/NVM266 */\r
1438         /* !req 3.1.5/NVM353 */ /* !req 3.1.5/NVM435 */ /* !req 3.1.5/NVM436 */ /* !req 3.1.5/NVM227 */\r
1439         /* !req 3.1.5/NVM228 */ /* !req 3.1.5/NVM229 */ /* !req 3.1.5/NVM413 */\r
1440 \r
1441         const NvM_BlockDescriptorType * bPtr;\r
1442         AdministrativeBlockType *               admPtr;\r
1443         Nvm_QueueType qEntry;\r
1444         int rv;\r
1445 \r
1446         NVM_ASSERT( blockId >= 2 );     /* No support for lower numbers, yet */\r
1447 \r
1448         /* @req 3.1.5/NVM618 */\r
1449         VALIDATE_RV(    blockId <= NVM_NUM_OF_NVRAM_BLOCKS,\r
1450                                         NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );\r
1451 \r
1452         bPtr = &NvM_Config.BlockDescriptor[blockId-1];\r
1453         admPtr = &AdminBlock[blockId-1];\r
1454 \r
1455         /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */ /** @req 3.1.5/NVM210 */\r
1456         /* It must be a permanent RAM block but no RamBlockDataAddress -> error */\r
1457         VALIDATE_RV( !((NvM_DestPtr == NULL) &&  ( bPtr->RamBlockDataAddress == NULL )),\r
1458                                                 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );\r
1459 \r
1460         VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );\r
1461 \r
1462         /* @req 3.1.5/NVM195 */\r
1463         qEntry.blockId = blockId;\r
1464         qEntry.op = NVM_RESTORE_BLOCK_DEFAULTS;\r
1465         qEntry.blockId = blockId;\r
1466         qEntry.dataPtr = (uint8_t *)NvM_DestPtr;\r
1467         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1468         NVM_ASSERT(rv == 0 );\r
1469 \r
1470         /* req 3.1.5/NVM185 */\r
1471         admPtr->ErrorStatus = NVM_REQ_PENDING;\r
1472 \r
1473         if( bPtr->BlockUseCrc) {\r
1474                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;\r
1475         } else {\r
1476                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1477         }\r
1478 \r
1479 \r
1480         return E_OK;\r
1481 }\r
1482 \r
1483 /**\r
1484  * Service to copy the data NV block to the RAM block\r
1485  *
1486  * @param blockId               0 and 1 reserved. The block ID are sequential.
1487  * @param NvM_DstPtr
1488  * @return
1489  */\r
1490 \r
1491 \r
1492 Std_ReturnType NvM_ReadBlock( NvM_BlockIdType blockId, uint8* NvM_DstPtr )\r
1493 {\r
1494         /* !req 3.1.5/NVM010 */\r
1495 \r
1496 \r
1497         /* !req 3.1.5/NVM278 */\r
1498         /* !req 3.1.5/NVM340 */\r
1499         /* !req 3.1.5/NVM354 */\r
1500         /* !req 3.1.5/NVM200 */\r
1501         /* !req 3.1.5/NVM366 */\r
1502         /* !req 3.1.5/NVM206 */\r
1503         /* !req 3.1.5/NVM341 */\r
1504         /* !req 3.1.5/NVM358 */\r
1505         /* !req 3.1.5/NVM359 */\r
1506         /* !req 3.1.5/NVM279 */\r
1507         /* !req 3.1.5/NVM316 */\r
1508         /* !req 3.1.5/NVM317 */\r
1509         /* !req 3.1.5/NVM201 */\r
1510         /* !req 3.1.5/NVM202 */\r
1511         /* !req 3.1.5/NVM203 */\r
1512         /* !req 3.1.5/NVM204 */\r
1513         /* !req 3.1.5/NVM409 */\r
1514 \r
1515 \r
1516    /* logical block:\r
1517     *\r
1518     *    1 1 1 1 1 1\r
1519     *   |5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|\r
1520     *    b b b b b b b b b b d d d d d d\r
1521     *\r
1522     * Here we have 10 bits for block id, 16-5 for DataSetSelection bits.\r
1523     * - 2^10, 1024 blocks\r
1524     * - 64 datasets for each NVRAM block\r
1525     *\r
1526     * How are the block numbers done in EA? Assume virtual page=8\r
1527     * logical\r
1528     *  Block   size\r
1529     *  1       32\r
1530     *   2\r
1531     *   3\r
1532     *   4\r
1533     *  5       12\r
1534     *   6\r
1535     *  7\r
1536     *\r
1537     *  How can NVM/NvmNvBlockLength and EA/EaBlockSize be different?\r
1538     *  It seems that EA/FEE does not care about that logical block 2 above is\r
1539     *  "blocked"\r
1540     *
1541     */\r
1542         Nvm_QueueType qEntry;\r
1543         int rv;\r
1544 \r
1545         /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */\r
1546     VALIDATE_RV( !(( NvM_DstPtr == NULL) &&\r
1547                         ( NvM_Config.BlockDescriptor[blockId-1].RamBlockDataAddress == NULL )),\r
1548                         0, NVM_E_PARAM_ADDRESS  , E_NOT_OK );\r
1549         VALIDATE_RV( (AdminBlock[blockId-1].ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );\r
1550 \r
1551         /* @req 3.1.5/NVM195 */\r
1552         qEntry.blockId = blockId;\r
1553         qEntry.op = NVM_READ_BLOCK;\r
1554         qEntry.blockId = blockId;\r
1555         qEntry.dataPtr = NvM_DstPtr;\r
1556         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1557         NVM_ASSERT(rv == 0 );\r
1558 \r
1559 \r
1560         /* req 3.1.5/NVM185 */\r
1561         AdminBlock[blockId-1].ErrorStatus = NVM_REQ_PENDING;\r
1562 \r
1563         return E_OK;\r
1564 }\r
1565 \r
1566 \r
1567 /**\r
1568  * Service to copy a RAM block to its correspnding NVRAM block\r
1569  *
1570  * @param blockId
1571  * @param NvM_SrcPtr
1572  * @return
1573  */\r
1574 Std_ReturnType NvM_WriteBlock( NvM_BlockIdType blockId, const uint8* NvM_SrcPtr ) {\r
1575 \r
1576         const NvM_BlockDescriptorType * bPtr;\r
1577         AdministrativeBlockType *               admPtr;\r
1578         Nvm_QueueType qEntry;\r
1579         int rv;\r
1580 \r
1581         NVM_ASSERT( blockId >= 2 );     /* No support for lower numbers, yet */\r
1582 \r
1583         /* @req 3.1.5/NVM618 */\r
1584         VALIDATE_RV(    blockId <= NVM_NUM_OF_NVRAM_BLOCKS,\r
1585                                         NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );\r
1586 \r
1587         bPtr = &NvM_Config.BlockDescriptor[blockId-1];\r
1588         admPtr = &AdminBlock[blockId-1];\r
1589 \r
1590         /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */\r
1591         VALIDATE_RV( !((NvM_SrcPtr == NULL) && ( bPtr->RamBlockDataAddress == NULL )),\r
1592                                 0, NVM_E_PARAM_ADDRESS, E_NOT_OK );\r
1593         VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );\r
1594 \r
1595         /* @req 3.1.5/NVM195 */\r
1596         qEntry.blockId = blockId;\r
1597         qEntry.op = NVM_WRITE_BLOCK;\r
1598         qEntry.blockId = blockId;\r
1599         qEntry.dataPtr = (uint8_t *)NvM_SrcPtr;\r
1600         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1601         NVM_ASSERT(rv == 0 );\r
1602 \r
1603         /* req 3.1.5/NVM185 */\r
1604         admPtr->ErrorStatus = NVM_REQ_PENDING;\r
1605 \r
1606         if( bPtr->BlockUseCrc) {\r
1607                 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;\r
1608         } else {\r
1609                 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;\r
1610         }\r
1611 \r
1612 \r
1613         return E_OK;\r
1614 }\r
1615 \r
1616 /* Missing from Class 2\r
1617  * - NvM_CancelWriteAll\r
1618  * */\r
1619 \r
1620 //#if (NVM_API_CONFIG_CLASS > NVM_API_CONFIG_CLASS_1)\r
1621 \r
1622 /*\r
1623  * Note!\r
1624  * This function returns void in 3.1.5 and in 4.0 it returns Std_ReturnType.\r
1625  *\r
1626  *\r
1627  * return\r
1628  *   x NVM_E_NOT_INITIALIZED\r
1629  *   x NVM_E_BLOCK_PENDING\r
1630  *   NVM_E_PARAM_BLOCK_DATA_IDX\r
1631  *   NVM_E_PARAM_BLOCK_TYPE\r
1632  *   x NVM_E_PARAM_BLOCK_ID\r
1633  *\r
1634  */\r
1635 Std_ReturnType NvM_SetDataIndex( NvM_BlockIdType blockId, uint8 dataIndex ) {\r
1636 #if  ( NVM_DEV_ERROR_DETECT == STD_ON )\r
1637         const NvM_BlockDescriptorType * bPtr = &NvM_Config.BlockDescriptor[blockId-1];\r
1638         AdministrativeBlockType *               admPtr = &AdminBlock[blockId-1];\r
1639 #endif\r
1640         Nvm_QueueType qEntry;\r
1641         int rv;\r
1642 \r
1643         NVM_ASSERT( blockId >= 2 );     /* No support for lower numbers, yet */\r
1644 \r
1645         VALIDATE_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_DATA_INDEX_ID, NVM_E_NOT_INITIALIZED, E_NOT_OK);\r
1646         VALIDATE_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK);\r
1647         VALIDATE_RV(bPtr->BlockManagementType != NVM_BLOCK_NATIVE ,  NVM_SET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_TYPE , E_NOT_OK);\r
1648         VALIDATE_RV(dataIndex < bPtr->NvBlockNum + bPtr->RomBlockNum , NVM_SET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_DATA_IDX ,E_NOT_OK);\r
1649         VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), NVM_SET_DATA_INDEX_ID, NVM_E_BLOCK_PENDING , E_NOT_OK);\r
1650 \r
1651         qEntry.blockId = blockId;\r
1652         qEntry.op = NVM_SETDATAINDEX;\r
1653         qEntry.blockId = blockId;\r
1654         qEntry.dataIndex = dataIndex;\r
1655         rv = CirqBuffPush(&nvmQueue,&qEntry);\r
1656         NVM_ASSERT(rv == 0 );\r
1657 \r
1658         /* req 3.1.5/NVM185 */\r
1659         admPtr->ErrorStatus = NVM_REQ_PENDING;\r
1660         return E_OK;\r
1661 }\r
1662 //#endif\r
1663 \r
1664 const NvM_BlockDescriptorType * nvmBlock;\r
1665 AdministrativeBlockType *admBlock;\r
1666 \r
1667 /**\r
1668  *
1669  */\r
1670 void NvM_MainFunction(void)\r
1671 {\r
1672         int                     rv;\r
1673         Nvm_QueueType   qEntry;\r
1674         const NvM_BlockDescriptorType * bList = NvM_Config.BlockDescriptor;\r
1675 //      const NvM_BlockDescriptorType * currBlock;\r
1676 //      static uint32 crc32;\r
1677 //      static uint32 crc32Left;\r
1678 \r
1679         /* Check for new requested state changes */\r
1680         if( nvmState == NVM_IDLE ) {\r
1681                 rv = CirqBuffPop( &nvmQueue, &qEntry );\r
1682                 if( rv == 0 ) {\r
1683                         /* Found something in buffer */\r
1684                         nvmState = qEntry.op;\r
1685                         nvmBlock = &bList[qEntry.blockId-1];\r
1686                         admBlock = &AdminBlock[qEntry.blockId-1];\r
1687                         nvmSubState = 0;\r
1688                         admBlock->ErrorStatus = NVM_REQ_PENDING;\r
1689                         DEBUG_PRINTF("### Popped Single FIFO : %s\n",StateToStr[qEntry.op]);\r
1690                         DEBUG_PRINTF("### CRC On:%d Ram:%d Type:%d\n",nvmBlock->BlockUseCrc, nvmBlock->CalcRamBlockCrc, nvmBlock->BlockCRCType );\r
1691                         DEBUG_PRINTF("### RAM:%x ROM:%x\n", nvmBlock->RamBlockDataAddress, nvmBlock->RomBlockDataAdress );\r
1692                 } else {\r
1693                         /* Check multiblock req and do after all single block reads (3.1.5/NVM243) */\r
1694                         if( AdminMultiReq.state != NVM_UNINITIALIZED ) {\r
1695                                 nvmState = AdminMultiReq.state ;\r
1696                                 nvmSubState = 0;\r
1697                                 nvmBlock = 0;\r
1698                                 admBlock = 0;\r
1699                                 AdminMultiReq.state = NVM_UNINITIALIZED;\r
1700 \r
1701                                 DEBUG_PRINTF("### Popped MULTI\n");\r
1702                         }\r
1703                 }\r
1704         }\r
1705 \r
1706         DEBUG_STATE(nvmState,nvmSubState);\r
1707 \r
1708         switch (nvmState) {\r
1709         case NVM_UNINITIALIZED:\r
1710                 break;\r
1711 \r
1712         case NVM_IDLE:\r
1713         {\r
1714                 CalcCrc();\r
1715                 break;\r
1716         }\r
1717         case NVM_READ_ALL:\r
1718                 if( NS_INIT == nvmSubState ) {\r
1719                         if( ReadAllInit() ) {\r
1720                                 nvmSubState = NS_PROSSING;\r
1721                         } else {\r
1722                                 /* Nothing to do, everything is OK */\r
1723                                 AdminMultiBlock.ErrorStatus = NVM_REQ_OK;\r
1724                                 nvmState = NVM_IDLE;\r
1725                                 nvmSubState = 0;\r
1726                         }\r
1727                 } else if( NS_PROSSING == nvmSubState ) {\r
1728                         ReadAllMain();\r
1729                 }\r
1730                 break;\r
1731 \r
1732         case NVM_READ_BLOCK:\r
1733                 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, false );\r
1734                 break;\r
1735 \r
1736         case NVM_RESTORE_BLOCK_DEFAULTS:\r
1737                 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, true );\r
1738                 break;\r
1739 \r
1740         case NVM_WRITE_BLOCK:\r
1741                 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, true /*write*/, false , false );\r
1742                 break;\r
1743 \r
1744         case NVM_WRITE_ALL:\r
1745                 if( NS_INIT == nvmSubState ) {\r
1746                         if( WriteAllInit() ) {\r
1747                                 nvmSubState = NS_PROSSING;\r
1748                         } else {\r
1749                                 /* Nothing to do, everything is OK */\r
1750                                 AdminMultiBlock.ErrorStatus = NVM_REQ_OK;\r
1751                                 nvmState = NVM_IDLE;\r
1752                                 nvmSubState = 0;\r
1753                         }\r
1754                 } else if( NS_PROSSING == nvmSubState ) {\r
1755                         WriteAllMain();\r
1756                 }\r
1757                 break;\r
1758         case NVM_SETDATAINDEX:\r
1759                 admBlock->DataIndex = qEntry.dataIndex;\r
1760                 nvmState = NVM_IDLE;\r
1761                 nvmSubState = 0;\r
1762                 admBlock->ErrorStatus = NVM_REQ_OK;\r
1763                 break;\r
1764         case NVM_GETDATAINDEX:\r
1765                 NVM_ASSERT(0);\r
1766                 nvmState = NVM_IDLE;\r
1767                 nvmSubState = 0;\r
1768                 admBlock->ErrorStatus = NVM_REQ_OK;\r
1769                 break;\r
1770         case NVM_SETRAMBLOCKSTATUS:\r
1771                 setRamBlockStatus(nvmBlock,admBlock,qEntry.blockChanged );\r
1772                 nvmState = NVM_IDLE;\r
1773                 nvmSubState = 0;\r
1774                 admBlock->ErrorStatus = NVM_REQ_OK;\r
1775                 break;\r
1776         default:\r
1777                 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_MAIN_FUNCTION_ID, NVM_UNEXPECTED_STATE);\r
1778                 break;\r
1779         }\r
1780 }\r
1781 \r
1782 \r
1783 /***************************************\r
1784  *  Call-back notifications functions  *\r
1785  ***************************************/\r
1786 #if (NVM_POLLING_MODE == STD_OFF)\r
1787 /*\r
1788  * Procedure:   NvM_JobEndNotification\r
1789  * Reentrant:   No\r
1790  */\r
1791 void NvM_JobEndNotification(void)\r
1792 {\r
1793         MemIfJobAdmin.JobFinished = TRUE;\r
1794         MemIfJobAdmin.JobStatus = E_OK;\r
1795         MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);\r
1796 }\r
1797 \r
1798 /*\r
1799  * Procedure:   NvM_JobErrorNotification\r
1800  * Reentrant:   No\r
1801  */\r
1802 void NvM_JobErrorNotification(void)\r
1803 {\r
1804         MemIfJobAdmin.JobFinished = TRUE;\r
1805         MemIfJobAdmin.JobStatus = E_NOT_OK;\r
1806         MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);\r
1807 }\r
1808 #endif\r
1809 \r