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
192 //#define DEBUG_BLOCK 1
\r
193 #if defined(DEBUG_BLOCK)
\r
194 #define DEBUG_BLOCK_STATE(_str,_block,_state) printf("%s BLOCK NR:%d STATE:%d\n",_str,_block, _state); fflush(stdout);
\r
195 #define DEBUG_STATE(_state,_substate) printf("MAIN_STATE:%s/%d\n",StateToStr[_state],_substate); fflush(stdout);
\r
196 #define DEBUG_PRINTF(format,...) printf(format,## __VA_ARGS__ ); fflush(stdout);
\r
197 #define DEBUG_CHECKSUM(_str,_crc) printf("%s crc=%x\n",_str,_crc);
\r
199 #define DEBUG_BLOCK_STATE(_str,_block,_state)
\r
200 #define DEBUG_STATE(_state,_substate)
\r
201 #define DEBUG_PRINTF(format,...)
\r
202 #define DEBUG_CHECKSUM(_str,_crc)
\r
206 /* ----------------------------[private define]------------------------------*/
\r
210 #define NVM_BLOCK_ALIGNMENT 4
\r
211 #define NVM_CHECKSUM_LENGTH 4
\r
213 #define NVM_BLOCK_OFFSET 2
\r
219 /* ----------------------------[private macro]-------------------------------*/
\r
221 #define NVM_ASSERT(_exp) if( !(_exp) ) { while(1) {}; } //assert(_exp)
\r
223 #if ( NVM_DEV_ERROR_DETECT == STD_ON )
\r
225 #define VALIDATE(_exp,_api,_err ) \
\r
227 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
231 #define VALIDATE_RV(_exp,_api,_err,_rv ) \
\r
233 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
237 #define VALIDATE_NO_RV(_exp,_api,_err ) \
\r
239 Det_ReportError(MODULE_ID_NVM, 0, _api, _err); \
\r
242 #define DET_REPORTERROR(_module,_instance,_api,_err) Det_ReportError(_module,_instance,_api,_err)
\r
245 #define VALIDATE(_exp,_api,_err )
\r
246 #define VALIDATE_RV(_exp,_api,_err,_rv )
\r
247 #define VALIDATE_NO_RV(_exp,_api,_err )
\r
248 #define DET_REPORTERROR(_module,_instance,_api,_err)
\r
251 #define BLOCK_BASE_AND_SET_TO_BLOCKNR(_blockbase, _set) ((uint16)(_blockbase << NVM_DATASET_SELECTION_BITS) | _set)
\r
253 #if defined(USE_DEM)
\r
254 #define DEM_REPORTERRORSTATUS(_err,_ev ) Dem_ReportErrorStatus(_err, DEM_EVENT_STATUS_FAILED);
\r
256 #define DEM_REPORTERRORSTATUS(_err,_ev )
\r
260 #define BLOCK_NR_FROM_PTR(_bptr) (((_bptr) - NvM_Config.BlockDescriptor + 1)) // sizeof(NvM_BlockDescriptorType))
\r
262 #define CREATE_ENTRY(_val) [_val] = #_val
\r
267 /* ----------------------------[private typedef]-----------------------------*/
\r
271 NVM_UNINITIALIZED = 0,
\r
277 NVM_RESTORE_BLOCK_DEFAULTS,
\r
280 char *StateToStr[20] = {
\r
281 CREATE_ENTRY(NVM_UNINITIALIZED),
\r
282 CREATE_ENTRY(NVM_IDLE),
\r
283 CREATE_ENTRY(NVM_READ_ALL),
\r
284 CREATE_ENTRY(NVM_WRITE_ALL),
\r
285 CREATE_ENTRY(NVM_READ_BLOCK),
\r
286 CREATE_ENTRY(NVM_WRITE_BLOCK),
\r
291 BLOCK_STATE_MEMIF_REQ,
\r
292 // BLOCK_STATE_START,
\r
293 BLOCK_STATE_MEMIF_PROCESS,
\r
294 // BLOCK_STATE_MEMIF_CRC_PROCESS,
\r
295 BLOCK_STATE_CALC_CRC,
\r
296 // BLOCK_STATE_MEMIF_PROCESS_CRC,
\r
297 BLOCK_STATE_CALC_CRC_WRITE,
\r
298 BLOCK_STATE_CALC_CRC_READ,
\r
299 // BLOCK_STATE_LOAD_FROM_NV,
\r
316 NvM_RequestResultType ErrorStatus; // Status from multi block requests i.e. Read/Write/CancelWrite-all
\r
317 } AdministrativeMultiBlockType;
\r
320 BlockStateType BlockState;
\r
321 uint8 DataIndex; // Selected data index if "Data Set" type
\r
322 boolean BlockWriteProtected; // Block write protected?
\r
323 NvM_RequestResultType ErrorStatus; // Status of block
\r
324 boolean BlockChanged; // Block changed?
\r
325 boolean BlockValid; // Block valid? (RAM block only?)
\r
326 uint8 NumberOfWriteFailed; // Current write retry cycle
\r
327 union Nvm_CRC RamCrc;
\r
328 union Nvm_CRC NvCrc; // The CRC of this block, read from NV
\r
329 void * savedDataPtr; //
\r
332 } AdministrativeBlockType;
\r
337 NVM_OP_WRITE_BLOCK,
\r
338 NVM_OP_RESTORE_BLOCK_DEFAULTS,
\r
343 #define NO_MULTIBLOCK 0
\r
344 #define MULTIBLOCK 1
\r
349 NvM_BlockIdType blockId;
\r
350 uint8 * dataPtr; /* Src or Dest ptr */
\r
355 /* ----------------------------[private function prototypes]-----------------*/
\r
356 /* ----------------------------[private variables]---------------------------*/
\r
358 static NvmStateType nvmState = NVM_UNINITIALIZED;
\r
361 #define RB_WAIT_READ 1
\r
362 #define RB_CALC_CHECKSUM 2
\r
364 static int nvmSubState = 0;
\r
365 //static int nvmSetNr;
\r
366 static AdministrativeBlockType AdminBlock[NVM_NUM_OF_NVRAM_BLOCKS];
\r
367 static AdministrativeMultiBlockType AdminMultiBlock;
\r
370 //static Nvm_QueueType nvmQueueImmData[NVM_SIZE_IMMEDIATE_JOB_QUEUE];
\r
371 static Nvm_QueueType nvmQueueData[NVM_SIZE_STANDARD_JOB_QUEUE];
\r
373 uint8 Nvm_WorkBuffer[200]; /* TODO */
\r
375 #if (NVM_SIZE_STANDARD_JOB_QUEUE == 0)
\r
376 #error NVM_SIZE_STANDARD_JOB_QUEUE have size 0
\r
380 CirqBufferType nvmQueue;
\r
383 /* ----------------------------[private functions]---------------------------*/
\r
385 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,
\r
386 AdministrativeBlockType *adminBlock,
\r
388 uint8 *sourceAddress);
\r
390 /* ----------------------------[public functions]----------------------------*/
\r
395 * This function needs to be implemented!
397 static void CalcCrc(void)
\r
399 // TODO: Calculate CRC
\r
403 boolean JobFinished;
\r
404 Std_ReturnType JobStatus;
\r
405 MemIf_JobResultType JobResult;
\r
406 const NvM_BlockDescriptorType * BlockDescriptor;
\r
407 AdministrativeBlockType * BlockAdmin;
\r
408 } MemIfJobAdminType;
\r
410 static MemIfJobAdminType MemIfJobAdmin = {
\r
411 .JobFinished = TRUE,
\r
413 .JobResult = MEMIF_JOB_OK,
\r
414 .BlockDescriptor = NULL,
\r
418 enum Nvm_MultiBlockReq {
\r
425 NvmStateType state;
\r
426 uint16 currBlockIndex; // Keeps track of next unfinished block
\r
427 NvM_RequestResultType PendingErrorStatus; // Status from multi block requests i.e. Read/Write/CancelWrite-all
\r
428 } AdminMultiReqType;
\r
430 static AdminMultiReqType AdminMultiReq;
\r
434 * Set the MemIf job as busy
436 static void SetMemifJobBusy()
\r
438 MemIfJobAdmin.JobFinished = FALSE;
\r
442 #if (NVM_POLLING_MODE == STD_ON)
\r
444 * Check if the MemIf job is finished
446 static boolean CheckMemIfJobFinished(void)
\r
448 MemIf_JobResultType jobResult;
\r
450 if (!MemIfJobAdmin.JobFinished) {
\r
451 jobResult = MemIf_GetJobResult(FIXME);
\r
453 if (jobResult == MEMIF_JOB_OK) {
\r
454 MemIfJobAdmin.JobFinished = TRUE;
\r
455 MemIfJobAdmin.JobStatus = E_OK;
\r
456 MemIfJobAdmin.JobResult = jobResult;
\r
457 } else if (jobResult != MEMIF_JOB_PENDING) {
\r
458 MemIfJobAdmin.JobFinished = TRUE;
\r
459 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
460 MemIfJobAdmin.JobResult = jobResult;
\r
464 return MemIfJobAdmin.JobFinished;
\r
468 * Check if the MemIf job is finished
\r
471 static boolean CheckMemIfJobFinished(void)
\r
473 return MemIfJobAdmin.JobFinished;
\r
480 * Abort the MemIf job with E_NOT_OK
\r
482 static void AbortMemIfJob(MemIf_JobResultType jobResult)
\r
484 MemIfJobAdmin.JobFinished = TRUE;
\r
485 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
486 MemIfJobAdmin.JobResult = jobResult;
\r
490 static boolean CheckJobFailed( void ) {
\r
491 return CheckMemIfJobFinished() && (MemIfJobAdmin.JobResult == MEMIF_JOB_FAILED);
\r
496 * Request a read of a block from MemIf
498 static void ReadBlock(const NvM_BlockDescriptorType *blockDescriptor,
\r
499 AdministrativeBlockType *adminBlock,
\r
501 uint16 blockOffset,
\r
502 uint8 *destAddress,
\r
505 Std_ReturnType returnCode;
\r
507 if (setNumber < blockDescriptor->NvBlockNum) {
\r
509 MemIfJobAdmin.BlockAdmin = adminBlock;
\r
510 MemIfJobAdmin.BlockDescriptor = blockDescriptor;
\r
511 returnCode = MemIf_Read(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), blockOffset, destAddress, length );
\r
512 if (returnCode != E_OK) {
\r
513 AbortMemIfJob(MEMIF_JOB_FAILED);
\r
515 } else if (setNumber < blockDescriptor->NvBlockNum + blockDescriptor->RomBlockNum) {
\r
516 // TODO: Read from ROM
\r
518 // Error: setNumber out of range
\r
519 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_READ_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);
\r
525 * Initiate the read all job
527 static void ReadAllInit(void)
\r
530 * Initiate the read all job
532 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
533 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
536 // Set status to pending in the administration blocks
\r
537 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING; /** @req 3.1.5/NVM304 */
\r
538 AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;
\r
539 AdminMultiReq.currBlockIndex = 0;
\r
541 for (i = 0; i < ( NVM_NUM_OF_NVRAM_BLOCKS ); i++) {
\r
542 if ((BlockDescriptorList->SelectBlockForReadall)
\r
543 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM345 */
\r
544 && ((!AdminBlockTable->BlockValid) // TODO: Check if this is to be done like this
\r
545 || (!AdminBlockTable->BlockChanged)) // TODO: Check if this is to be done like this
\r
548 VALIDATE_NO_RV(BlockDescriptorList->RamBlockDataAddress != NULL, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);
\r
549 VALIDATE_NO_RV(BlockDescriptorList->BlockManagementType != NVM_BLOCK_DATASET, NVM_READ_ALL_ID, NVM_E_WRONG_CONFIG);
\r
551 AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;
\r
552 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
554 AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED; /* @req 3.1.5/NVM287 */
\r
558 BlockDescriptorList++;
\r
563 static void writeCrcToBuffer( void *bufPtr,
\r
564 const NvM_BlockDescriptorType *bPtr,
\r
565 AdministrativeBlockType *admPtr )
\r
567 if( bPtr->BlockUseCrc ) {
\r
568 if(bPtr->BlockCRCType == NVM_CRC16) {
\r
569 WRITE16_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc16);
\r
571 WRITE32_NA(bufPtr + bPtr->NvBlockLength,admPtr->RamCrc.crc32);
\r
578 * Drive the read state-machine
\r
584 static void DriveBlock( const NvM_BlockDescriptorType *bPtr,
\r
585 AdministrativeBlockType *admPtr,
\r
588 boolean multiBlock,
\r
589 boolean restoreFromRom )
\r
591 bool blockDone = 0;
\r
592 static uint8 driveBlockCnt = 0;
\r
595 NVM_ASSERT( admPtr->ErrorStatus == NVM_REQ_PENDING);
\r
597 DEBUG_BLOCK_STATE("DriveBlock", BLOCK_NR_FROM_PTR(bPtr), admPtr->BlockState );
\r
599 switch (admPtr->BlockState) {
\r
600 case BLOCK_STATE_MEMIF_REQ:
\r
602 void *ramData = (dataPtr != NULL) ? dataPtr : bPtr->RamBlockDataAddress;
\r
604 admPtr->savedDataPtr = ramData;
\r
607 if( multiBlock && (dataPtr!=NULL)) {
\r
610 /* Copy to work buffer */
\r
611 memcpy( Nvm_WorkBuffer, ramData, bPtr->NvBlockLength );
\r
612 /* Add the CRC to write */
\r
613 writeCrcToBuffer(Nvm_WorkBuffer, bPtr, admPtr );
\r
614 WriteBlock(bPtr, admPtr, 0, Nvm_WorkBuffer);
\r
617 /* Read to workbuffer */
\r
618 if( bPtr->BlockUseCrc ) {
\r
619 crcLen = (bPtr->BlockCRCType == NVM_CRC16) ? 2: 4;
\r
622 if( restoreFromRom ) {
\r
623 NVM_ASSERT( bPtr->RomBlockDataAdress != NULL );
\r
624 /* No CRC on the ROM block */
\r
625 memcpy(ramData,bPtr->RomBlockDataAdress,bPtr->NvBlockLength);
\r
627 admPtr->ErrorStatus = NVM_REQ_OK;
\r
631 ReadBlock(bPtr, admPtr, 0, 0, bPtr->RamBlockDataAddress, bPtr->NvBlockLength+crcLen);
\r
635 admPtr->BlockState = BLOCK_STATE_MEMIF_PROCESS;
\r
639 case BLOCK_STATE_MEMIF_PROCESS:
\r
642 MemIf_JobResultType jobResult = MemIf_GetJobResult(FIXME);
\r
644 if( MEMIF_JOB_PENDING == jobResult ) {
\r
645 /* Keep on waiting */
\r
646 } else if( MEMIF_JOB_OK == jobResult ) {
\r
650 if( BLOCK_STATE_MEMIF_CRC_PROCESS == admPtr->BlockState ) {
\r
651 /* @req 3.1.5/NVM362 NvM_ReadAll*/
\r
652 DEBUG_CHECKSUM("RAM CRC", (bPtr->BlockCRCType == NVM_CRC16) ? admPtr->RamCrc.crc16 : admPtr->RamCrc.crc32);
\r
653 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;
\r
659 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
660 admPtr->ErrorStatus = NVM_REQ_OK;
\r
664 if( bPtr->BlockUseCrc ) {
\r
665 /* Explicit CRC calc (not dependent on NvmCalcRamBlockCrc) */
\r
666 /* @req 3.1.5/NVM212 NvM_WriteBlock */
\r
667 /* @req 3.1.5/NVM253 NvM_WriteAll */
\r
668 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
671 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
672 admPtr->ErrorStatus = NVM_REQ_OK;
\r
679 if( bPtr->BlockUseCrc ) {
\r
681 /* The read data is in the work buffer, read the CRC */
\r
682 if( bPtr->BlockCRCType == NVM_CRC16) {
\r
683 admPtr->NvCrc.crc16 = READ16_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );
\r
685 DEBUG_PRINTF(">> Nv CRC %04x\n",admPtr->NvCrc.crc16);
\r
686 admPtr->RamCrc.crc16 = admPtr->NvCrc.crc16; /* Set RAM CRC = NvRAM CRC */
\r
688 admPtr->NvCrc.crc32 = READ32_NA( Nvm_WorkBuffer + bPtr->NvBlockLength );
\r
690 DEBUG_PRINTF(">> Nv CRC %08x\n",admPtr->NvCrc.crc16);
\r
691 admPtr->RamCrc.crc32 = admPtr->NvCrc.crc32; /* Set RAM CRC = NvRAM CRC */
\r
694 memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength + crcLen );
\r
696 /* Check if we should re-calculate the RAM checksum now when it's in RAM */
\r
697 if( bPtr->CalcRamBlockCrc ) {
\r
698 /* This block want its RAM block CRC checked */
\r
699 DEBUG_PRINTF(">> Recalculation of RAM checksum \n",admPtr->NvCrc.crc16);
\r
700 assert( bPtr->BlockUseCrc == 1);
\r
701 admPtr->BlockState = BLOCK_STATE_CALC_CRC_READ;
\r
704 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
705 admPtr->ErrorStatus = NVM_REQ_OK;
\r
710 DEBUG_PRINTF(">> Block have NO CRC\n");
\r
712 memcpy(admPtr->savedDataPtr, Nvm_WorkBuffer, bPtr->NvBlockLength + crcLen );
\r
714 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
715 admPtr->ErrorStatus = NVM_REQ_OK;
\r
719 /* Copy from Workbuffer to the real buffer */
\r
724 /* Something failed */
\r
725 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;
\r
727 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ; /* TODO, this really true for all result below */
\r
729 switch( jobResult ) {
\r
730 case MEMIF_BLOCK_INVALID:
\r
731 /* @req 3.1.5/NVM342 */
\r
732 admPtr->ErrorStatus = NVM_REQ_NV_INVALIDATED;
\r
734 case MEMIF_BLOCK_INCONSISTENT:
\r
735 /* @req 3.1.5/NVM360 */
\r
736 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;
\r
737 DEM_REPORTERRORSTATUS(NVM_E_REQ_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);
\r
739 case MEMIF_JOB_FAILED:
\r
740 /* @req 3.1.5/NVM361 */
\r
741 admPtr->ErrorStatus = NVM_REQ_NOT_OK;
\r
742 DEM_REPORTERRORSTATUS(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);
\r
751 case BLOCK_STATE_CALC_CRC:
\r
755 case BLOCK_STATE_CALC_CRC_WRITE:
\r
759 NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );
\r
761 /* Calculate RAM CRC checksum */
\r
762 if( bPtr->BlockCRCType == NVM_CRC16 ) {
\r
764 crc16 = Crc_CalculateCRC16(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffff);
\r
765 DEBUG_CHECKSUM("RAM",crc16);
\r
767 /* Just save the checksum */
\r
768 admPtr->RamCrc.crc16 = crc16;
\r
771 /* NV CRC in admin block */
\r
772 if( admPtr->RamCrc.crc16 != crc16 ) {
\r
773 NVM_ASSERT(0); /* TODO: Corrupt CRC */
\r
775 admPtr->BlockChanged = BLOCK_STATE_MEMIF_REQ;
\r
779 /* Write the block */
\r
780 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
782 /* @req 3.1.5/NVM253 */
\r
783 crc32 = Crc_CalculateCRC32(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffffffffUL);
\r
784 if( crc32 != admPtr->RamCrc.crc32 ) {
\r
785 /* The checksum is wrong, something have written to the RAM area without
\r
786 * telling the NVM */
\r
789 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
791 admPtr->RamCrc.crc32 = crc32;
\r
795 case BLOCK_STATE_CALC_CRC_READ:
\r
797 NVM_ASSERT(bPtr->RamBlockDataAddress != NULL );
\r
798 NVM_ASSERT(bPtr->CalcRamBlockCrc == true );
\r
802 /* Calculate RAM CRC checksum */
\r
803 if( bPtr->BlockCRCType == NVM_CRC16 ) {
\r
806 crc16 = Crc_CalculateCRC16(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffff);
\r
807 DEBUG_CHECKSUM("RAM",crc16);
\r
809 /* NV CRC in admin block */
\r
811 if( driveBlockCnt == 1) {
\r
812 /* The previous "loop" we filled with default data */
\r
813 admPtr->RamCrc.crc16 = crc16;
\r
816 /* @req 3.1.5/NVM387 */
\r
817 if( admPtr->RamCrc.crc16 != crc16 ) {
\r
819 /* @req 3.1.5/NVM388 Nvm_ReadAll */
\r
823 * Corrupt CRC, what choices are there:
\r
824 * 1. Default data (=ROM) configured, just copy it.
\r
825 * 2. Data redundancy, get it.
\r
826 * 3. None of the above. Catastrophic failure. (NVM203)
\r
828 if( bPtr->RomBlockDataAdress != NULL ) {
\r
829 /* TODO: Restore block from ROM */
\r
832 /* @req 3.1.5/NVM469 */
\r
833 if( bPtr->InitBlockCallback != NULL ) {
\r
835 DEBUG_PRINTF("Filling block with default data\n");
\r
836 bPtr->InitBlockCallback();
\r
838 /* NVM085 is very vague here, but the says the application should be
\r
839 * able distinguish between when the init-callback have been called
\r
840 * or CRC is corrupt.
\r
843 /* The RAM CRC is at this point not calculated...so we must do this
\r
844 * .. so just stay in this state one more MainFunction.
\r
849 /* @req 3.1.5/NVM203 */
\r
850 DEM_REPORTERRORSTATUS(NVM_E_INTEGRITY_FAILED,DEM_EVENT_STATUS_FAILED);
\r
851 /* @req 3.1.5/NVM204 */
\r
852 admPtr->ErrorStatus = NVM_REQ_INTEGRITY_FAILED;
\r
853 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
858 DEBUG_CHECKSUM("RAM checksum ok with ",crc16);
\r
859 admPtr->ErrorStatus = NVM_REQ_OK;
\r
860 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
865 /* @req 3.1.5/NVM253 */
\r
866 /* Calculate CRC on the data we just read to RAM. Compare with CRC that is located in NV block */
\r
867 crc32 = Crc_CalculateCRC32(bPtr->RamBlockDataAddress,bPtr->NvBlockLength,0xffffffffUL);
\r
868 if( crc32 != admPtr->RamCrc.crc32 ) {
\r
869 NVM_ASSERT(0); /* TODO: Corrupt CRC */
\r
871 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
883 DEBUG_PRINTF("# Block Done\n");
\r
885 if( admPtr->ErrorStatus == NVM_REQ_OK ) {
\r
886 admPtr->BlockChanged = FALSE;
\r
887 admPtr->BlockValid = TRUE;
\r
891 /* @req 3.1.5/NVM281 */
\r
892 if( bPtr->SingleBlockCallback != NULL ) {
\r
893 bPtr->SingleBlockCallback(NVM_READ_ALL_ID, admPtr->ErrorStatus);
\r
897 AdminMultiReq.currBlockIndex++;
\r
898 if( AdminMultiReq.currBlockIndex >= NVM_NUM_OF_NVRAM_BLOCKS ) {
\r
899 AdminMultiReq.currBlockIndex = 0;
\r
901 /* @req 3.1.5/NVM301 */
\r
902 if( NVM_REQ_NOT_OK == AdminMultiReq.PendingErrorStatus ) {
\r
903 AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;
\r
905 AdminMultiBlock.ErrorStatus = NVM_REQ_OK;
\r
907 nvmState = NVM_IDLE;
\r
911 nvmState = NVM_IDLE;
\r
919 * Main function for the read all job
921 static void ReadAllMain(void)
\r
925 * 1. We process each block until it's finished
\r
926 * 2. We start to process a lot of blocks. The blocks may use different devices
\r
927 * and should be able to read a lot of them. This includes CRC.
\r
929 * 1) is much simpler and 2) probably much faster.
\r
930 * This implementation will use 1) since it's simpler and maximum time that is
\r
931 * spent in MainFunction() can be controlled much better.
\r
934 /* Skip blocks that are skipped */
\r
936 while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {
\r
937 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {
\r
938 AdminMultiReq.currBlockIndex++;
\r
944 DriveBlock( &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],
\r
945 &AdminBlock[AdminMultiReq.currBlockIndex],
\r
953 * Request writing of a block to MemIf
955 static void WriteBlock( const NvM_BlockDescriptorType *blockDescriptor,
\r
956 AdministrativeBlockType *adminBlock,
\r
958 uint8 *sourceAddress)
\r
960 Std_ReturnType returnCode;
\r
962 if (setNumber < blockDescriptor->NvBlockNum) {
\r
964 MemIfJobAdmin.BlockAdmin = adminBlock;
\r
965 MemIfJobAdmin.BlockDescriptor = blockDescriptor;
\r
966 returnCode = MemIf_Write(blockDescriptor->NvramDeviceId, BLOCK_BASE_AND_SET_TO_BLOCKNR(blockDescriptor->NvBlockBaseNumber, setNumber), sourceAddress);
\r
967 if (returnCode != E_OK) {
\r
968 AbortMemIfJob(MEMIF_JOB_FAILED);
\r
971 // Error: setNumber out of range
\r
972 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_LOC_WRITE_BLOCK_ID, NVM_PARAM_OUT_OF_RANGE);
\r
979 * Initiate the write all job
\r
981 static void WriteAllInit(void)
\r
983 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
984 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
987 // nvmState = NVM_WRITE_ALL_PROCESSING;
\r
988 AdminMultiReq.PendingErrorStatus = NVM_REQ_OK;
\r
989 AdminMultiReq.currBlockIndex = 0;
\r
991 for (i = 0; i < NVM_NUM_OF_NVRAM_BLOCKS; i++) {
\r
992 if ((BlockDescriptorList->RamBlockDataAddress != NULL)
\r
993 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM344 */
\r
994 && (AdminBlockTable->BlockValid) /** @req NVM682 */
\r
995 && (AdminBlockTable->BlockChanged) /** @req NVM682 */
\r
997 && (!AdminBlockTable->BlockWriteProtected)) /** @req NVM432 *//** @req NVM433 */
\r
999 AdminBlockTable->ErrorStatus = NVM_REQ_PENDING;
\r
1001 if (BlockDescriptorList->BlockUseCrc) {
\r
1002 AdminBlockTable->BlockState = BLOCK_STATE_CALC_CRC_WRITE; /** @req NVM253 */
\r
1004 AdminBlockTable->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1005 AdminBlockTable->NumberOfWriteFailed = 0;
\r
1008 AdminBlockTable->ErrorStatus = NVM_REQ_BLOCK_SKIPPED; /** @req NVM298 */
\r
1011 AdminBlockTable++;
\r
1012 BlockDescriptorList++;
\r
1019 * Main function for the write all job
\r
1021 static void WriteAllMain(void)
\r
1024 while ( (AdminBlock[AdminMultiReq.currBlockIndex].ErrorStatus == NVM_REQ_BLOCK_SKIPPED) ) {
\r
1025 if( (AdminMultiReq.currBlockIndex < NVM_NUM_OF_NVRAM_BLOCKS) ) {
\r
1026 AdminMultiReq.currBlockIndex++;
\r
1032 DriveBlock( &NvM_Config.BlockDescriptor[AdminMultiReq.currBlockIndex],
\r
1033 &AdminBlock[AdminMultiReq.currBlockIndex],
\r
1043 * Handles the result of one MemIf block write
\r
1045 static void WriteAllCheckWriteResult(void)
\r
1047 if (MemIfJobAdmin.JobStatus == E_OK) {
\r
1048 // TODO: Check if redundant block shall be written NVM337
\r
1050 if (MemIfJobAdmin.BlockDescriptor->WriteBlockOnce) {
\r
1051 MemIfJobAdmin.BlockAdmin->BlockWriteProtected = TRUE; /** @req NVM329 */
\r
1053 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1054 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_OK;
\r
1056 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {
\r
1057 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);
\r
1060 MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed++;
\r
1061 if (MemIfJobAdmin.BlockAdmin->NumberOfWriteFailed > NVM_MAX_NUMBER_OF_WRITE_RETRIES) {
\r
1062 // TODO: Check if redundant block shall be written NVM337
\r
1064 // Write has failed
\r
1065 AdminMultiReq.PendingErrorStatus = NVM_REQ_NOT_OK;
\r
1067 MemIfJobAdmin.BlockAdmin->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1068 MemIfJobAdmin.BlockAdmin->ErrorStatus = NVM_REQ_NOT_OK; /** @req NVM296 */
\r
1069 #if defined(USE_DEM)
\r
1070 Dem_ReportErrorStatus(NVM_E_REQ_FAILED,DEM_EVENT_STATUS_FAILED);
\r
1073 if (MemIfJobAdmin.BlockDescriptor->SingleBlockCallback != NULL) {
\r
1074 (void)MemIfJobAdmin.BlockDescriptor->SingleBlockCallback(NVM_SERVICE_ID, MemIfJobAdmin.BlockAdmin->ErrorStatus);
\r
1078 nvmState = NVM_WRITE_ALL_PROCESSING;
\r
1084 /***************************************
\r
1085 * External accessible functions *
\r
1086 ***************************************/
\r
1088 * Procedure: NvM_Init
\r
1091 void NvM_Init(void)
\r
1093 /** @req NVM399 *//** @req NVM193 */
\r
1094 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
1095 AdministrativeBlockType *AdminBlockTable = AdminBlock;
\r
1099 CirqBuff_Init(&nvmQueue,nvmQueueData,sizeof(nvmQueueData),sizeof(Nvm_QueueType));
\r
1101 // Initiate the administration blocks
\r
1102 for (i = 0; i< NVM_NUM_OF_NVRAM_BLOCKS; i++) {
\r
1103 if (BlockDescriptorList->BlockManagementType == NVM_BLOCK_DATASET) {
\r
1104 AdminBlockTable->DataIndex = 0; /** @req NVM192 */
\r
1106 AdminBlockTable->BlockWriteProtected = BlockDescriptorList->BlockWriteProt;
\r
1107 AdminBlockTable->ErrorStatus = NVM_REQ_NOT_OK;
\r
1108 AdminBlockTable->BlockChanged = FALSE;
\r
1109 AdminBlockTable->BlockValid = FALSE;
\r
1110 AdminBlockTable->NumberOfWriteFailed = 0;
\r
1112 AdminBlockTable++;
\r
1113 BlockDescriptorList++;
\r
1116 AdminMultiBlock.ErrorStatus = NVM_REQ_NOT_OK;
\r
1118 // Set status to initialized
\r
1119 nvmState = NVM_IDLE; /** @req 3.1.5/NVM399 */
\r
1124 * Procedure: NvM_ReadAll
\r
1127 void NvM_ReadAll(void)
\r
1129 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);
\r
1131 NVM_ASSERT(nvmState == NVM_IDLE);
\r
1133 AdminMultiReq.state = NVM_READ_ALL;
\r
1134 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;
\r
1140 * Procedure: NvM_WriteAll
\r
1143 void NvM_WriteAll(void)
\r
1145 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_READ_ALL_ID, NVM_E_NOT_INITIALIZED);
\r
1147 NVM_ASSERT(nvmState == NVM_IDLE);
\r
1149 AdminMultiReq.state = NVM_WRITE_ALL;
\r
1150 AdminMultiBlock.ErrorStatus = NVM_REQ_PENDING;
\r
1155 * Procedure: NvM_CancelWriteAll
\r
1158 void NvM_CancelWriteAll(void)
\r
1165 * Procedure: NvM_GetErrorStatus
\r
1168 void NvM_GetErrorStatus(NvM_BlockIdType blockId, uint8 *requestResultPtr)
\r
1170 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_GET_ERROR_STATUS_ID, NVM_E_NOT_INITIALIZED);
\r
1171 VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_GET_ERROR_STATUS_ID, NVM_E_PARAM_BLOCK_ID);
\r
1173 if (blockId == 0) {
\r
1175 *requestResultPtr = AdminMultiBlock.ErrorStatus;
\r
1176 } else if (blockId == 1) {
\r
1178 *requestResultPtr = NVM_REQ_OK;
\r
1180 *requestResultPtr = AdminBlock[blockId-1].ErrorStatus;
\r
1186 #if (NVM_SET_RAM_BLOCK_STATUS_API == STD_ON) /** @req NVM408 */
\r
1188 * Procedure: Nvm_SetRamBlockStatus
\r
1191 void NvM_SetRamBlockStatus(NvM_BlockIdType blockId, boolean blockChanged)
\r
1193 const NvM_BlockDescriptorType *BlockDescriptorList = NvM_Config.BlockDescriptor;
\r
1195 VALIDATE_NO_RV(nvmState != NVM_UNINITIALIZED, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_NOT_INITIALIZED); /** @req NVM497 */
\r
1196 VALIDATE_NO_RV(blockId < NVM_NUM_OF_NVRAM_BLOCKS+1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);
\r
1197 VALIDATE_NO_RV(blockId > 1, NVM_SET_RAM_BLOCK_STATUS_ID, NVM_E_PARAM_BLOCK_ID);
\r
1199 if (BlockDescriptorList[blockId-1].RamBlockDataAddress != NULL) { /** @req NVM240 */
\r
1200 if (blockChanged) {
\r
1201 AdminBlock[blockId-1].BlockChanged = TRUE; /** @req NVM406 */
\r
1202 AdminBlock[blockId-1].BlockValid = TRUE; /** @req NVM241 */
\r
1203 if (BlockDescriptorList[blockId-1].BlockUseCrc) {
\r
1204 AdminBlock[blockId-1].BlockState = BLOCK_STATE_CALC_CRC; /** @req NVM121 */
\r
1207 AdminBlock[blockId-1].BlockChanged = FALSE; /** @req NVM405 */
\r
1208 AdminBlock[blockId-1].BlockValid = FALSE;
\r
1209 } // else blockChanged
\r
1210 } // if permanent block
\r
1215 void NvM_SetBlockLockStatus( NvM_BlockIdType blockId, boolean blockLocked ) {
\r
1217 (void)blockLocked;
\r
1222 * Restore default data to its corresponding RAM block.
\r
1224 * @param BlockId NVRAM block identifier.
1225 * @param NvM_DestPtr Pointer to the RAM block
1228 Std_ReturnType NvM_RestoreBlockDefaults( NvM_BlockIdType blockId, uint8* NvM_DestPtr )
\r
1230 /* !req 3.1.5/NVM012 */ /* !req 3.1.5/NVM267 */ /* !req 3.1.5/NVM266 */
\r
1231 /* !req 3.1.5/NVM353 */ /* !req 3.1.5/NVM435 */ /* !req 3.1.5/NVM436 */ /* !req 3.1.5/NVM227 */
\r
1232 /* !req 3.1.5/NVM228 */ /* !req 3.1.5/NVM229 */ /* !req 3.1.5/NVM413 */
\r
1234 const NvM_BlockDescriptorType * bPtr;
\r
1235 AdministrativeBlockType * admPtr;
\r
1236 Nvm_QueueType qEntry;
\r
1239 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1241 /* @req 3.1.5/NVM618 */
\r
1242 VALIDATE_RV( blockId <= NVM_NUM_OF_NVRAM_BLOCKS,
\r
1243 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );
\r
1245 bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1246 admPtr = &AdminBlock[blockId-1];
\r
1248 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1249 if( (NvM_DestPtr == NULL) && ( bPtr->RamBlockDataAddress == NULL ) ) {
\r
1250 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */
\r
1251 NVM_ASSERT(0); // TODO: See NVM210, DET error
\r
1255 /* @req 3.1.5/NVM195 */
\r
1256 qEntry.blockId = blockId;
\r
1257 qEntry.op = NVM_RESTORE_BLOCK_DEFAULTS;
\r
1258 qEntry.blockId = blockId;
\r
1259 qEntry.dataPtr = (uint8_t *)NvM_DestPtr;
\r
1260 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1261 NVM_ASSERT(rv == 0 );
\r
1263 /* @req 3.1.5/NVM620 */
\r
1264 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1266 /* req 3.1.5/NVM185 */
\r
1267 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1269 if( bPtr->BlockUseCrc) {
\r
1270 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
1272 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1280 * Service to copy the data NV block to the RAM block
\r
1282 * @param blockId 0 and 1 reserved. The block ID are sequential.
1288 Std_ReturnType NvM_ReadBlock( NvM_BlockIdType blockId, uint8* NvM_DstPtr )
\r
1290 /* !req 3.1.5/NVM010 */
\r
1293 /* !req 3.1.5/NVM278 */
\r
1294 /* !req 3.1.5/NVM340 */
\r
1295 /* !req 3.1.5/NVM354 */
\r
1296 /* !req 3.1.5/NVM200 */
\r
1297 /* !req 3.1.5/NVM366 */
\r
1298 /* !req 3.1.5/NVM206 */
\r
1299 /* !req 3.1.5/NVM341 */
\r
1300 /* !req 3.1.5/NVM358 */
\r
1301 /* !req 3.1.5/NVM359 */
\r
1302 /* !req 3.1.5/NVM279 */
\r
1303 /* !req 3.1.5/NVM316 */
\r
1304 /* !req 3.1.5/NVM317 */
\r
1305 /* !req 3.1.5/NVM201 */
\r
1306 /* !req 3.1.5/NVM202 */
\r
1307 /* !req 3.1.5/NVM203 */
\r
1308 /* !req 3.1.5/NVM204 */
\r
1309 /* !req 3.1.5/NVM409 */
\r
1315 * |5 4 3 2 1 0 9 8|7 6 5 4 3 2 1 0|
\r
1316 * b b b b b b b b b b d d d d d d
\r
1318 * Here we have 10 bits for block id, 16-5 for DataSetSelection bits.
\r
1319 * - 2^10, 1024 blocks
\r
1320 * - 64 datasets for each NVRAM block
\r
1322 * How are the block numbers done in EA? Assume virtual page=8
\r
1333 * How can NVM/NvmNvBlockLength and EA/EaBlockSize be different?
\r
1334 * It seems that EA/FEE does not care about that logical block 2 above is
\r
1338 Nvm_QueueType qEntry;
\r
1341 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1342 if( (NvM_DstPtr == NULL) && ( NvM_Config.BlockDescriptor[blockId-1].RamBlockDataAddress == NULL ) ) {
\r
1343 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */
\r
1347 /* @req 3.1.5/NVM195 */
\r
1348 qEntry.blockId = blockId;
\r
1349 qEntry.op = NVM_READ_BLOCK;
\r
1350 qEntry.blockId = blockId;
\r
1351 qEntry.dataPtr = NvM_DstPtr;
\r
1352 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1353 NVM_ASSERT(rv == 0 );
\r
1355 /* @req 3.1.5/NVM615 */
\r
1356 VALIDATE_RV( (AdminBlock[blockId-1].ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1358 /* req 3.1.5/NVM185 */
\r
1359 AdminBlock[blockId-1].ErrorStatus = NVM_REQ_PENDING;
\r
1366 * Service to copy a RAM block to its correspnding NVRAM block
\r
1372 Std_ReturnType NvM_WriteBlock( NvM_BlockIdType blockId, const uint8* NvM_SrcPtr ) {
\r
1374 const NvM_BlockDescriptorType * bPtr;
\r
1375 AdministrativeBlockType * admPtr;
\r
1376 Nvm_QueueType qEntry;
\r
1379 NVM_ASSERT( blockId >= 2 ); /* No support for lower numbers, yet */
\r
1381 /* @req 3.1.5/NVM618 */
\r
1382 VALIDATE_RV( blockId <= NVM_NUM_OF_NVRAM_BLOCKS,
\r
1383 NVM_WRITE_BLOCK_ID,NVM_E_PARAM_BLOCK_ID,E_NOT_OK );
\r
1385 bPtr = &NvM_Config.BlockDescriptor[blockId-1];
\r
1386 admPtr = &AdminBlock[blockId-1];
\r
1388 /** @req 3.1.5/NVM196 */ /** @req 3.1.5/NVM278 */
\r
1389 if( (NvM_SrcPtr == NULL) && ( bPtr->RamBlockDataAddress == NULL ) ) {
\r
1390 /* It must be a permanent RAM block but no RamBlockDataAddress -> error */
\r
1391 NVM_ASSERT(0); // TODO: See NVM210, DET error
\r
1395 /* @req 3.1.5/NVM195 */
\r
1396 qEntry.blockId = blockId;
\r
1397 qEntry.op = NVM_WRITE_BLOCK;
\r
1398 qEntry.blockId = blockId;
\r
1399 qEntry.dataPtr = (uint8_t *)NvM_SrcPtr;
\r
1400 rv = CirqBuffPush(&nvmQueue,&qEntry);
\r
1401 NVM_ASSERT(rv == 0 );
\r
1403 /* @req 3.1.5/NVM620 */
\r
1404 VALIDATE_RV( (admPtr->ErrorStatus != NVM_REQ_PENDING), 0, NVM_E_BLOCK_PENDING , E_NOT_OK );
\r
1406 /* req 3.1.5/NVM185 */
\r
1407 admPtr->ErrorStatus = NVM_REQ_PENDING;
\r
1409 if( bPtr->BlockUseCrc) {
\r
1410 admPtr->BlockState = BLOCK_STATE_CALC_CRC_WRITE;
\r
1412 admPtr->BlockState = BLOCK_STATE_MEMIF_REQ;
\r
1419 /* Missing from Class 2
\r
1420 * - NvM_CancelWriteAll
\r
1421 * - NvM_SetDataIndex
\r
1422 * - NvM_GetDataIndex
\r
1429 const NvM_BlockDescriptorType * nvmBlock;
\r
1430 AdministrativeBlockType *admBlock;
\r
1435 void NvM_MainFunction(void)
\r
1438 Nvm_QueueType qEntry;
\r
1439 const NvM_BlockDescriptorType * bList = NvM_Config.BlockDescriptor;
\r
1440 // const NvM_BlockDescriptorType * currBlock;
\r
1441 // static uint32 crc32;
\r
1442 // static uint32 crc32Left;
\r
1444 /* Check for new requested state changes */
\r
1445 if( nvmState == NVM_IDLE ) {
\r
1446 rv = CirqBuffPop( &nvmQueue, &qEntry );
\r
1448 /* Found something in buffer */
\r
1449 nvmState = qEntry.op;
\r
1450 nvmBlock = &bList[qEntry.blockId-1];
\r
1451 admBlock = &AdminBlock[qEntry.blockId-1];
\r
1453 admBlock->ErrorStatus = NVM_REQ_PENDING;
\r
1454 DEBUG_PRINTF("### Popped Single FIFO \n");
\r
1455 DEBUG_PRINTF("### CRC On:%d Ram:%d Type:%d\n",nvmBlock->BlockUseCrc, nvmBlock->CalcRamBlockCrc, nvmBlock->BlockCRCType );
\r
1456 DEBUG_PRINTF("### RAM:%x ROM:%x\n", nvmBlock->RamBlockDataAddress, nvmBlock->RomBlockDataAdress );
\r
1458 /* Check multiblock req */
\r
1459 if( AdminMultiReq.state != NVM_UNINITIALIZED ) {
\r
1460 nvmState = AdminMultiReq.state ;
\r
1464 AdminMultiReq.state = NVM_UNINITIALIZED;
\r
1466 DEBUG_PRINTF("### Popped MULTI\n");
\r
1471 DEBUG_STATE(nvmState,nvmSubState);
\r
1473 switch (nvmState) {
\r
1474 case NVM_UNINITIALIZED:
\r
1482 case NVM_READ_ALL:
\r
1483 if( NS_INIT == nvmSubState ) {
\r
1485 nvmSubState = NS_PROSSING;
\r
1486 } else if( NS_PROSSING == nvmSubState ) {
\r
1491 case NVM_READ_BLOCK:
\r
1492 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, false );
\r
1495 case NVM_RESTORE_BLOCK_DEFAULTS:
\r
1496 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, false, false, true );
\r
1499 case NVM_WRITE_BLOCK:
\r
1500 DriveBlock(nvmBlock,admBlock, qEntry.dataPtr, true /*write*/, false , false );
\r
1503 case NVM_WRITE_ALL:
\r
1504 if( NS_INIT == nvmSubState ) {
\r
1506 nvmSubState = NS_PROSSING;
\r
1507 } else if( NS_PROSSING == nvmSubState ) {
\r
1513 DET_REPORTERROR(MODULE_ID_NVM, 0, NVM_MAIN_FUNCTION_ID, NVM_UNEXPECTED_STATE);
\r
1519 /***************************************
\r
1520 * Call-back notifications functions *
\r
1521 ***************************************/
\r
1522 #if (NVM_POLLING_MODE == STD_OFF)
\r
1524 * Procedure: NvM_JobEndNotification
\r
1527 void NvM_JobEndNotification(void)
\r
1529 MemIfJobAdmin.JobFinished = TRUE;
\r
1530 MemIfJobAdmin.JobStatus = E_OK;
\r
1531 MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);
\r
1535 * Procedure: NvM_JobErrorNotification
\r
1538 void NvM_JobErrorNotification(void)
\r
1540 MemIfJobAdmin.JobFinished = TRUE;
\r
1541 MemIfJobAdmin.JobStatus = E_NOT_OK;
\r
1542 MemIfJobAdmin.JobResult = MemIf_GetJobResult(FIXME);
\r