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
17 * RamBlockDataAddress
\r
18 * NULL is no permanent RAM block. Otherwise allocate the number of bytes in space (like the stack)
\r
21 * Understanding block numbering:
\r
23 * NVM_DATASET_SELECTION_BIT=2
\r
26 * 0 Reserved (NVM478)
\r
27 * 1 NVM_BLOCK_NATIVE, NvBlockNum=1
\r
28 * 2 NVM_BLOCK_REDUNDANT, NvBlockNum=2
\r
29 * 3 NVM_BLOCK_DATASET, NvBlockNum=4
\r
31 * NvM_ReadBlock( 0, ... ) - Reserved for "multi block requests"
\r
32 * NvM_ReadBlock( 1, ... ) - Reserved for redundant NVRAM block which holds the configuration ID.
\r
33 * NvM_ReadBlock( 2--x, ... ) - "Normal" blocks
\r
36 * NvM_BlockIdType*) NvBlockBaseNumber EA_BLOCK_NUMBER
\r
39 * 2 1 4, (5,6,7) ****)
\r
40 * 3 2 8, R9,(10,11) ****)
\r
41 * 4 3 12, D13,D14,D15 ****)
\r
43 * *) Type used in the API.
\r
46 * ****) FEE/EA_BLOCK_NUMBER = NvBlockBaseNumber << NvmDatasetSelectionBits = NvBlockBaseNumber * 4
\r
47 * () - Cannot be accesses due to NvBlockNum
\r
48 * R9 - Redundant block
\r
52 * Both NvM and EA/FEE have block sizes. NvM have NvNvmBlockLength (NVM479) and FEE/EA have EaBlockSize.
\r
53 * FEE/EA also have virtual page that is the alignment of a block, with the smallest block=size of the virtual page.
\r
55 * So, who allocates space for this. FEE/EA only have EaBlockSize.
\r
56 * NvM have NvmRamBlockDataAddress, NvmRomBlockDataAddress and mapping to a MemIf Blocks (FEE/EA blocks)
\r
58 * ASSUME: I can't really see a point for the FEE/EA EaBlockSize.. it will just a multiple of NvNvmBlockLength*NvBlockNum + overhead?
\r
59 * Click-box in EA/FEE that leaves the size calculation to NvM?
\r
60 * This also means that enabling NvmBlockUseCrc or set a block from NVM_BLOCK_NATIVE to NVM_BLOCK_DATASET would be "automatic"
\r
61 * in calculation of the EaBlockSize.
\r
63 * 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
64 * 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
67 * NVM121: NvM_SetRamBlockStatus(), calculate CRC in background if NvmCalcRamBlockCrc==TRUE
\r
68 * NVM362: NvM_ReadAll() , if (NvmCalcRamBlockCrc == TRUE && permanent RAM block) re-calc CRC.
\r
70 * NvmBlockUseCrc - Global CRC switch. Space is allocated in both RAM and NV block
\r
71 * NvmCalcRamBlockCrc - CRC re-calculation. For example during startup, you may don't want
\r
72 * to verify all the checksums again, but instead just copy from NV
\r
75 * There is also explicit RAM checksum calculations for example NVM253 (Nvm_WriteAll()) where a CRC calculation
\r
76 * is requested (although not stated should be dependent on NvmBlockUseCrc only, not NvmCalcRamBlockCrc).
\r
77 * You have to calculate the checksum at some point....
\r
80 * NVM185: Says "successful enqueueing a request".."set to NVM_REQ_PENDING"
\r
81 * NVM380: The queue length for multi block request shall be one (NvM_ReadAll, NvM_WriteAll)
\r
82 * NVM381+NVM567 : Multi block requests shall not be interrupted.
\r
83 * NVM243+NVM245: Do not unqueue the multi block request until all single block queues are empty.
\r
84 * So, when NvmState==IDLE and we have a multi-request
\r
91 * To get some speed into this multiple thing must be done in the same MainFunction loop.
\r
94 * The interface is actually quite strange, so you may read from any address (through MemIf_Read())
\r
95 * but MemIf_Write(..) only takes a logical block and a pointer to the data to write.
\r
97 * See two alternatives here:
\r
98 * 1. If the NVBlock also contains the checksum after the data then writing the data needs a
\r
99 * RAM that is as big as the biggest RAM block + room for checksum.
\r
100 * 2. If checksums would be kept in a separate EA/FEE block the ALL the checksum need to be written.
\r
101 * For example after a NvM_WriteBlock() the checksum block would need to be written. This
\r
102 * will probably lead consistency problems also... what happens if we fail to write the checksum
\r
111 * Provide Data for the first/initial read
\r
112 * When a block have no
\r
119 * BlockUseCrc (A): If the block (both RAM and NV) should use CRC
\r
120 * CalcRamBlockCrc (B): If the permanent RAM block should re-calculate it's CRC.
\r
124 * 0 0 No error detection or recovery
\r
129 * RAM BLOCK VALID/UNCHANGED
\r
130 * Figure 8 and 9 in 3.1.5/NVM is more confusing than good.
\r
131 * What we have to know is:
\r
132 * 1. Initially the RAM block is in INVALID/UNCHANGED
\r
133 * ALT 2. After a NvM_ReadAll() and all is well the state goes to VALID/UNCHANGED
\r
134 * ALT 2. If ROM values are used we go to VALID/CHANGED (We failed to read from NVRAM)
\r
136 * For NvM_WriteAll()
\r
137 * 1. A block that is INVALID can't be written
\r
138 * 2. A block that is UNCHANGED should not be written.
\r
139 * -> Write only blocks that are VALID/CHANGED.
\r
141 * VALID/UNCHANGED - RAM == NV
\r
142 * VALID/CHANGED - RAM != NV (analog to cache memories, "dirty")
\r
145 * VALID/CHANGED state - Dirty (since RAM != NV)
\r
146 * WriteBlock - Flush (Flush the RAM block to NV)
\r
147 * ReadBlock - Invalidate (NV block is read to RAM)
\r
152 * General requirements
\r
160 * NB! Even though some code exist for handling RamCrc, the functionality is not complete
\r
161 * and shall not be used.
164 //lint -esym(522,CalcCrc) // 522 PC-Lint exception for empty functions
\r
165 //lint -emacro(904,VALIDATE_RV,VALIDATE_NO_RV) //904 PC-Lint exception to MISRA 14.7 (validate macros).
\r
167 // Exception made as a result of that NVM_DATASET_SELECTION_BITS can be zero
\r
168 //lint -emacro(835, BLOCK_BASE_AND_SET_TO_BLOCKNR) // 835 PC-lint: A zero has been given as right argument to operator '<<' or '>>'
\r
171 /* ----------------------------[includes]------------------------------------*/
\r
173 #include <assert.h>
\r
175 #include "NvM_Cbk.h"
\r
176 #include "Rte.h" // ???
\r
177 #if defined(USE_DEM)
\r
181 //#include "SchM_NvM.h"
\r
182 #include "MemMap.h"
\r
183 #include "cirq_buffer.h"
\r
184 #include "Modules.h"
\r
188 #include <string.h>
\r
190 //#define DEBUG_BLOCK 1
\r
191 #if defined(DEBUG_BLOCK)
\r
192 #define DEBUG_BLOCK_STATE(_str,_block,_state) printf("%s BLOCK NR:%d STATE:%d\n",_str,_block, _state); fflush(stdout);
\r
193 #define DEBUG_STATE(_state,_substate) printf("MAIN_STATE:%s/%d\n",StateToStr[_state],_substate); fflush(stdout);
\r
194 #define DEBUG_PRINTF(format,...) printf(format,## __VA_ARGS__ ); fflush(stdout);
\r
195 #define DEBUG_CHECKSUM(_str,_crc) printf("%s crc=%x\n",_str,_crc);
\r
197 #define DEBUG_BLOCK_STATE(_str,_block,_state)
\r
198 #define DEBUG_STATE(_state,_substate)
\r
199 #define DEBUG_PRINTF(format,...)
\r
200 #define DEBUG_CHECKSUM(_str,_crc)
\r
204 /* ----------------------------[private define]------------------------------*/
\r
208 #define NVM_BLOCK_ALIGNMENT 4
\r
209 #define NVM_CHECKSUM_LENGTH 4
\r
211 #define NVM_BLOCK_OFFSET 2
\r
217 /* ----------------------------[private macro]-------------------------------*/
\r
219 #define NVM_ASSERT(_exp) if( !(_exp) ) { while(1) {}; } //assert(_exp)
\r
221 #if ( NVM_DEV_ERROR_DETECT == STD_ON )
\r
223 #define VALIDATE(_exp,_api,_err ) \
\r
225 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
229 #define VALIDATE_RV(_exp,_api,_err,_rv ) \
\r
231 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
235 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
237 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
240 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)
\r
243 #define VALIDATE(_exp,_api,_err )
\r
244 #define VALIDATE_RV(_exp,_api,_err,_rv )
\r
245 #define VALIDATE_NO_RV(_exp,_api,_err )
\r
246 #define DET_REPORTERROR(_module,_instance,_api,_err)
\r
249 #define BLOCK_BASE_AND_SET_TO_BLOCKNR(_blockbase, _set) ((uint16)(_blockbase << NVM_DATASET_SELECTION_BITS) | _set)
\r
251 #if defined(USE_DEM)
\r
252 #define DEM_REPORTERRORSTATUS(_err,_ev ) Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED);
\r
254 #define DEM_REPORTERRORSTATUS(_err,_ev )
\r
258 #define BLOCK_NR_FROM_PTR(_bptr) (((_bptr) - NvM_Config.BlockDescriptor + 1)) // sizeof(NvM_BlockDescriptorType))
\r
260 #define CREATE_ENTRY(_val) [_val] = #_val
\r
265 /* ----------------------------[private typedef]-----------------------------*/
\r
269 NVM_UNINITIALIZED = 0,
\r
275 NVM_RESTORE_BLOCK_DEFAULTS,
\r
278 char *StateToStr[20] = {
\r
279 CREATE_ENTRY(NVM_UNINITIALIZED),
\r
280 CREATE_ENTRY(NVM_IDLE),
\r
281 CREATE_ENTRY(NVM_READ_ALL),
\r
282 CREATE_ENTRY(NVM_WRITE_ALL),
\r
283 CREATE_ENTRY(NVM_READ_BLOCK),
\r
284 CREATE_ENTRY(NVM_WRITE_BLOCK),
\r
289 BLOCK_STATE_MEMIF_REQ,
\r
290 // BLOCK_STATE_START,
\r
291 BLOCK_STATE_MEMIF_PROCESS,
\r
292 // BLOCK_STATE_MEMIF_CRC_PROCESS,
\r
293 BLOCK_STATE_CALC_CRC,
\r
294 // BLOCK_STATE_MEMIF_PROCESS_CRC,
\r
295 BLOCK_STATE_CALC_CRC_WRITE,
\r
296 BLOCK_STATE_CALC_CRC_READ,
\r
297 // BLOCK_STATE_LOAD_FROM_NV,
\r
314 NvM_RequestResultType ErrorStatus; // Status from multi block requests i.e. Read/Write/CancelWrite-all
\r
315 } AdministrativeMultiBlockType;
\r
318 BlockStateType BlockState;
\r
319 uint8 DataIndex; // Selected data index if "Data Set" type
\r
320 boolean BlockWriteProtected; // Block write protected?
\r
321 NvM_RequestResultType ErrorStatus; // Status of block
\r
322 boolean BlockChanged; // Block changed?
\r
323 boolean BlockValid; // Block valid? (RAM block only?)
\r
324 uint8 NumberOfWriteFailed; // Current write retry cycle
\r
325 union Nvm_CRC RamCrc;
\r
326 union Nvm_CRC NvCrc; // The CRC of this block, read from NV
\r
327 void * savedDataPtr; //
\r
330 } AdministrativeBlockType;
\r
335 NVM_OP_WRITE_BLOCK,
\r
336 NVM_OP_RESTORE_BLOCK_DEFAULTS,
\r
341 #define NO_MULTIBLOCK 0
\r
342 #define MULTIBLOCK 1
\r
347 NvM_BlockIdType blockId;
\r
348 uint8 * dataPtr; /* Src or Dest ptr */
\r
353 /* ----------------------------[private function prototypes]-----------------*/
\r
354 /* ----------------------------[private variables]---------------------------*/
\r
356 static NvmStateType nvmState = NVM_UNINITIALIZED;
\r
359 #define RB_WAIT_READ 1
\r
360 #define RB_CALC_CHECKSUM 2
\r
362 static int nvmSubState = 0;
\r
363 //static int nvmSetNr;
\r
364 static AdministrativeBlockType AdminBlock[NVM_NUM_OF_NVRAM_BLOCKS];
\r
365 static AdministrativeMultiBlockType AdminMultiBlock;
\r
368 //static Nvm_QueueType nvmQueueImmData[NVM_SIZE_IMMEDIATE_JOB_QUEUE];
\r
369 static Nvm_QueueType nvmQueueData[NVM_SIZE_STANDARD_JOB_QUEUE];
\r
371 uint8 Nvm_WorkBuffer[200]; /* TODO */
\r
373 #if (NVM_SIZE_STANDARD_JOB_QUEUE == 0)
\r
374 #error NVM_SIZE_STANDARD_JOB_QUEUE have size 0
\r
378 CirqBufferType nvmQueue;
\r
381 /* ----------------------------[private functions]---------------------------*/
\r
383 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,
\r
384 AdministrativeBlockType *adminBlock,
\r
386 uint8 *sourceAddress);
\r
388 /* ----------------------------[public functions]----------------------------*/
\r
393 * This function needs to be implemented!
395 static void CalcCrc(void)
\r
397 // TODO: Calculate CRC
\r
401 boolean JobFinished;
\r
402 Std_ReturnType JobStatus;
\r
403 MemIf_JobResultType JobResult;
\r
404 const NvM_BlockDescriptorType * BlockDescriptor;
\r
405 AdministrativeBlockType * BlockAdmin;
\r
406 } MemIfJobAdminType;
\r
408 static MemIfJobAdminType MemIfJobAdmin = {
\r
409 .JobFinished = TRUE,
\r
411 .JobResult = MEMIF_JOB_OK,
\r
412 .BlockDescriptor = NULL,
\r
416 enum Nvm_MultiBlockReq {
\r
423 NvmStateType state;
\r
424 uint16 currBlockIndex; // Keeps track of next unfinished block
\r
425 NvM_RequestResultType PendingErrorStatus; // Status from multi block requests i.e. Read/Write/CancelWrite-all
\r
426 } AdminMultiReqType;
\r
428 static AdminMultiReqType AdminMultiReq;
\r
432 * Set the MemIf job as busy
434 static void SetMemifJobBusy()
\r
436 MemIfJobAdmin.JobFinished = FALSE;
\r
440 #if (NVM_POLLING_MODE == STD_ON)
\r
442 * Check if the MemIf job is finished
444 static boolean CheckMemIfJobFinished(void)
\r
446 MemIf_JobResultType jobResult;
\r
448 if (!MemIfJobAdmin.JobFinished) {
\r
449 jobResult = MemIf_GetJobResult();
\r
451 if (jobResult == MEMIF_JOB_OK) {
\r
452 MemIfJobAdmin.JobFinished = TRUE;
\r
453 MemIfJobAdmin.JobStatus = E_OK;
\r
454 MemIfJobAdmin.JobResult = jobResult;
\r
455 } else if (jobResult != MEMIF_JOB_PENDING) {
\r
456 MemIfJobAdmin.JobFinished = TRUE;
\r
457 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
458 MemIfJobAdmin.JobResult = jobResult;
\r
462 return MemIfJobAdmin.JobFinished;
\r
466 * Check if the MemIf job is finished
\r
469 static boolean CheckMemIfJobFinished(void)
\r
471 return MemIfJobAdmin.JobFinished;
\r
478 * Abort the MemIf job with E_NOT_OK
\r
480 static void AbortMemIfJob(MemIf_JobResultType jobResult)
\r
482 MemIfJobAdmin.JobFinished = TRUE;
\r
483 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
484 MemIfJobAdmin.JobResult = jobResult;
\r
488 static boolean CheckJobFailed( void ) {
\r
489 return CheckMemIfJobFinished() && (MemIfJobAdmin.JobResult == MEMIF_JOB_FAILED);
\r
494 * Request a read of a block from MemIf
496 static void ReadBlock(const NvM_BlockDescriptorType *blockDescriptor,
\r
497 AdministrativeBlockType *adminBlock,
\r
499 uint16 blockOffset,
\r
500 uint8 *destAddress,
\r
503 Std_ReturnType returnCode;
\r
505 if (setNumber < blockDescriptor->NvBlockNum) {
\r
507 MemIfJobAdmin.BlockAdmin = adminBlock;
\r
508 MemIfJobAdmin.BlockDescriptor = blockDescriptor;
\r
509 returnCode = MemIf_Read(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), blockOffset, destAddress, length );
\r
510 if (returnCode != E_OK) {
\r
511 AbortMemIfJob(MEMIF_JOB_FAILED);
\r
513 } else if (setNumber < blockDescriptor->NvBlockNum + blockDescriptor->RomBlockNum) {
\r
514 // TODO: Read from ROM
\r
516 // Error: setNumber out of range
\r
517 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_READ_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);
\r
523 * Initiate the read all job
525 static void ReadAllInit(void)
\r
528 * Initiate the read all job
530 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
531 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
534 // Set status to pending in the administration blocks
\r
535 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING; /** @req 3.1.5/NVM304 */
\r
536 AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;
\r
537 AdminMultiReq.currBlockIndex = 0;
\r
539 for (i = 0; i < ( NVM_NUM_OF_NVRAM_BLOCKS ); i++) {
\r
540 if ((BlockDescriptorList->SelectBlockForReadall)
\r
541 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM345 */
\r
542 && ((!AdminBlockTable->BlockValid) // TODO: Check if this is to be done like this
\r
543 || (!AdminBlockTable->BlockChanged)) // TODO: Check if this is to be done like this
\r
546 VALIDATE_NO_RV(BlockDescriptorList->RamBlockDataAddress != NULL, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);
\r
547 VALIDATE_NO_RV(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);
\r
549 AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;
\r
550 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
552 AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED; /* @req 3.1.5/NVM287 */
\r
556 BlockDescriptorList++;
\r
561 static void writeCrcToBuffer( void *bufPtr,
\r
562 const NvM_BlockDescriptorType *bPtr,
\r
563 AdministrativeBlockType *admPtr )
\r
565 if( bPtr->BlockUseCrc ) {
\r
566 if(bPtr->BlockCRCType == NVM_CRC16) {
\r
567 WRITE16_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc16);
\r
569 WRITE32_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc32);
\r
576 * Drive the read state-machine
\r
582 static void DriveBlock( const NvM_BlockDescriptorType *bPtr,
\r
583 AdministrativeBlockType *admPtr,
\r
586 boolean multiBlock,
\r
587 boolean restoreFromRom )
\r
589 bool blockDone = 0;
\r
590 static uint8 driveBlockCnt = 0;
\r
593 NVM_ASSERT( admPtr->ErrorStatus == NVM_REQ_PENDING);
\r
595 DEBUG_BLOCK_STATE("DriveBlock", BLOCK_NR_FROM_PTR(bPtr), admPtr->BlockState );
\r
597 switch (admPtr->BlockState) {
\r
598 case BLOCK_STATE_MEMIF_REQ:
\r
600 void *ramData = (dataPtr != NULL) ? dataPtr : bPtr->RamBlockDataAddress;
\r
602 admPtr->savedDataPtr = ramData;
\r
605 if( multiBlock && (dataPtr!=NULL)) {
\r
608 /* Copy to work buffer */
\r
609 memcpy( Nvm_WorkBuffer, ramData, bPtr->NvBlockLength );
\r
610 /* Add the CRC to write */
\r
611 writeCrcToBuffer(Nvm_WorkBuffer, bPtr, admPtr );
\r
612 WriteBlock(bPtr, admPtr, 0, Nvm_WorkBuffer);
\r
615 /* Read to workbuffer */
\r
616 if( bPtr->BlockUseCrc ) {
\r
617 crcLen = (bPtr->BlockCRCType == NVM_CRC16) ? 2: 4;
\r
620 if( restoreFromRom ) {
\r
621 NVM_ASSERT( bPtr->RomBlockDataAdress != NULL );
\r
622 /* No CRC on the ROM block */
\r
623 memcpy(ramData,bPtr->RomBlockDataAdress,bPtr->NvBlockLength);
\r
625 admPtr->ErrorStatus = NVM_REQ_OK;
\r
629 ReadBlock(bPtr, admPtr, 0, 0, bPtr->RamBlockDataAddress, bPtr->NvBlockLength+crcLen);
\r
633 admPtr->BlockState = BLOCK_STATE_MEMIF_PROCESS;
\r
637 case BLOCK_STATE_MEMIF_PROCESS:
\r
640 MemIf_JobResultType jobResult = MemIf_GetJobResult(0);
\r
642 if( MEMIF_JOB_PENDING == jobResult ) {
\r
643 /* Keep on waiting */
\r
644 } else if( MEMIF_JOB_OK == jobResult ) {
\r
648 if( BLOCK_STATE_MEMIF_CRC_PROCESS == admPtr->BlockState ) {
\r
649 /* @req 3.1.5/NVM362 NvM_ReadAll*/
\r
650 DEBUG_CHECKSUM("RAM CRC", (bPtr->BlockCRCType == NVM_CRC16) ? admPtr->RamCrc.crc16 : admPtr->RamCrc.crc32);
\r
651 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;
\r
657 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
658 admPtr->ErrorStatus = NVM_REQ_OK;
\r
662 if( bPtr->BlockUseCrc ) {
\r
663 /* Explicit CRC calc (not dependent on NvmCalcRamBlockCrc) */
\r
664 /* @req 3.1.5/NVM212 NvM_WriteBlock */
\r
665 /* @req 3.1.5/NVM253 NvM_WriteAll */
\r
666 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
669 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
670 admPtr->ErrorStatus = NVM_REQ_OK;
\r
677 if( bPtr->BlockUseCrc ) {
\r
679 /* The read data is in the work buffer, read the CRC */
\r
680 if( bPtr->BlockCRCType == NVM_CRC16) {
\r
681 admPtr->NvCrc.crc16 = READ16_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );
\r
683 DEBUG_PRINTF(">> Nv CRC %04x\n",admPtr->NvCrc.crc16);
\r
684 admPtr->RamCrc.crc16 = admPtr->NvCrc.crc16; /* Set RAM CRC = NvRAM CRC */
\r
686 admPtr->NvCrc.crc32 = READ32_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );
\r
688 DEBUG_PRINTF(">> Nv CRC %08x\n",admPtr->NvCrc.crc16);
\r
689 admPtr->RamCrc.crc32 = admPtr->NvCrc.crc32; /* Set RAM CRC = NvRAM CRC */
\r
692 memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength + crcLen );
\r
694 /* Check if we should re-calculate the RAM checksum now when it's in RAM */
\r
695 if( bPtr->CalcRamBlockCrc ) {
\r
696 /* This block want its RAM block CRC checked */
\r
697 DEBUG_PRINTF(">> Recalculation of RAM checksum \n",admPtr->NvCrc.crc16);
\r
698 assert( bPtr->BlockUseCrc == 1);
\r
699 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;
\r
702 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
703 admPtr->ErrorStatus = NVM_REQ_OK;
\r
708 DEBUG_PRINTF(">> Block have NO CRC\n");
\r
710 memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength + crcLen );
\r
712 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
713 admPtr->ErrorStatus = NVM_REQ_OK;
\r
717 /* Copy from Workbuffer to the real buffer */
\r
722 /* Something failed */
\r
723 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;
\r
725 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ; /* TODO, this really true for all result below */
\r
727 switch( jobResult ) {
\r
728 case MEMIF_BLOCK_INVALID:
\r
729 /* @req 3.1.5/NVM342 */
\r
730 admPtr->ErrorStatus = NVM_REQ_NV_INVALIDATED;
\r
732 case MEMIF_BLOCK_INCONSISTENT:
\r
733 /* @req 3.1.5/NVM360 */
\r
734 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;
\r
735 DEM_REPORTERRORSTATUS(NVM_E_REQ_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);
\r
737 case MEMIF_JOB_FAILED:
\r
738 /* @req 3.1.5/NVM361 */
\r
739 admPtr->ErrorStatus = NVM_REQ_NOT_OK;
\r
740 DEM_REPORTERRORSTATUS(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);
\r
749 case BLOCK_STATE_CALC_CRC:
\r
753 case BLOCK_STATE_CALC_CRC_WRITE:
\r
757 NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );
\r
759 /* Calculate RAM CRC checksum */
\r
760 if( bPtr->BlockCRCType == NVM_CRC16 ) {
\r
762 crc16 = Crc_CalculateCRC16(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffff);
\r
763 DEBUG_CHECKSUM("RAM",crc16);
\r
765 /* Just save the checksum */
\r
766 admPtr->RamCrc.crc16 = crc16;
\r
769 /* NV CRC in admin block */
\r
770 if( admPtr->RamCrc.crc16 != crc16 ) {
\r
771 NVM_ASSERT(0); /* TODO: Corrupt CRC */
\r
773 admPtr->BlockChanged = BLOCK_STATE_MEMIF_REQ;
\r
777 /* Write the block */
\r
778 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
780 /* @req 3.1.5/NVM253 */
\r
781 crc32 = Crc_CalculateCRC32(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffffffffUL);
\r
782 if( crc32 != admPtr->RamCrc.crc32 ) {
\r
783 /* The checksum is wrong, something have written to the RAM area without
\r
784 * telling the NVM */
\r
787 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
789 admPtr->RamCrc.crc32 = crc32;
\r
793 case BLOCK_STATE_CALC_CRC_READ:
\r
795 NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );
\r
796 NVM_ASSERT(bPtr->CalcRamBlockCrc == true );
\r
800 /* Calculate RAM CRC checksum */
\r
801 if( bPtr->BlockCRCType == NVM_CRC16 ) {
\r
804 crc16 = Crc_CalculateCRC16(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffff);
\r
805 DEBUG_CHECKSUM("RAM",crc16);
\r
807 /* NV CRC in admin block */
\r
809 if( driveBlockCnt == 1) {
\r
810 /* The previous "loop" we filled with default data */
\r
811 admPtr->RamCrc.crc16 = crc16;
\r
814 /* @req 3.1.5/NVM387 */
\r
815 if( admPtr->RamCrc.crc16 != crc16 ) {
\r
817 /* @req 3.1.5/NVM388 Nvm_ReadAll */
\r
821 * Corrupt CRC, what choices are there:
\r
822 * 1. Default data (=ROM) configured, just copy it.
\r
823 * 2. Data redundancy, get it.
\r
824 * 3. None of the above. Catastrophic failure. (NVM203)
\r
826 if( bPtr->RomBlockDataAdress != NULL ) {
\r
827 /* TODO: Restore block from ROM */
\r
830 /* @req 3.1.5/NVM469 */
\r
831 if( bPtr->InitBlockCallback != NULL ) {
\r
833 DEBUG_PRINTF("Filling block with default data\n");
\r
834 bPtr->InitBlockCallback();
\r
836 /* NVM085 is very vague here, but the says the application should be
\r
837 * able distinguish between when the init-callback have been called
\r
838 * or CRC is corrupt.
\r
841 /* The RAM CRC is at this point not calculated...so we must do this
\r
842 * .. so just stay in this state one more MainFunction.
\r
847 /* @req 3.1.5/NVM203 */
\r
848 DEM_REPORTERRORSTATUS(NVM_E_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);
\r
849 /* @req 3.1.5/NVM204 */
\r
850 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;
\r
851 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
856 DEBUG_CHECKSUM("RAM checksum ok with ",crc16);
\r
857 admPtr->ErrorStatus = NVM_REQ_OK;
\r
858 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
863 /* @req 3.1.5/NVM253 */
\r
864 /* Calculate CRC on the data we just read to RAM. Compare with CRC that is located in NV block */
\r
865 crc32 = Crc_CalculateCRC32(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffffffffUL);
\r
866 if( crc32 != admPtr->RamCrc.crc32 ) {
\r
867 NVM_ASSERT(0); /* TODO: Corrupt CRC */
\r
869 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
881 DEBUG_PRINTF("# Block Done\n");
\r
883 if( admPtr->ErrorStatus == NVM_REQ_OK ) {
\r
884 admPtr->BlockChanged = FALSE;
\r
885 admPtr->BlockValid = TRUE;
\r
889 /* @req 3.1.5/NVM281 */
\r
890 if( bPtr->SingleBlockCallback != NULL ) {
\r
891 bPtr->SingleBlockCallback(NVM_READ_ALL_ID, admPtr->ErrorStatus);
\r
895 AdminMultiReq.currBlockIndex++;
\r
896 if( AdminMultiReq.currBlockIndex >= NVM_NUM_OF_NVRAM_BLOCKS ) {
\r
897 AdminMultiReq.currBlockIndex = 0;
\r
899 /* @req 3.1.5/NVM301 */
\r
900 if( NVM_REQ_NOT_OK == AdminMultiReq.PendingErrorStatus ) {
\r
901 AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;
\r
903 AdminMultiBlock.ErrorStatus = NVM_REQ_OK;
\r
905 nvmState = NVM_IDLE;
\r
909 nvmState = NVM_IDLE;
\r
917 * Main function for the read all job
919 static void ReadAllMain(void)
\r
923 * 1. We process each block until it's finished
\r
924 * 2. We start to process a lot of blocks. The blocks may use different devices
\r
925 * and should be able to read a lot of them. This includes CRC.
\r
927 * 1) is much simpler and 2) probably much faster.
\r
928 * This implementation will use 1) since it's simpler and maximum time that is
\r
929 * spent in MainFunction() can be controlled much better.
\r
932 /* Skip blocks that are skipped */
\r
934 while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {
\r
935 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {
\r
936 AdminMultiReq.currBlockIndex++;
\r
942 DriveBlock( &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],
\r
943 &AdminBlock[AdminMultiReq.currBlockIndex],
\r
951 * Request writing of a block to MemIf
953 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,
\r
954 AdministrativeBlockType *adminBlock,
\r
956 uint8 *sourceAddress)
\r
958 Std_ReturnType returnCode;
\r
960 if (setNumber < blockDescriptor->NvBlockNum) {
\r
962 MemIfJobAdmin.BlockAdmin = adminBlock;
\r
963 MemIfJobAdmin.BlockDescriptor = blockDescriptor;
\r
964 returnCode = MemIf_Write(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), sourceAddress);
\r
965 if (returnCode != E_OK) {
\r
966 AbortMemIfJob(MEMIF_JOB_FAILED);
\r
969 // Error: setNumber out of range
\r
970 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_WRITE_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);
\r
977 * Initiate the write all job
\r
979 static void WriteAllInit(void)
\r
981 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
982 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
985 // nvmState = NVM_WRITE_ALL_PROCESSING;
\r
986 AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;
\r
987 AdminMultiReq.currBlockIndex = 0;
\r
989 for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {
\r
990 if ((BlockDescriptorList->RamBlockDataAddress != NULL)
\r
991 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM344 */
\r
992 && (AdminBlockTable->BlockValid) /** @req NVM682 */
\r
993 && (AdminBlockTable->BlockChanged) /** @req NVM682 */
\r
995 && (!AdminBlockTable->BlockWriteProtected)) /** @req NVM432 *//** @req NVM433 */
\r
997 AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;
\r
999 if (BlockDescriptorList->BlockUseCrc) {
\r
1000 AdminBlockTable->BlockState = BLOCK_STATE_CALC_CRC_WRITE; /** @req NVM253 */
\r
1002 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1003 AdminBlockTable->NumberOfWriteFailed = 0;
\r
1006 AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED; /** @req NVM298 */
\r
1009 AdminBlockTable++;
\r
1010 BlockDescriptorList++;
\r
1017 * Main function for the write all job
\r
1019 static void WriteAllMain(void)
\r
1022 while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {
\r
1023 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {
\r
1024 AdminMultiReq.currBlockIndex++;
\r
1030 DriveBlock( &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],
\r
1031 &AdminBlock[AdminMultiReq.currBlockIndex],
\r
1041 * Handles the result of one MemIf block write
\r
1043 static void WriteAllCheckWriteResult(void)
\r
1045 if (MemIfJobAdmin.JobStatus == E_OK) {
\r
1046 // TODO: Check if redundant block shall be written NVM337
\r
1048 if (MemIfJobAdmin.BlockDescriptor->WriteBlockOnce) {
\r
1049 MemIfJobAdmin.BlockAdmin->BlockWriteProtected = TRUE; /** @req NVM329 */
\r
1051 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1052 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_OK;
\r
1054 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {
\r
1055 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);
\r
1058 MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed++;
\r
1059 if (MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES) {
\r
1060 // TODO: Check if redundant block shall be written NVM337
\r
1062 // Write has failed
\r
1063 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;
\r
1065 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1066 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK; /** @req NVM296 */
\r
1067 #if defined(USE_DEM)
\r
1068 Dem_ReportErrorStatus(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);
\r
1071 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {
\r
1072 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);
\r
1076 nvmState = NVM_WRITE_ALL_PROCESSING;
\r
1082 /***************************************
\r
1083 * External accessible functions *
\r
1084 ***************************************/
\r
1086 * Procedure: NvM_Init
\r
1089 void NvM_Init(void)
\r
1091 /** @req NVM399 *//** @req NVM193 */
\r
1092 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
1093 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
1097 CirqBuff_Init(&nvmQueue,nvmQueueData,sizeof(nvmQueueData),sizeof(Nvm_QueueType));
\r
1099 // Initiate the administration blocks
\r
1100 for (i = 0; i< NVM_NUM_OF_NVRAM_BLOCKS; i++) {
\r
1101 if (BlockDescriptorList->BlockManagementType == NVM_BLOCK_DATASET) {
\r
1102 AdminBlockTable->DataIndex = 0; /** @req NVM192 */
\r
1104 AdminBlockTable->BlockWriteProtected = BlockDescriptorList->BlockWriteProt;
\r
1105 AdminBlockTable->ErrorStatus = NVM_REQ_NOT_OK;
\r
1106 AdminBlockTable->BlockChanged = FALSE;
\r
1107 AdminBlockTable->BlockValid = FALSE;
\r
1108 AdminBlockTable->NumberOfWriteFailed = 0;
\r
1110 AdminBlockTable++;
\r
1111 BlockDescriptorList++;
\r
1114 AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;
\r
1116 // Set status to initialized
\r
1117 nvmState = NVM_IDLE; /** @req 3.1.5/NVM399 */
\r
1122 * Procedure: NvM_ReadAll
\r
1125 void NvM_ReadAll(void)
\r
1127 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);
\r
1129 NVM_ASSERT(nvmState == NVM_IDLE);
\r
1131 AdminMultiReq.state = NVM_READ_ALL;
\r
1132 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;
\r
1138 * Procedure: NvM_WriteAll
\r
1141 void NvM_WriteAll(void)
\r
1143 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);
\r
1145 NVM_ASSERT(nvmState == NVM_IDLE);
\r
1147 AdminMultiReq.state = NVM_WRITE_ALL;
\r
1148 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;
\r
1153 * Procedure: NvM_CancelWriteAll
\r
1156 void NvM_CancelWriteAll(void)
\r
1163 * Procedure: NvM_GetErrorStatus
\r
1166 void NvM_GetErrorStatus(NvM_BlockIdType blockId, uint8 *requestResultPtr)
\r
1168 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_GET_ERROR_STATUS_ID, NVM_E_NOT_INITIALIZED);
\r
1169 VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_GET_ERROR_STATUS_ID, NVM_E_PARAM_BLOCK_ID);
\r
1171 if (blockId == 0) {
\r
1173 *requestResultPtr = AdminMultiBlock.ErrorStatus;
\r
1174 } else if (blockId == 1) {
\r
1177 *requestResultPtr = AdminBlock[blockId-1].ErrorStatus;
\r
1183 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM408 */
\r
1185 * Procedure: Nvm_SetRamBlockStatus
\r
1188 void NvM_SetRamBlockStatus(NvM_BlockIdType blockId, boolean blockChanged)
\r
1190 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
1192 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_NOT_INITIALIZED); /** @req NVM497 */
\r
1193 VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);
\r
1194 VALIDATE_NO_RV(blockId > 1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);
\r
1196 if (BlockDescriptorList[blockId-1].RamBlockDataAddress != NULL) { /** @req NVM240 */
\r
1197 if (blockChanged) {
\r
1198 AdminBlock[blockId-1].BlockChanged = TRUE; /** @req NVM406 */
\r
1199 AdminBlock[blockId-1].BlockValid = TRUE; /** @req NVM241 */
\r
1200 if (BlockDescriptorList[blockId-1].BlockUseCrc) {
\r
1201 AdminBlock[blockId-1].BlockState = BLOCK_STATE_CALC_CRC; /** @req NVM121 */
\r
1204 AdminBlock[blockId-1].BlockChanged = FALSE; /** @req NVM405 */
\r
1205 AdminBlock[blockId-1].BlockValid = FALSE;
\r
1206 } // else blockChanged
\r
1207 } // if permanent block
\r
1212 void NvM_SetBlockLockStatus( NvM_BlockIdType blockId, boolean blockLocked ) {
\r
1214 (void)blockLocked;
\r
1219 * Restore default data to its corresponding RAM block.
\r
1221 * @param BlockId NVRAM block identifier.
1222 * @param NvM_DestPtr Pointer to the RAM block
1225 Std_ReturnType NvM_RestoreBlockDefaults( NvM_BlockIdType blockId, uint8* NvM_DestPtr )
\r
1227 /* !req 3.1.5/NVM012 */ /* !req 3.1.5/NVM267 */ /* !req 3.1.5/NVM266 */
\r
1228 /* !req 3.1.5/NVM353 */ /* !req 3.1.5/NVM435 */ /* !req 3.1.5/NVM436 */ /* !req 3.1.5/NVM227 */
\r
1229 /* !req 3.1.5/NVM228 */ /* !req 3.1.5/NVM229 */ /* !req 3.1.5/NVM413 */
\r
1231 const NvM_BlockDescriptorType * bPtr;
\r
1232 AdministrativeBlockType * admPtr;
\r
1233 Nvm_QueueType qEntry;
\r
1236 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1238 /* @req 3.1.5/NVM618 */
\r
1239 VALIDATE_RV( blockId <= NVM_NUM_OF_NVRAM_BLOCKS,
\r
1240 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );
\r
1242 bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1243 admPtr = &AdminBlock[blockId-1];
\r
1245 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1246 if( (NvM_DestPtr == NULL) && ( bPtr->RamBlockDataAddress == NULL ) ) {
\r
1247 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */
\r
1248 NVM_ASSERT(0); // TODO: See NVM210, DET error
\r
1252 /* @req 3.1.5/NVM195 */
\r
1253 qEntry.blockId = blockId;
\r
1254 qEntry.op = NVM_RESTORE_BLOCK_DEFAULTS;
\r
1255 qEntry.blockId = blockId;
\r
1256 qEntry.dataPtr = (uint8_t *)NvM_DestPtr;
\r
1257 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1258 NVM_ASSERT(rv == 0 );
\r
1260 /* @req 3.1.5/NVM620 */
\r
1261 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1263 /* req 3.1.5/NVM185 */
\r
1264 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1266 if( bPtr->BlockUseCrc) {
\r
1267 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
1269 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1277 * Service to copy the data NV block to the RAM block
\r
1279 * @param blockId 0 and 1 reserved. The block ID are sequential.
1285 Std_ReturnType NvM_ReadBlock( NvM_BlockIdType blockId, uint8* NvM_DstPtr )
\r
1287 /* !req 3.1.5/NVM010 */
\r
1290 /* !req 3.1.5/NVM278 */
\r
1291 /* !req 3.1.5/NVM340 */
\r
1292 /* !req 3.1.5/NVM354 */
\r
1293 /* !req 3.1.5/NVM200 */
\r
1294 /* !req 3.1.5/NVM366 */
\r
1295 /* !req 3.1.5/NVM206 */
\r
1296 /* !req 3.1.5/NVM341 */
\r
1297 /* !req 3.1.5/NVM358 */
\r
1298 /* !req 3.1.5/NVM359 */
\r
1299 /* !req 3.1.5/NVM279 */
\r
1300 /* !req 3.1.5/NVM316 */
\r
1301 /* !req 3.1.5/NVM317 */
\r
1302 /* !req 3.1.5/NVM201 */
\r
1303 /* !req 3.1.5/NVM202 */
\r
1304 /* !req 3.1.5/NVM203 */
\r
1305 /* !req 3.1.5/NVM204 */
\r
1306 /* !req 3.1.5/NVM409 */
\r
1312 * |5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
\r
1313 * b b b b b b b b b b d d d d d d
\r
1315 * Here we have 10 bits for block id, 16-5 for DataSetSelection bits.
\r
1316 * - 2^10, 1024 blocks
\r
1317 * - 64 datasets for each NVRAM block
\r
1319 * How are the block numbers done in EA? Assume virtual page=8
\r
1330 * How can NVM/NvmNvBlockLength and EA/EaBlockSize be different?
\r
1331 * It seems that EA/FEE does not care about that logical block 2 above is
\r
1335 Nvm_QueueType qEntry;
\r
1338 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1339 if( (NvM_DstPtr == NULL) && ( NvM_Config.BlockDescriptor[blockId-1].RamBlockDataAddress == NULL ) ) {
\r
1340 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */
\r
1344 /* @req 3.1.5/NVM195 */
\r
1345 qEntry.blockId = blockId;
\r
1346 qEntry.op = NVM_READ_BLOCK;
\r
1347 qEntry.blockId = blockId;
\r
1348 qEntry.dataPtr = NvM_DstPtr;
\r
1349 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1350 NVM_ASSERT(rv == 0 );
\r
1352 /* @req 3.1.5/NVM615 */
\r
1353 VALIDATE_RV( (AdminBlock[blockId-1].ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1355 /* req 3.1.5/NVM185 */
\r
1356 AdminBlock[blockId-1].ErrorStatus = NVM_REQ_PENDING;
\r
1363 * Service to copy a RAM block to its correspnding NVRAM block
\r
1369 Std_ReturnType NvM_WriteBlock( NvM_BlockIdType blockId, const uint8* NvM_SrcPtr ) {
\r
1371 const NvM_BlockDescriptorType * bPtr;
\r
1372 AdministrativeBlockType * admPtr;
\r
1373 Nvm_QueueType qEntry;
\r
1376 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1378 /* @req 3.1.5/NVM618 */
\r
1379 VALIDATE_RV( blockId <= NVM_NUM_OF_NVRAM_BLOCKS,
\r
1380 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );
\r
1382 bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1383 admPtr = &AdminBlock[blockId-1];
\r
1385 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1386 if( (NvM_SrcPtr == NULL) && ( bPtr->RamBlockDataAddress == NULL ) ) {
\r
1387 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */
\r
1388 NVM_ASSERT(0); // TODO: See NVM210, DET error
\r
1392 /* @req 3.1.5/NVM195 */
\r
1393 qEntry.blockId = blockId;
\r
1394 qEntry.op = NVM_WRITE_BLOCK;
\r
1395 qEntry.blockId = blockId;
\r
1396 qEntry.dataPtr = (uint8_t *)NvM_SrcPtr;
\r
1397 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1398 NVM_ASSERT(rv == 0 );
\r
1400 /* @req 3.1.5/NVM620 */
\r
1401 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1403 /* req 3.1.5/NVM185 */
\r
1404 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1406 if( bPtr->BlockUseCrc) {
\r
1407 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
1409 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1416 /* Missing from Class 2
\r
1417 * - NvM_CancelWriteAll
\r
1418 * - NvM_SetDataIndex
\r
1419 * - NvM_GetDataIndex
\r
1426 const NvM_BlockDescriptorType * nvmBlock;
\r
1427 AdministrativeBlockType *admBlock;
\r
1432 void NvM_MainFunction(void)
\r
1435 Nvm_QueueType qEntry;
\r
1436 const NvM_BlockDescriptorType * bList = NvM_Config.BlockDescriptor;
\r
1437 // const NvM_BlockDescriptorType * currBlock;
\r
1438 // static uint32 crc32;
\r
1439 // static uint32 crc32Left;
\r
1441 /* Check for new requested state changes */
\r
1442 if( nvmState == NVM_IDLE ) {
\r
1443 rv = CirqBuffPop( &nvmQueue, &qEntry );
\r
1445 /* Found something in buffer */
\r
1446 nvmState = qEntry.op;
\r
1447 nvmBlock = &bList[qEntry.blockId-1];
\r
1448 admBlock = &AdminBlock[qEntry.blockId-1];
\r
1450 admBlock->ErrorStatus = NVM_REQ_PENDING;
\r
1451 DEBUG_PRINTF("### Popped Single FIFO \n");
\r
1452 DEBUG_PRINTF("### CRC On:%d Ram:%d Type:%d\n",nvmBlock->BlockUseCrc, nvmBlock->CalcRamBlockCrc, nvmBlock->BlockCRCType );
\r
1453 DEBUG_PRINTF("### RAM:%x ROM:%x\n", nvmBlock->RamBlockDataAddress, nvmBlock->RomBlockDataAdress );
\r
1455 /* Check multiblock req */
\r
1456 if( AdminMultiReq.state != NVM_UNINITIALIZED ) {
\r
1457 nvmState = AdminMultiReq.state ;
\r
1461 AdminMultiReq.state = NVM_UNINITIALIZED;
\r
1463 DEBUG_PRINTF("### Popped MULTI\n");
\r
1468 DEBUG_STATE(nvmState,nvmSubState);
\r
1470 switch (nvmState) {
\r
1471 case NVM_UNINITIALIZED:
\r
1479 case NVM_READ_ALL:
\r
1480 if( NS_INIT == nvmSubState ) {
\r
1482 nvmSubState = NS_PROSSING;
\r
1483 } else if( NS_PROSSING == nvmSubState ) {
\r
1488 case NVM_READ_BLOCK:
\r
1489 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, false );
\r
1492 case NVM_RESTORE_BLOCK_DEFAULTS:
\r
1493 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, true );
\r
1496 case NVM_WRITE_BLOCK:
\r
1497 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, true /*write*/, false , false );
\r
1500 case NVM_WRITE_ALL:
\r
1501 if( NS_INIT == nvmSubState ) {
\r
1503 nvmSubState = NS_PROSSING;
\r
1504 } else if( NS_PROSSING == nvmSubState ) {
\r
1510 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_MAIN_FUNCTION_ID, NVM_UNEXPECTED_STATE);
\r
1516 /***************************************
\r
1517 * Call-back notifications functions *
\r
1518 ***************************************/
\r
1519 #if (NVM_POLLING_MODE == STD_OFF)
\r
1521 * Procedure: NvM_JobEndNotification
\r
1524 void NvM_JobEndNotification(void)
\r
1526 MemIfJobAdmin.JobFinished = TRUE;
\r
1527 MemIfJobAdmin.JobStatus = E_OK;
\r
1528 MemIfJobAdmin.JobResult = MemIf_GetJobResult();
\r
1532 * Procedure: NvM_JobErrorNotification
\r
1535 void NvM_JobErrorNotification(void)
\r
1537 MemIfJobAdmin.JobFinished = TRUE;
\r
1538 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
1539 MemIfJobAdmin.JobResult = MemIf_GetJobResult();
\r