1 /* -------------------------------- Arctic Core ------------------------------
\r
2 * Arctic Core - the open source AUTOSAR platform http://arccore.com
\r
4 * Copyright (C) 2009 ArcCore AB <contact@arccore.com>
\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
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
14 * -------------------------------- Arctic Core ------------------------------*/
\r
18 * Author: Peter+mahi
\r
24 * Implements the NVRAM Manager module.
\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
44 * NvmBlockDescriptor Have Support
\r
45 * -------------------------------------------
\r
47 * NvmBlockJobPriority N
\r
48 * NvmBlockManagementType Y, All blocks supported
\r
50 * NvmBlockWriteProt N
\r
51 * NvmCalcRamBlockCrc Y
\r
52 * NvmInitBlockCallback Y
\r
53 * NvmNvBlockBaseNumber Y
\r
54 * NvmNvBlockLength Y
\r
56 * NvmNvramBlockIdentifier Y
\r
57 * NvmNvramDeviceId N (always device Id 0)
\r
58 * NvmResistantToChangedSw N
\r
59 * NvmRomBlockDataAddress Y
\r
61 * NvmSelectBlockForReadall Y
\r
62 * NvmSingleBlockCallback Y
\r
63 * NvmWriteBlockOnce N
\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
78 * RamBlockDataAddress
\r
79 * NULL is no permanent RAM block. Otherwise allocate the number of bytes in space (like the stack)
\r
82 * Understanding block numbering:
\r
84 * NVM_DATASET_SELECTION_BIT=2
\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
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
97 * NvM_BlockIdType*) NvBlockBaseNumber EA_BLOCK_NUMBER
\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
107 * *) Type used in the API.
\r
108 * **) Reserved ID's ( 0 - multiblock, 1 - redundant NVRAM block which hold configuration 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
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
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
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
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
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
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
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
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
155 * To get some speed into this multiple thing must be done in the same MainFunction loop.
\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
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
175 * Provide Data for the first/initial read
\r
176 * When a block have no
\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
188 * 0 0 No error detection or recovery
\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
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
205 * VALID/UNCHANGED - RAM == NV
\r
206 * VALID/CHANGED - RAM != NV (analog to cache memories, "dirty")
\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
216 * General requirements
\r
224 * NB! Even though some code exist for handling RamCrc, the functionality is not complete
\r
225 * and shall not be used.
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
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
235 /* ----------------------------[includes]------------------------------------*/
\r
237 #include <assert.h>
\r
239 #include "NvM_Cbk.h"
\r
240 #if defined(CFG_NVM_USE_SERVICE_PORTS)
\r
241 #include "Rte.h" // ???
\r
243 #if defined(USE_DEM)
\r
247 //#include "SchM_NvM.h"
\r
248 #include "MemMap.h"
\r
249 #include "cirq_buffer.h"
\r
250 #include "Modules.h"
\r
254 #include <string.h>
\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
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
273 /* ----------------------------[private define]------------------------------*/
\r
277 #define NVM_BLOCK_ALIGNMENT 4
\r
278 #define NVM_CHECKSUM_LENGTH 4
\r
280 #define NVM_BLOCK_OFFSET 2
\r
286 /* ----------------------------[private macro]-------------------------------*/
\r
288 #if defined(DEBUG_BLOCK)
\r
289 #define NVM_ASSERT(_exp) if( !(_exp) ) { assert(_exp); } //
\r
291 #define NVM_ASSERT(_exp) if( !(_exp) ) { while(1) {}; } //assert(_exp)
\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
298 #define DET_REPORT_ERROR( _api, _err)
\r
301 #if ( NVM_DEV_ERROR_DETECT == STD_ON )
\r
303 #define VALIDATE(_exp,_api,_err ) \
\r
305 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
309 #define VALIDATE_RV(_exp,_api,_err,_rv ) \
\r
311 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
315 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
317 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
320 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)
\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
329 #define BLOCK_BASE_AND_SET_TO_BLOCKNR(_blockbase, _set) ((uint16)(_blockbase) | _set)
\r
331 #if defined(USE_DEM)
\r
332 #define DEM_REPORTERRORSTATUS(_err,_ev ) Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED);
\r
334 #define DEM_REPORTERRORSTATUS(_err,_ev )
\r
338 #define BLOCK_NR_FROM_PTR(_bptr) (((_bptr) - NvM_Config.BlockDescriptor + 1)) // sizeof(NvM_BlockDescriptorType))
\r
340 #define CREATE_ENTRY(_val) [_val] = #_val
\r
345 /* ----------------------------[private typedef]-----------------------------*/
\r
349 NVM_UNINITIALIZED = 0,
\r
355 NVM_RESTORE_BLOCK_DEFAULTS,
\r
358 NVM_SETRAMBLOCKSTATUS,
\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
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
391 } BlockSubStateType;
\r
408 NvM_RequestResultType ErrorStatus; // Status from multi block requests i.e. Read/Write/CancelWrite-all
\r
409 } AdministrativeMultiBlockType;
\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
424 uint8 flags; // Used for all sorts of things.
\r
425 } AdministrativeBlockType;
\r
430 NVM_OP_WRITE_BLOCK,
\r
431 NVM_OP_RESTORE_BLOCK_DEFAULTS,
\r
436 #define NO_MULTIBLOCK 0
\r
437 #define MULTIBLOCK 1
\r
442 NvM_BlockIdType blockId;
\r
443 uint8 * dataPtr; /* Src or Dest ptr */
\r
445 boolean blockChanged;
\r
451 /* ----------------------------[private function prototypes]-----------------*/
\r
452 /* ----------------------------[private variables]---------------------------*/
\r
454 static NvmStateType nvmState = NVM_UNINITIALIZED;
\r
457 #define RB_WAIT_READ 1
\r
458 #define RB_CALC_CHECKSUM 2
\r
460 static int nvmSubState = 0;
\r
461 static uint8 serviceId = NVM_INIT_ID;
\r
462 //static int nvmSetNr;
\r
463 static AdministrativeBlockType AdminBlock[NVM_NUM_OF_NVRAM_BLOCKS];
\r
464 static AdministrativeMultiBlockType AdminMultiBlock;
\r
467 //static Nvm_QueueType nvmQueueImmData[NVM_SIZE_IMMEDIATE_JOB_QUEUE];
\r
468 static Nvm_QueueType nvmQueueData[NVM_SIZE_STANDARD_JOB_QUEUE];
\r
470 uint8 Nvm_WorkBuffer[NVM_MAX_BLOCK_LENGTH+4]; /* +4 to make place for max crc length */
\r
472 #if (NVM_SIZE_STANDARD_JOB_QUEUE == 0)
\r
473 #error NVM_SIZE_STANDARD_JOB_QUEUE have size 0
\r
477 CirqBufferType nvmQueue;
\r
480 /* ----------------------------[private functions]---------------------------*/
\r
482 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,
\r
483 AdministrativeBlockType *adminBlock,
\r
485 uint8 *sourceAddress);
\r
487 static void setRamBlockStatus( const NvM_BlockDescriptorType *bPtr,
\r
488 AdministrativeBlockType *admPtr,
\r
489 boolean blockChanged );
\r
492 /* ----------------------------[public functions]----------------------------*/
\r
497 * This function needs to be implemented!
499 static void CalcCrc(void)
\r
501 // TODO: Calculate CRC
\r
505 boolean JobFinished;
\r
506 Std_ReturnType JobStatus;
\r
507 MemIf_JobResultType JobResult;
\r
508 const NvM_BlockDescriptorType * BlockDescriptor;
\r
509 AdministrativeBlockType * BlockAdmin;
\r
510 } MemIfJobAdminType;
\r
512 static MemIfJobAdminType MemIfJobAdmin = {
\r
513 .JobFinished = TRUE,
\r
515 .JobResult = MEMIF_JOB_OK,
\r
516 .BlockDescriptor = NULL,
\r
520 enum Nvm_MultiBlockReq {
\r
527 NvmStateType state;
\r
528 uint16 currBlockIndex; // Keeps track of next unfinished block
\r
529 NvM_RequestResultType PendingErrorStatus; // Status from multi block requests i.e. Read/Write/CancelWrite-all
\r
531 } AdminMultiReqType;
\r
533 static AdminMultiReqType AdminMultiReq;
\r
537 * Set the MemIf job as busy
539 static void SetMemifJobBusy()
\r
541 MemIfJobAdmin.JobFinished = FALSE;
\r
545 #if (NVM_POLLING_MODE == STD_ON)
\r
547 * Check if the MemIf job is finished
549 static boolean CheckMemIfJobFinished(void)
\r
551 MemIf_JobResultType jobResult;
\r
553 if (!MemIfJobAdmin.JobFinished) {
\r
554 jobResult = MemIf_GetJobResult(FIXME);
\r
556 if (jobResult == MEMIF_JOB_OK) {
\r
557 MemIfJobAdmin.JobFinished = TRUE;
\r
558 MemIfJobAdmin.JobStatus = E_OK;
\r
559 MemIfJobAdmin.JobResult = jobResult;
\r
560 } else if (jobResult != MEMIF_JOB_PENDING) {
\r
561 MemIfJobAdmin.JobFinished = TRUE;
\r
562 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
563 MemIfJobAdmin.JobResult = jobResult;
\r
567 return MemIfJobAdmin.JobFinished;
\r
571 * Check if the MemIf job is finished
\r
574 static boolean CheckMemIfJobFinished(void)
\r
576 return MemIfJobAdmin.JobFinished;
\r
583 * Abort the MemIf job with E_NOT_OK
\r
585 static void AbortMemIfJob(MemIf_JobResultType jobResult)
\r
587 MemIfJobAdmin.JobFinished = TRUE;
\r
588 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
589 MemIfJobAdmin.JobResult = jobResult;
\r
593 static boolean CheckJobFailed( void ) {
\r
594 return CheckMemIfJobFinished() && (MemIfJobAdmin.JobResult == MEMIF_JOB_FAILED);
\r
599 * Initiate the read all job
601 static boolean ReadAllInit(void)
\r
604 * Initiate the read all job
606 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
607 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
609 boolean needsProcessing = FALSE;
\r
611 // Set status to pending in the administration blocks
\r
612 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING; /** @req 3.1.5/NVM304 */
\r
613 AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;
\r
614 AdminMultiReq.currBlockIndex = 0;
\r
616 for (i = 0; i < ( NVM_NUM_OF_NVRAM_BLOCKS ); i++) {
\r
617 if ((BlockDescriptorList->SelectBlockForReadall)
\r
618 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM345 */
\r
619 && ((!AdminBlockTable->BlockValid) // TODO: Check if this is to be done like this
\r
620 || (!AdminBlockTable->BlockChanged)) // TODO: Check if this is to be done like this
\r
623 NVM_ASSERT(BlockDescriptorList->RamBlockDataAddress != NULL);
\r
624 VALIDATE_RV(BlockDescriptorList->RamBlockDataAddress != NULL, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG, FALSE );
\r
626 NVM_ASSERT(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET);
\r
627 VALIDATE_RV(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG, FALSE );
\r
629 AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;
\r
630 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
631 needsProcessing = TRUE;
\r
633 AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED; /* @req 3.1.5/NVM287 */
\r
637 BlockDescriptorList++;
\r
640 return needsProcessing;
\r
644 static void writeCrcToBuffer( void *bufPtr,
\r
645 const NvM_BlockDescriptorType *bPtr,
\r
646 AdministrativeBlockType *admPtr )
\r
648 if( bPtr->BlockUseCrc ) {
\r
649 if(bPtr->BlockCRCType == NVM_CRC16) {
\r
650 WRITE16_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc16);
\r
652 WRITE32_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc32);
\r
657 #define REDUNDANT_BLOCK_OK 0
\r
658 #define REDUNDANT_BLOCK_BOTH_FAIL 1
\r
659 #define REDUNDANT_BLOCK_OK 0
\r
662 static boolean handleRedundantBlock(const NvM_BlockDescriptorType *bPtr,
\r
663 AdministrativeBlockType *admPtr ) {
\r
665 /* According to 3.1.5/NVM137 we have 2 NV Blocks and 0..1 ROM Blocks */
\r
666 /* Req 3.1.5/NVM199 , 3.1.5/NVM279 , 3.1.5/NVM317
\r
667 * 3.1.5/NVM288, 3.1.5/NVM315
\r
670 if ( bPtr->BlockManagementType == NVM_BLOCK_REDUNDANT ) {
\r
671 if( admPtr->flags == 1 ) {
\r
672 NVM_ASSERT(bPtr->NvBlockNum == 2); /* Configuration error */
\r
673 admPtr->DataIndex = ((admPtr->DataIndex) ? 0 : 1);
\r
674 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
675 DEBUG_PRINTF(" # First redundant NV block failed\n");
\r
678 DEBUG_PRINTF(" # Both redundant NV blocks failed\n");
\r
686 * Drive the read state-machine
\r
692 static void DriveBlock( const NvM_BlockDescriptorType *bPtr,
\r
693 AdministrativeBlockType *admPtr,
\r
696 boolean multiBlock,
\r
697 boolean restoreFromRom )
\r
699 bool blockDone = 0;
\r
701 DEBUG_BLOCK_STATE("DriveBlock", BLOCK_NR_FROM_PTR(bPtr), admPtr->BlockState );
\r
703 NVM_ASSERT( admPtr->ErrorStatus == NVM_REQ_PENDING);
\r
705 switch (admPtr->BlockState) {
\r
706 case BLOCK_STATE_MEMIF_REQ:
\r
708 void *ramData = (dataPtr != NULL) ? dataPtr : bPtr->RamBlockDataAddress;
\r
710 admPtr->savedDataPtr = ramData;
\r
713 if( multiBlock && (dataPtr!=NULL)) {
\r
716 /* Copy to work buffer */
\r
717 memcpy( Nvm_WorkBuffer, ramData, bPtr->NvBlockLength );
\r
718 /* Add the CRC to write */
\r
719 writeCrcToBuffer(Nvm_WorkBuffer, bPtr, admPtr );
\r
720 WriteBlock(bPtr, admPtr, admPtr->DataIndex, Nvm_WorkBuffer);
\r
723 /* Read to workbuffer */
\r
724 if( bPtr->BlockUseCrc ) {
\r
725 crcLen = (bPtr->BlockCRCType == NVM_CRC16) ? 2: 4;
\r
728 if( restoreFromRom ) {
\r
729 NVM_ASSERT( bPtr->RomBlockDataAdress != NULL );
\r
730 /* No CRC on the ROM block */
\r
731 memcpy(ramData,bPtr->RomBlockDataAdress,bPtr->NvBlockLength);
\r
733 admPtr->ErrorStatus = NVM_REQ_OK;
\r
735 break; /* Do NOT advance to next state */
\r
737 uint8 setNumber = admPtr->DataIndex;
\r
738 uint16 length = bPtr->NvBlockLength+crcLen;
\r
740 boolean fail = FALSE;
\r
746 if (setNumber < bPtr->NvBlockNum) {
\r
748 MemIfJobAdmin.BlockAdmin = admPtr;
\r
749 MemIfJobAdmin.BlockDescriptor = bPtr;
\r
752 /* First reading the MemIf block and then checking MemIf_GetStatus() to determine
\r
753 * if the device BUSY in anyway...is not threadsafe. The way Autosar have defined
\r
754 * it you would have to lock over the MemIf_Read() to be sure.
\r
758 /* We want to read from MemIf, but the device may be busy.
\r
760 rv = MemIf_Read(bPtr->NvramDeviceId,
\r
761 BLOCK_BASE_AND_SET_TO_BLOCKNR(bPtr->NvBlockBaseNumber, setNumber),
\r
766 if ( MemIf_GetStatus(FIXME) == MEMIF_IDLE ) {
\r
767 AbortMemIfJob(MEMIF_JOB_FAILED);
\r
770 /* Do nothing. For MEMIF_UNINIT, MEMIF_BUSY and MEMIF_BUSY_INTERNAL we just stay in the
\r
771 * same state. Better in the next run */
\r
772 Irq_Restore(state);
\r
773 break; /* Do NOT advance to next state */
\r
776 Irq_Restore(state);
\r
778 } else if (setNumber < bPtr->NvBlockNum + bPtr->RomBlockNum) {
\r
779 // TODO: Read from ROM
\r
781 // Error: setNumber out of range
\r
782 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_READ_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);
\r
788 admPtr->ErrorStatus = NVM_REQ_NOT_OK;
\r
790 break; /* Do NOT advance to next state */
\r
795 admPtr->BlockState = BLOCK_STATE_MEMIF_PROCESS;
\r
799 case BLOCK_STATE_MEMIF_PROCESS:
\r
802 MemIf_JobResultType jobResult = MemIf_GetJobResult(FIXME);
\r
804 if( MEMIF_JOB_PENDING == jobResult ) {
\r
805 /* Keep on waiting */
\r
806 } else if( MEMIF_JOB_OK == jobResult ) {
\r
809 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
810 admPtr->ErrorStatus = NVM_REQ_OK;
\r
815 if( bPtr->BlockUseCrc ) {
\r
817 /* The read data is in the work buffer, read the CRC */
\r
818 if( bPtr->BlockCRCType == NVM_CRC16) {
\r
819 admPtr->NvCrc.crc16 = READ16_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );
\r
821 DEBUG_PRINTF(">> Nv CRC %04x\n",admPtr->NvCrc.crc16);
\r
822 admPtr->RamCrc.crc16 = admPtr->NvCrc.crc16; /* Set RAM CRC = NvRAM CRC */
\r
824 admPtr->NvCrc.crc32 = READ32_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );
\r
826 DEBUG_PRINTF(">> Nv CRC %08x\n",admPtr->NvCrc.crc16);
\r
827 admPtr->RamCrc.crc32 = admPtr->NvCrc.crc32; /* Set RAM CRC = NvRAM CRC */
\r
830 /* 3.1.5/NVM201 + 3.1.5/NVM292 NvM_ReadBlock() + NvM_ReadAll() should request
\r
831 * recalculation of the RAM block data if configured with CRC.
\r
834 /* savedDataPtr points to the real data buffers and they do no contain the
\r
836 memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength );
\r
838 /* Check if we should re-calculate the RAM checksum now when it's in RAM
\r
840 if( bPtr->CalcRamBlockCrc ) {
\r
841 /* This block want its RAM block CRC checked */
\r
842 DEBUG_PRINTF(">> Recalculation of RAM checksum \n",admPtr->NvCrc.crc16);
\r
843 assert( bPtr->BlockUseCrc == 1);
\r
844 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;
\r
845 admPtr->BlockSubState = BLOCK_SUBSTATE_0;
\r
850 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
851 admPtr->ErrorStatus = NVM_REQ_OK;
\r
856 DEBUG_PRINTF(">> Block have NO CRC\n");
\r
858 memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength + crcLen );
\r
860 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
861 admPtr->ErrorStatus = NVM_REQ_OK;
\r
865 /* Copy from Workbuffer to the real buffer */
\r
870 /* Something failed */
\r
871 DEBUG_PRINTF(">> Read/Write FAILED\n");
\r
873 admPtr->NumberOfWriteFailed++;
\r
874 if( admPtr->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES ) {
\r
875 DEBUG_PRINTF(">> Write FAILED COMPLETELY (all retries)\n");
\r
877 admPtr->NumberOfWriteFailed = 0;
\r
884 * MEMIF have failed. Now what?
\r
885 * 1. Check if redundant, if so read the other block
\r
886 * 2. If point 1 fails and not redundant nor rom-block/initcallback,
\r
887 * fail with MEMIF_BLOCK_INVALID, MEMIF_BLOCK_INCONSISTENT or MEMIF_JOB_FAILED
\r
889 if( blockDone == 1 ) {
\r
890 /* All write have failed or we are reading? */
\r
891 if( 0 == handleRedundantBlock(bPtr,admPtr) ) {
\r
892 /* block is NOT redundant or both blocks have failed */
\r
893 if( bPtr->RomBlockDataAdress != NULL ) {
\r
894 DEBUG_PRINTF("Copying ROM data to block\n");
\r
895 memcpy(bPtr->RamBlockDataAddress, bPtr->RomBlockDataAdress,bPtr->NvBlockLength);
\r
896 admPtr->ErrorStatus = NVM_REQ_OK;
\r
897 } else if( bPtr->InitBlockCallback != NULL ) {
\r
898 /* @req 3.1.5/NVM469 */
\r
899 DEBUG_PRINTF("Filling block with default data\n");
\r
900 bPtr->InitBlockCallback();
\r
901 admPtr->ErrorStatus = NVM_REQ_OK;
\r
906 * Returned status are:
\r
908 * MEMIF_BLOCK_INVALID
\r
909 * The block is currenlty under some strange service (Fee_InvalidateBlock)
\r
911 * MEMIF_BLOCK_INCONSISTENT
\r
912 * Ea/Fee have detected that something is strange with the block. This may
\r
913 * happen for a virgin unit.
\r
916 * We failed for some reason.
\r
918 * At this point a lot of requirements NVM360, NVM342,etc will not be active
\r
919 * if there is a configured ROM block/InitCallback.
\r
922 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ; /* TODO, this really true for all result below */
\r
923 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;
\r
925 switch (jobResult) {
\r
926 case MEMIF_BLOCK_INVALID:
\r
927 /* @req 3.1.5/NVM342 */
\r
928 admPtr->ErrorStatus = NVM_REQ_NV_INVALIDATED;
\r
930 case MEMIF_BLOCK_INCONSISTENT:
\r
931 /* @req 3.1.5/NVM360 but is overridden by NVM172 (implicit revovery) */
\r
932 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;
\r
933 DEM_REPORTERRORSTATUS(NVM_E_REQ_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);
\r
935 case MEMIF_JOB_FAILED:
\r
936 /* @req 3.1.5/NVM361 */
\r
937 admPtr->ErrorStatus = NVM_REQ_NOT_OK;
\r
938 DEM_REPORTERRORSTATUS(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);
\r
941 DEBUG_PRINTF("## Unexpected jobResult:%d\n",jobResult);
\r
953 case BLOCK_STATE_CALC_CRC:
\r
957 case BLOCK_STATE_CALC_CRC_WRITE:
\r
963 if( bPtr->RamBlockDataAddress == NULL ) {
\r
964 /* If we have no buffer to work with something is very very wrong */
\r
965 NVM_ASSERT(dataPtr != NULL );
\r
968 ramData = bPtr->RamBlockDataAddress;
\r
971 admPtr->savedDataPtr = ramData;
\r
973 /* Calculate RAM CRC checksum */
\r
974 if( bPtr->BlockCRCType == NVM_CRC16 ) {
\r
976 crc16 = Crc_CalculateCRC16(ramData,bPtr->NvBlockLength,0xffff);
\r
977 DEBUG_CHECKSUM("RAM",crc16);
\r
979 /* Just save the checksum */
\r
980 admPtr->RamCrc.crc16 = crc16;
\r
982 /* Write the block */
\r
983 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
985 /* @req 3.1.5/NVM253 */
\r
986 crc32 = Crc_CalculateCRC32(ramData,bPtr->NvBlockLength,0xffffffffUL);
\r
987 DEBUG_CHECKSUM("RAM",crc32);
\r
989 admPtr->RamCrc.crc32 = crc32;
\r
991 /* Write the block */
\r
992 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
996 case BLOCK_STATE_CALC_CRC_READ:
\r
998 //NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );
\r
999 NVM_ASSERT(bPtr->CalcRamBlockCrc == true );
\r
1002 boolean checksumOk;
\r
1005 /* @req 3.1.5/NVM253 */
\r
1006 /* Calculate CRC on the data we just read to RAM. Compare with CRC that is located in NV block */
\r
1008 if( bPtr->BlockCRCType == NVM_CRC16 ) {
\r
1009 crc16 = Crc_CalculateCRC16(admPtr->savedDataPtr,bPtr->NvBlockLength,0xffff);
\r
1011 crc32 = Crc_CalculateCRC32(admPtr->savedDataPtr,bPtr->NvBlockLength,0xffffffffUL);
\r
1014 switch( admPtr->BlockSubState ) {
\r
1015 case BLOCK_SUBSTATE_0:
\r
1017 checksumOk = ( bPtr->BlockCRCType == NVM_CRC16 ) ? ( crc16 == admPtr->RamCrc.crc16 ) : ( crc32 == admPtr->RamCrc.crc32 );
\r
1019 /* @req 3.1.5/NVM387 */
\r
1020 if( checksumOk ) {
\r
1021 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1023 DEBUG_CHECKSUM("RAM checksum ok with ", ( bPtr->BlockCRCType == NVM_CRC16 ) ? crc16 : crc32 );
\r
1024 admPtr->ErrorStatus = NVM_REQ_OK;
\r
1025 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1030 * Corrupt CRC, what choices are there:
\r
1031 * 1. Default data (=ROM) configured, just copy it.
\r
1032 * 2. Data redundancy, get it.
\r
1033 * 3. None of the above. Catastrophic failure. (NVM203)
\r
1036 if( 0 == handleRedundantBlock(bPtr,admPtr) ) {
\r
1037 /* block is NOT redundant or both blocks have failed */
\r
1038 if( bPtr->RomBlockDataAdress != NULL ) {
\r
1039 DEBUG_PRINTF("Copying ROM data to block\n");
\r
1040 memcpy(bPtr->RamBlockDataAddress, bPtr->RomBlockDataAdress,bPtr->NvBlockLength);
\r
1041 admPtr->BlockSubState = BLOCK_SUBSTATE_1;
\r
1044 /* @req 3.1.5/NVM469 */
\r
1045 if( bPtr->InitBlockCallback != NULL ) {
\r
1047 DEBUG_PRINTF("Filling block with default data\n");
\r
1048 bPtr->InitBlockCallback();
\r
1049 admPtr->BlockSubState = BLOCK_SUBSTATE_1;
\r
1051 /* NVM085 is very vague here, but the says the application should be
\r
1052 * able distinguish between when the init-callback have been called
\r
1053 * or CRC is corrupt.
\r
1056 /* The RAM CRC is at this point not calculated...so we must do this
\r
1057 * .. so just stay in this state one more MainFunction.
\r
1062 /* We have CRC mismatch -> FAIL */
\r
1063 DEBUG_PRINTF("### Block FAILED with NVM_REQ_INTEGRITY_FAILED\n");
\r
1066 /* @req 3.1.5/NVM203 */
\r
1067 DEM_REPORTERRORSTATUS(NVM_E_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);
\r
1068 /* @req 3.1.5/NVM204 */
\r
1069 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;
\r
1070 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1077 case BLOCK_SUBSTATE_1:
\r
1078 /* The checksum is on the ROM data so just save it */
\r
1079 DEBUG_CHECKSUM("RAM checksum after ROM copy ", ( bPtr->BlockCRCType == NVM_CRC16 ) ? crc16 : crc32 );
\r
1081 if( bPtr->BlockCRCType == NVM_CRC16 ) {
\r
1082 admPtr->RamCrc.crc16 = crc16;
\r
1084 admPtr->RamCrc.crc32 = crc32;
\r
1086 admPtr->BlockSubState = BLOCK_SUBSTATE_0;
\r
1087 admPtr->ErrorStatus = NVM_REQ_OK;
\r
1088 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1104 DEBUG_PRINTF("# Block Done\n");
\r
1106 if( admPtr->ErrorStatus == NVM_REQ_OK ) {
\r
1107 admPtr->BlockChanged = FALSE;
\r
1108 admPtr->BlockValid = TRUE;
\r
1112 /* @req 3.1.5/NVM281 */
\r
1113 if( bPtr->SingleBlockCallback != NULL ) {
\r
1114 bPtr->SingleBlockCallback(serviceId, admPtr->ErrorStatus);
\r
1117 if( multiBlock ) {
\r
1118 AdminMultiReq.currBlockIndex++;
\r
1119 if( AdminMultiReq.currBlockIndex >= NVM_NUM_OF_NVRAM_BLOCKS ) {
\r
1120 AdminMultiReq.currBlockIndex = 0;
\r
1122 /* @req 3.1.5/NVM301 */
\r
1123 if( NVM_REQ_NOT_OK == AdminMultiReq.PendingErrorStatus ) {
\r
1124 AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;
\r
1126 AdminMultiBlock.ErrorStatus = NVM_REQ_OK;
\r
1128 nvmState = NVM_IDLE;
\r
1131 /* @req 3.1.5/NVM468 */
\r
1132 if( NvM_Config.Common.MultiBlockCallback != NULL ) {
\r
1133 NvM_Config.Common.MultiBlockCallback(serviceId, AdminMultiBlock.ErrorStatus);
\r
1137 nvmState = NVM_IDLE;
\r
1145 * Main function for the read all job
1147 static void ReadAllMain(void)
\r
1151 * 1. We process each block until it's finished
\r
1152 * 2. We start to process a lot of blocks. The blocks may use different devices
\r
1153 * and should be able to read a lot of them. This includes CRC.
\r
1155 * 1) is much simpler and 2) probably much faster.
\r
1156 * This implementation will use 1) since it's simpler and maximum time that is
\r
1157 * spent in MainFunction() can be controlled much better.
\r
1160 /* Skip blocks that are skipped */
\r
1161 while ( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {
\r
1163 if( AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus != NVM_REQ_BLOCK_SKIPPED) {
\r
1164 DriveBlock( &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],
\r
1165 &AdminBlock[AdminMultiReq.currBlockIndex],
\r
1171 AdminMultiReq.currBlockIndex++;
\r
1176 * Request writing of a block to MemIf
1178 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,
\r
1179 AdministrativeBlockType *adminBlock,
\r
1181 uint8 *sourceAddress)
\r
1183 Std_ReturnType returnCode;
\r
1185 if (setNumber < blockDescriptor->NvBlockNum) {
\r
1186 SetMemifJobBusy();
\r
1187 MemIfJobAdmin.BlockAdmin = adminBlock;
\r
1188 MemIfJobAdmin.BlockDescriptor = blockDescriptor;
\r
1189 returnCode = MemIf_Write(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), sourceAddress);
\r
1190 if (returnCode != E_OK) {
\r
1191 AbortMemIfJob(MEMIF_JOB_FAILED);
\r
1194 // Error: setNumber out of range
\r
1195 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_WRITE_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);
\r
1202 * Initiate the write all job
\r
1204 static boolean WriteAllInit(void)
\r
1206 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
1207 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
1209 boolean needsProcessing = FALSE;
\r
1211 // nvmState = NVM_WRITE_ALL_PROCESSING;
\r
1212 AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;
\r
1213 AdminMultiReq.currBlockIndex = 0;
\r
1215 for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {
\r
1216 if ((BlockDescriptorList->RamBlockDataAddress != NULL)
\r
1217 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM344 */
\r
1218 && (AdminBlockTable->BlockValid) /** @req NVM682 */
\r
1219 && (AdminBlockTable->BlockChanged) /** @req NVM682 */
\r
1221 && (!AdminBlockTable->BlockWriteProtected)) /** @req NVM432 *//** @req NVM433 */
\r
1223 AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;
\r
1225 if (BlockDescriptorList->BlockUseCrc) {
\r
1226 AdminBlockTable->BlockState = BLOCK_STATE_CALC_CRC_WRITE; /** @req NVM253 */
\r
1228 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1229 AdminBlockTable->NumberOfWriteFailed = 0;
\r
1231 needsProcessing = TRUE;
\r
1233 AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED; /** @req NVM298 */
\r
1236 AdminBlockTable++;
\r
1237 BlockDescriptorList++;
\r
1239 return needsProcessing;
\r
1245 * Main function for the write all job
\r
1247 static void WriteAllMain(void)
\r
1249 while ( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {
\r
1251 if( AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus != NVM_REQ_BLOCK_SKIPPED) {
\r
1252 DriveBlock( &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],
\r
1253 &AdminBlock[AdminMultiReq.currBlockIndex],
\r
1259 AdminMultiReq.currBlockIndex++;
\r
1266 * Handles the result of one MemIf block write
\r
1268 static void WriteAllCheckWriteResult(void)
\r
1270 if (MemIfJobAdmin.JobStatus == E_OK) {
\r
1271 // TODO: Check if redundant block shall be written NVM337
\r
1273 if (MemIfJobAdmin.BlockDescriptor->WriteBlockOnce) {
\r
1274 MemIfJobAdmin.BlockAdmin->BlockWriteProtected = TRUE; /** @req NVM329 */
\r
1276 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1277 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_OK;
\r
1279 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {
\r
1280 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);
\r
1283 MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed++;
\r
1284 if (MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES) {
\r
1285 // TODO: Check if redundant block shall be written NVM337
\r
1287 // Write has failed
\r
1288 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;
\r
1290 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1291 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK; /** @req NVM296 */
\r
1292 #if defined(USE_DEM)
\r
1293 Dem_ReportErrorStatus(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);
\r
1296 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {
\r
1297 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);
\r
1301 nvmState = NVM_WRITE_ALL_PROCESSING;
\r
1307 /***************************************
\r
1308 * External accessible functions *
\r
1309 ***************************************/
\r
1311 * Procedure: NvM_Init
\r
1314 void NvM_Init(void)
\r
1316 /** @req NVM399 *//** @req NVM193 */
\r
1317 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
1318 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
1322 CirqBuff_Init(&nvmQueue,nvmQueueData,sizeof(nvmQueueData)/sizeof(Nvm_QueueType),sizeof(Nvm_QueueType));
\r
1324 // Initiate the administration blocks
\r
1325 for (i = 0; i< NVM_NUM_OF_NVRAM_BLOCKS; i++) {
\r
1326 if (BlockDescriptorList->BlockManagementType == NVM_BLOCK_DATASET) {
\r
1327 AdminBlockTable->DataIndex = 0; /** @req NVM192 */
\r
1329 AdminBlockTable->BlockWriteProtected = BlockDescriptorList->BlockWriteProt;
\r
1330 AdminBlockTable->ErrorStatus = NVM_REQ_NOT_OK;
\r
1331 AdminBlockTable->BlockChanged = FALSE;
\r
1332 AdminBlockTable->BlockValid = FALSE;
\r
1333 AdminBlockTable->NumberOfWriteFailed = 0;
\r
1335 AdminBlockTable++;
\r
1336 BlockDescriptorList++;
\r
1339 AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;
\r
1341 // Set status to initialized
\r
1342 nvmState = NVM_IDLE; /** @req 3.1.5/NVM399 */
\r
1349 * NvM_ReadAll() does not set status here or need to check status of the
\r
1350 * any blocks since it's done after all single reads are done.
\r
1352 void NvM_ReadAll(void)
\r
1355 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);
\r
1357 NVM_ASSERT(nvmState == NVM_IDLE);
\r
1360 AdminMultiReq.state = NVM_READ_ALL;
\r
1361 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;
\r
1362 AdminMultiReq.serviceId = NVM_READ_ALL_ID;
\r
1363 Irq_Restore(state);
\r
1369 * Procedure: NvM_WriteAll
\r
1372 void NvM_WriteAll(void)
\r
1375 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);
\r
1377 NVM_ASSERT(nvmState == NVM_IDLE);
\r
1380 AdminMultiReq.state = NVM_WRITE_ALL;
\r
1381 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;
\r
1382 AdminMultiReq.serviceId = NVM_WRITE_ALL_ID;
\r
1383 Irq_Restore(state);
\r
1388 * Procedure: NvM_CancelWriteAll
\r
1391 void NvM_CancelWriteAll(void)
\r
1398 * Procedure: NvM_GetErrorStatus
\r
1401 Std_ReturnType NvM_GetErrorStatus(NvM_BlockIdType blockId, NvM_RequestResultType *requestResultPtr)
\r
1403 VALIDATE_RV(nvmState != NVM_UNINITIALIZED, NVM_GET_ERROR_STATUS_ID, NVM_E_NOT_INITIALIZED, E_NOT_OK );
\r
1404 VALIDATE_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_GET_ERROR_STATUS_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK );
\r
1406 if (blockId == 0) {
\r
1408 *requestResultPtr = AdminMultiBlock.ErrorStatus;
\r
1409 } else if (blockId == 1) {
\r
1410 /* TODO Configuration ID */
\r
1411 *requestResultPtr = NVM_REQ_OK;
\r
1413 *requestResultPtr = AdminBlock[blockId-1].ErrorStatus;
\r
1419 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM408 */
\r
1421 * Procedure: Nvm_SetRamBlockStatus
\r
1424 Std_ReturnType NvM_SetRamBlockStatus(NvM_BlockIdType blockId, boolean blockChanged)
\r
1426 AdministrativeBlockType * admPtr;
\r
1427 Nvm_QueueType qEntry;
\r
1430 VALIDATE_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK);
\r
1432 admPtr = &AdminBlock[blockId-1];
\r
1434 VALIDATE_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_NOT_INITIALIZED, E_NOT_OK); /** @req NVM497 */
\r
1435 VALIDATE_RV(blockId > 1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK );
\r
1436 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1438 qEntry.blockId = blockId;
\r
1439 qEntry.op = NVM_SETRAMBLOCKSTATUS;
\r
1440 qEntry.blockChanged = blockChanged;
\r
1441 qEntry.serviceId = NVM_SET_RAM_BLOCK_STATUS_ID;
\r
1442 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1443 NVM_ASSERT(rv == 0 );
\r
1445 /* req 3.1.5/NVM185 */
\r
1446 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1452 static void setRamBlockStatus( const NvM_BlockDescriptorType *bPtr, AdministrativeBlockType *admPtr, boolean blockChanged ) {
\r
1454 if (bPtr->RamBlockDataAddress != NULL) { /** @req NVM240 */
\r
1455 if (blockChanged) {
\r
1456 admPtr->BlockChanged = TRUE; /** @req NVM406 */
\r
1457 admPtr->BlockValid = TRUE; /** @req NVM241 */
\r
1458 // TODO? if (bPtr->BlockUseCrc) {
\r
1459 // admPtr->BlockState = BLOCK_STATE_CALC_CRC; /** @req NVM121 */
\r
1462 admPtr->BlockChanged = FALSE; /** @req NVM405 */
\r
1463 admPtr->BlockValid = FALSE;
\r
1464 } // else blockChanged
\r
1465 } // if permanent block
\r
1468 void NvM_SetBlockLockStatus( NvM_BlockIdType blockId, boolean blockLocked ) {
\r
1470 (void)blockLocked;
\r
1475 * Restore default data to its corresponding RAM block.
\r
1477 * @param BlockId NVRAM block identifier.
1478 * @param NvM_DestPtr Pointer to the RAM block
1481 Std_ReturnType NvM_RestoreBlockDefaults( NvM_BlockIdType blockId, uint8* NvM_DestPtr )
\r
1483 /* !req 3.1.5/NVM012 */ /* !req 3.1.5/NVM267 */ /* !req 3.1.5/NVM266 */
\r
1484 /* !req 3.1.5/NVM353 */ /* !req 3.1.5/NVM435 */ /* !req 3.1.5/NVM436 */ /* !req 3.1.5/NVM227 */
\r
1485 /* !req 3.1.5/NVM228 */ /* !req 3.1.5/NVM229 */ /* !req 3.1.5/NVM413 */
\r
1487 const NvM_BlockDescriptorType * bPtr;
\r
1488 AdministrativeBlockType * admPtr;
\r
1489 Nvm_QueueType qEntry;
\r
1492 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1494 /* @req 3.1.5/NVM618 */
\r
1495 VALIDATE_RV( blockId <= NVM_NUM_OF_NVRAM_BLOCKS,
\r
1496 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );
\r
1498 bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1499 admPtr = &AdminBlock[blockId-1];
\r
1501 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */ /** @req 3.1.5/NVM210 */
\r
1502 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */
\r
1503 VALIDATE_RV( !((NvM_DestPtr == NULL) && ( bPtr->RamBlockDataAddress == NULL )),
\r
1504 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );
\r
1506 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1508 /* @req 3.1.5/NVM195 */
\r
1509 qEntry.blockId = blockId;
\r
1510 qEntry.op = NVM_RESTORE_BLOCK_DEFAULTS;
\r
1511 qEntry.blockId = blockId;
\r
1512 qEntry.dataPtr = (uint8_t *)NvM_DestPtr;
\r
1513 qEntry.serviceId = NVM_RESTORE_BLOCK_DEFAULTS_ID;
\r
1514 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1515 NVM_ASSERT(rv == 0 );
\r
1517 /* req 3.1.5/NVM185 */
\r
1518 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1520 if( bPtr->BlockUseCrc) {
\r
1521 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
1523 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1531 * Service to copy the data NV block to the RAM block
\r
1533 * @param blockId 0 and 1 reserved. The block ID are sequential.
1539 Std_ReturnType NvM_ReadBlock( NvM_BlockIdType blockId, uint8* NvM_DstPtr )
\r
1541 /* !req 3.1.5/NVM010 */
\r
1544 /* !req 3.1.5/NVM278 */
\r
1545 /* !req 3.1.5/NVM340 */
\r
1546 /* !req 3.1.5/NVM354 */
\r
1547 /* !req 3.1.5/NVM200 */
\r
1548 /* !req 3.1.5/NVM366 */
\r
1549 /* !req 3.1.5/NVM206 */
\r
1550 /* !req 3.1.5/NVM341 */
\r
1551 /* !req 3.1.5/NVM358 */
\r
1552 /* !req 3.1.5/NVM359 */
\r
1553 /* !req 3.1.5/NVM279 */
\r
1554 /* !req 3.1.5/NVM316 */
\r
1555 /* !req 3.1.5/NVM317 */
\r
1556 /* !req 3.1.5/NVM201 */
\r
1557 /* !req 3.1.5/NVM202 */
\r
1558 /* !req 3.1.5/NVM203 */
\r
1559 /* !req 3.1.5/NVM204 */
\r
1560 /* !req 3.1.5/NVM409 */
\r
1566 * |5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
\r
1567 * b b b b b b b b b b d d d d d d
\r
1569 * Here we have 10 bits for block id, 16-5 for DataSetSelection bits.
\r
1570 * - 2^10, 1024 blocks
\r
1571 * - 64 datasets for each NVRAM block
\r
1573 * How are the block numbers done in EA? Assume virtual page=8
\r
1584 * How can NVM/NvmNvBlockLength and EA/EaBlockSize be different?
\r
1585 * It seems that EA/FEE does not care about that logical block 2 above is
\r
1589 Nvm_QueueType qEntry;
\r
1592 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1593 VALIDATE_RV( !(( NvM_DstPtr == NULL) &&
\r
1594 ( NvM_Config.BlockDescriptor[blockId-1].RamBlockDataAddress == NULL )),
\r
1595 0, NVM_E_PARAM_ADDRESS , E_NOT_OK );
\r
1596 VALIDATE_RV( (AdminBlock[blockId-1].ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1598 /* @req 3.1.5/NVM195 */
\r
1599 qEntry.blockId = blockId;
\r
1600 qEntry.op = NVM_READ_BLOCK;
\r
1601 qEntry.blockId = blockId;
\r
1602 qEntry.dataPtr = NvM_DstPtr;
\r
1603 qEntry.serviceId = NVM_READ_BLOCK_ID;
\r
1604 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1605 NVM_ASSERT(rv == 0 );
\r
1608 /* req 3.1.5/NVM185 */
\r
1609 AdminBlock[blockId-1].ErrorStatus = NVM_REQ_PENDING;
\r
1616 * Service to copy a RAM block to its correspnding NVRAM block
\r
1622 Std_ReturnType NvM_WriteBlock( NvM_BlockIdType blockId, const uint8* NvM_SrcPtr ) {
\r
1624 const NvM_BlockDescriptorType * bPtr;
\r
1625 AdministrativeBlockType * admPtr;
\r
1626 Nvm_QueueType qEntry;
\r
1629 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1631 /* @req 3.1.5/NVM618 */
\r
1632 VALIDATE_RV( blockId <= NVM_NUM_OF_NVRAM_BLOCKS,
\r
1633 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );
\r
1635 bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1636 admPtr = &AdminBlock[blockId-1];
\r
1638 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1639 VALIDATE_RV( !((NvM_SrcPtr == NULL) && ( bPtr->RamBlockDataAddress == NULL )),
\r
1640 0, NVM_E_PARAM_ADDRESS, E_NOT_OK );
\r
1641 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1643 /* @req 3.1.5/NVM195 */
\r
1644 qEntry.blockId = blockId;
\r
1645 qEntry.op = NVM_WRITE_BLOCK;
\r
1646 qEntry.blockId = blockId;
\r
1647 qEntry.dataPtr = (uint8_t *)NvM_SrcPtr;
\r
1648 qEntry.serviceId = NVM_WRITE_BLOCK_ID;
\r
1649 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1650 NVM_ASSERT(rv == 0 );
\r
1652 /* req 3.1.5/NVM185 */
\r
1653 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1655 if( bPtr->BlockUseCrc) {
\r
1656 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
1658 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1665 /* Missing from Class 2
\r
1666 * - NvM_CancelWriteAll
\r
1669 //#if (NVM_API_CONFIG_CLASS > NVM_API_CONFIG_CLASS_1)
\r
1673 * This function returns void in 3.1.5 and in 4.0 it returns Std_ReturnType.
\r
1677 * x NVM_E_NOT_INITIALIZED
\r
1678 * x NVM_E_BLOCK_PENDING
\r
1679 * NVM_E_PARAM_BLOCK_DATA_IDX
\r
1680 * NVM_E_PARAM_BLOCK_TYPE
\r
1681 * x NVM_E_PARAM_BLOCK_ID
\r
1684 Std_ReturnType NvM_SetDataIndex( NvM_BlockIdType blockId, uint8 dataIndex ) {
\r
1685 #if ( NVM_DEV_ERROR_DETECT == STD_ON )
\r
1686 const NvM_BlockDescriptorType * bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1688 AdministrativeBlockType * admPtr = &AdminBlock[blockId-1];
\r
1690 Nvm_QueueType qEntry;
\r
1693 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1695 VALIDATE_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_DATA_INDEX_ID, NVM_E_NOT_INITIALIZED, E_NOT_OK);
\r
1696 VALIDATE_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK);
\r
1697 VALIDATE_RV(bPtr->BlockManagementType != NVM_BLOCK_NATIVE , NVM_SET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_TYPE , E_NOT_OK);
\r
1698 VALIDATE_RV(dataIndex < bPtr->NvBlockNum + bPtr->RomBlockNum , NVM_SET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_DATA_IDX ,E_NOT_OK);
\r
1699 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), NVM_SET_DATA_INDEX_ID, NVM_E_BLOCK_PENDING , E_NOT_OK);
\r
1701 qEntry.blockId = blockId;
\r
1702 qEntry.op = NVM_SETDATAINDEX;
\r
1703 qEntry.blockId = blockId;
\r
1704 qEntry.dataIndex = dataIndex;
\r
1705 qEntry.serviceId = NVM_SET_DATA_INDEX_ID;
\r
1706 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1707 NVM_ASSERT(rv == 0 );
\r
1709 /* req 3.1.5/NVM185 */
\r
1710 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1715 Std_ReturnType NvM_GetDataIndex( NvM_BlockIdType blockId, uint8 *dataIndexPtr ) {
\r
1716 #if ( NVM_DEV_ERROR_DETECT == STD_ON )
\r
1717 const NvM_BlockDescriptorType * bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1719 AdministrativeBlockType * admPtr = &AdminBlock[blockId-1];
\r
1720 Nvm_QueueType qEntry;
\r
1723 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1725 VALIDATE_RV(nvmState != NVM_UNINITIALIZED, NVM_GET_DATA_INDEX_ID, NVM_E_NOT_INITIALIZED, E_NOT_OK);
\r
1726 VALIDATE_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_GET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_ID, E_NOT_OK);
\r
1727 VALIDATE_RV(bPtr->BlockManagementType != NVM_BLOCK_NATIVE , NVM_GET_DATA_INDEX_ID, NVM_E_PARAM_BLOCK_TYPE , E_NOT_OK);
\r
1728 VALIDATE_RV( (dataIndexPtr != NULL) , NVM_GET_DATA_INDEX_ID, NVM_E_PARAM_DATA ,E_NOT_OK);
\r
1729 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), NVM_GET_DATA_INDEX_ID, NVM_E_BLOCK_PENDING , E_NOT_OK);
\r
1731 qEntry.blockId = blockId;
\r
1732 qEntry.op = NVM_GETDATAINDEX;
\r
1733 qEntry.blockId = blockId;
\r
1734 qEntry.dataPtr = dataIndexPtr;
\r
1735 qEntry.serviceId = NVM_GET_DATA_INDEX_ID;
\r
1736 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1737 NVM_ASSERT(rv == 0 );
\r
1739 /* req 3.1.5/NVM185 */
\r
1740 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1745 const NvM_BlockDescriptorType * nvmBlock;
\r
1746 AdministrativeBlockType *admBlock;
\r
1751 void NvM_MainFunction(void)
\r
1754 Nvm_QueueType qEntry;
\r
1755 const NvM_BlockDescriptorType * bList = NvM_Config.BlockDescriptor;
\r
1756 // const NvM_BlockDescriptorType * currBlock;
\r
1757 // static uint32 crc32;
\r
1758 // static uint32 crc32Left;
\r
1760 /* Check for new requested state changes */
\r
1761 if( nvmState == NVM_IDLE ) {
\r
1762 rv = CirqBuffPop( &nvmQueue, &qEntry );
\r
1764 /* Found something in buffer */
\r
1765 nvmState = qEntry.op;
\r
1766 nvmBlock = &bList[qEntry.blockId-1];
\r
1767 admBlock = &AdminBlock[qEntry.blockId-1];
\r
1769 admBlock->ErrorStatus = NVM_REQ_PENDING;
\r
1770 serviceId = qEntry.serviceId;
\r
1771 DEBUG_PRINTF("### Popped Single FIFO : %s\n",StateToStr[qEntry.op]);
\r
1772 DEBUG_PRINTF("### CRC On:%d Ram:%d Type:%d\n",nvmBlock->BlockUseCrc, nvmBlock->CalcRamBlockCrc, nvmBlock->BlockCRCType );
\r
1773 DEBUG_PRINTF("### RAM:%x ROM:%x\n", nvmBlock->RamBlockDataAddress, nvmBlock->RomBlockDataAdress );
\r
1775 /* Check multiblock req and do after all single block reads (3.1.5/NVM243) */
\r
1776 if( AdminMultiReq.state != NVM_UNINITIALIZED ) {
\r
1777 nvmState = AdminMultiReq.state ;
\r
1781 serviceId = AdminMultiReq.serviceId;
\r
1782 AdminMultiReq.state = NVM_UNINITIALIZED;
\r
1784 DEBUG_PRINTF("### Popped MULTI\n");
\r
1789 DEBUG_STATE(nvmState,nvmSubState);
\r
1791 switch (nvmState) {
\r
1792 case NVM_UNINITIALIZED:
\r
1800 case NVM_READ_ALL:
\r
1801 if( NS_INIT == nvmSubState ) {
\r
1802 if( ReadAllInit() ) {
\r
1803 nvmSubState = NS_PROSSING;
\r
1805 /* Nothing to do, everything is OK */
\r
1806 AdminMultiBlock.ErrorStatus = NVM_REQ_OK;
\r
1807 nvmState = NVM_IDLE;
\r
1810 } else if( NS_PROSSING == nvmSubState ) {
\r
1815 case NVM_READ_BLOCK:
\r
1816 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, false );
\r
1819 case NVM_RESTORE_BLOCK_DEFAULTS:
\r
1820 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, true );
\r
1823 case NVM_WRITE_BLOCK:
\r
1824 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, true /*write*/, false , false );
\r
1827 case NVM_WRITE_ALL:
\r
1828 if( NS_INIT == nvmSubState ) {
\r
1829 if( WriteAllInit() ) {
\r
1830 nvmSubState = NS_PROSSING;
\r
1832 /* Nothing to do, everything is OK */
\r
1833 AdminMultiBlock.ErrorStatus = NVM_REQ_OK;
\r
1834 nvmState = NVM_IDLE;
\r
1837 } else if( NS_PROSSING == nvmSubState ) {
\r
1841 case NVM_SETDATAINDEX:
\r
1842 admBlock->DataIndex = qEntry.dataIndex;
\r
1843 nvmState = NVM_IDLE;
\r
1845 admBlock->ErrorStatus = NVM_REQ_OK;
\r
1847 case NVM_GETDATAINDEX:
\r
1848 *qEntry.dataPtr = admBlock->DataIndex;
\r
1849 nvmState = NVM_IDLE;
\r
1851 admBlock->ErrorStatus = NVM_REQ_OK;
\r
1853 case NVM_SETRAMBLOCKSTATUS:
\r
1854 setRamBlockStatus(nvmBlock,admBlock,qEntry.blockChanged );
\r
1855 nvmState = NVM_IDLE;
\r
1857 admBlock->ErrorStatus = NVM_REQ_OK;
\r
1860 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_MAIN_FUNCTION_ID, NVM_UNEXPECTED_STATE);
\r
1866 /***************************************
\r
1867 * Call-back notifications functions *
\r
1868 ***************************************/
\r
1869 #if (NVM_POLLING_MODE == STD_OFF)
\r
1871 * Procedure: NvM_JobEndNotification
\r
1874 void NvM_JobEndNotification(void)
\r
1876 MemIfJobAdmin.JobFinished = TRUE;
\r
1877 MemIfJobAdmin.JobStatus = E_OK;
\r
1878 MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);
\r
1882 * Procedure: NvM_JobErrorNotification
\r
1885 void NvM_JobErrorNotification(void)
\r
1887 MemIfJobAdmin.JobFinished = TRUE;
\r
1888 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
1889 MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);
\r