/********************************************************************************************************************** * FILE DESCRIPTION * -----------------------------------------------------------------------------------------------------------------*/ /** \file WrapNv.c * \brief Wrapper for NV-memory access * ------------------------------------------------------------------------------------------------------------------- * COPYRIGHT * ------------------------------------------------------------------------------------------------------------------- * \par Copyright * \verbatim * Copyright (c) 2024 by Vector Informatik GmbH. All rights reserved. * * This software is copyright protected and proprietary to Vector Informatik GmbH. * Vector Informatik GmbH grants to you only those rights as set out in the license conditions. * All other rights remain with Vector Informatik GmbH. * \endverbatim */ /*********************************************************************************************************************/ /********************************************************************************************************************** * REVISION HISTORY * ------------------------------------------------------------------------------------------------------------------- * Refer to the module's header file. *********************************************************************************************************************/ #define WRAPNV_SOURCE /********************************************************************************************************************** * INCLUDES *********************************************************************************************************************/ #include "WrapNv.h" #if defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) || \ defined( WRAPNV_USECASE_NVM ) /* Critical sections handled by SchM */ # include "SchM_WrapNv.h" # if (WRAPNV_DEV_ERROR_REPORT == STD_ON) # include "Det.h" # endif /* WRAPNV_DEV_ERROR_REPORT */ #endif /* WRAPNV_USECASE_ */ #if defined( WRAPNV_USECASE_DRVEEP ) # include "EepInc.h" #endif #if defined( WRAPNV_USECASE_EEPM ) # include "EepMgr_Inc.h" #endif /*********************************************************************************************************************** * VERSION **********************************************************************************************************************/ #if ( SYSSERVICE_WRAPPERNV_VERSION != 0x0402u ) || \ ( SYSSERVICE_WRAPPERNV_RELEASE_VERSION != 0x00u ) # error "Error in WrapNv.c: Source and header file are inconsistent!" #endif /********************************************************************************************************************** * DEFINES *********************************************************************************************************************/ #if defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) || \ defined( WRAPNV_USECASE_NVM ) /** Default value, in case block/data is not available and explicit default value not given */ # if !defined( WRAPNV_DEFAULT_VALUE ) # define WRAPNV_DEFAULT_VALUE 0xFFu # endif /* WRAPNV_DEFAULT_VALUE */ # if !defined( STATIC ) # define STATIC static # endif # if (WRAPNV_DEV_ERROR_REPORT == STD_ON) /* PRQA S 3453 1 */ /* MD_MSR_19.7 */ # define WrapNv_Det_ReportError(ApiId, ErrorCode) (void)Det_ReportError(WRAPNV_MODULE_ID, WRAPNV_INSTANCE_ID, (ApiId), (ErrorCode)) # endif # define WrapNv_EnterCritical() SchM_Enter_WrapNv_WRAPNV_EXCLUSIVE_AREA_0() # define WrapNv_LeaveCritical() SchM_Exit_WrapNv_WRAPNV_EXCLUSIVE_AREA_0() /*********************************************************************************************************************** * TYPEDEFS **********************************************************************************************************************/ /** Specifies the current state of the operation */ typedef enum { WRAPNV_STATE_IDLE = 0u, /** No operation in progress */ WRAPNV_STATE_READ_INIT, /** Initialize read operation */ WRAPNV_STATE_READ_PENDING, /** Wait until read operation has finished */ WRAPNV_STATE_READ_MODIFY_INIT, /** Initialize read operation for read-modify-write operation */ WRAPNV_STATE_READ_MODIFY_PENDING, /** Wait until read operation has finished */ WRAPNV_STATE_MODIFY_DATA, /** Modify data for write operation */ WRAPNV_STATE_WRITE_INIT, /** Initialize write operation */ WRAPNV_STATE_WRITE_PENDING, /** Wait until write operation has finished */ WRAPNV_STATE_DELETE_INIT, /** Initialize delete operation */ WRAPNV_STATE_DELETE_PENDING, /** Wait until delete operation has finished */ WRAPNV_STATE_CANCEL /** Process cancel operation */ } tWrapNvState; /** Defines the current operation which is processed by the WrapNv */ typedef enum { WRAPNV_OPERATION_IDLE = 0u, /** No operation in progress */ WRAPNV_OPERATION_READ, /** Read operation in progress */ WRAPNV_OPERATION_READPARTIAL, /** ReadPartial operation in progress */ WRAPNV_OPERATION_WRITE, /** Write operation in progress */ WRAPNV_OPERATION_DELETE /** Delete operation in progress */ } tWrapNvOperation; /*********************************************************************************************************************** * LOCAL DATA **********************************************************************************************************************/ # define WRAPNV_START_SEC_VAR_NOINIT_UNSPECIFIED # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ /* NV block specific */ STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvRecordNumber; /**< Record ID */ STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvBlockNumber; /**< Number of block */ STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvBlockDataset; /**< Dataset of block */ STATIC VAR(uint8, WRAPNV_VAR_NOINIT) gWrapNvBlockBuffer[WRAPNV_MAX_BLOCK_LENGTH]; /**< Data buffer for whole NV block */ /* PRQA S 3218 */ /* MD_WrapNv_3218 */ STATIC P2CONST(uint8, AUTOMATIC, WRAPNV_CONST) gWrapNvBlockDefaultValue; /**< Default value of a NV block, if invalid/not present */ # if defined( WRAPNV_USECASE_NVM ) STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvBlockMaxDataset; /**< Maximum number of datasets of the block */ # endif /* WRAPNV_USECASE_NVM */ /* Data specific */ STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvReadDataOffset; /**< Offset in NV block to the data */ STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvReadDataLength; /**< Length of data inside the NV block */ STATIC VAR(tWrapNvRamData, WRAPNV_VAR_NOINIT) gWrapNvReadDataBuffer; /**< Input buffer from upper layer */ STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvWriteDataOffset; /**< Offset in NV block to the data */ STATIC VAR(uint16, WRAPNV_VAR_NOINIT) gWrapNvWriteDataLength; /**< Length of data inside the NV block */ STATIC VAR(tWrapNvConstData, WRAPNV_VAR_NOINIT) gWrapNvWriteDataBuffer; /**< Write buffer from upper layer */ STATIC VAR(tWrapNvRamData, WRAPNV_VAR_NOINIT) gWrapNvBlockAccessBuffer; /**< Buffer used to read and/or write data from/to the NV block */ STATIC VAR(tWrapNvState, WRAPNV_VAR_NOINIT) gWrapNvCurrentState; /**< Current state of NV access (read/modify/write) */ STATIC VAR(tWrapNvOperation, WRAPNV_VAR_NOINIT) gWrapNvCurrentOperation; /**< Current operation */ # define WRAPNV_STOP_SEC_VAR_NOINIT_UNSPECIFIED # include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ #endif /* WRAPNV_USECASE_* */ /*********************************************************************************************************************** * LOCAL FUNCTION PROTOTYPES **********************************************************************************************************************/ #define WRAPNV_START_SEC_CODE #include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ #if defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) || \ defined( WRAPNV_USECASE_NVM ) STATIC FUNC(MemIf_StatusType, WRAPNV_CODE) WrapNv_GetStatus( void ); STATIC FUNC(MemIf_JobResultType, WRAPNV_CODE) WrapNv_GetJobResult( void ); # if defined( WRAPNV_USECASE_NVM ) STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_SetDataIndex( void ); # endif /* WRAPNV_USECASE_NVM */ STATIC FUNC(void, WRAPNV_CODE) WrapNv_InitInternal( void ); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Cancel( void ); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Read( uint16 id, uint16 idx, tWrapNvRamData buffer, tWrapNvAccessType access); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadAsyncInternal(uint16 id, uint16 idx, tWrapNvRamData buffer, tWrapNvOpStatus opStatus, tWrapNvAccessType access); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartial( uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length, tWrapNvAccessType access); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartialAsyncInternal(uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length, tWrapNvOpStatus opStatus, tWrapNvAccessType access); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Delete( uint16 id, uint16 idx ); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Write( uint16 id, uint16 idx, tWrapNvConstData buffer, tWrapNvAccessType access ); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_WriteAsyncInternal(uint16 id, uint16 idx, tWrapNvConstData buffer, tWrapNvOpStatus opStatus, tWrapNvAccessType access); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_MainFunction( void ); STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_PollMainFunctions( void ); /*********************************************************************************************************************** * LOCAL FUNCTIONS **********************************************************************************************************************/ /*********************************************************************************************************************** * WrapNv_GetStatus **********************************************************************************************************************/ /*! \brief Checks the process state of the NV * \return MEMIF_IDLE in case job is finished (failed or OK state), otherwise MEMIF_BUSY **********************************************************************************************************************/ STATIC FUNC(MemIf_StatusType, WRAPNV_CODE) WrapNv_GetStatus( void ) { MemIf_StatusType result; # if defined( WRAPNV_USECASE_NVM ) NvM_RequestResultType nvmStatus; if (E_OK == NvM_GetErrorStatus(gWrapNvBlockNumber, &nvmStatus)) { /* Check if NVM currently processes a request */ if (NVM_REQ_PENDING == nvmStatus) { result = MEMIF_BUSY; } else { result = MEMIF_IDLE; } } else { result = MEMIF_IDLE; } # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) result = WrapNv_MemDrvGetStatus(); # endif /* WRAPNV_USECASE_* */ return result; } /*********************************************************************************************************************** * WrapNv_GetJobResult **********************************************************************************************************************/ /*! \brief Checks the result of the last request * \pre WrapNv_GetStatus has been called and returned MEMIF_IDLE * \return return MEMIF_JOB_OK in case data could be read successfully * MEMIF_BLOCK_INCONSISTENT in case data could not be read (e.g. data are corrupt) * MEMIF_INVALID in case the block has been invalidated previously * MEMIF_JOB_FAILED otherwise **********************************************************************************************************************/ STATIC FUNC(MemIf_JobResultType, WRAPNV_CODE) WrapNv_GetJobResult( void ) { MemIf_JobResultType result; # if defined( WRAPNV_USECASE_NVM ) NvM_RequestResultType nvmStatus; if (E_OK == NvM_GetErrorStatus(gWrapNvBlockNumber, &nvmStatus)) { /* Remap NVM status to MEMIF status */ switch (nvmStatus) { case NVM_REQ_OK: { result = MEMIF_JOB_OK; break; } case NVM_REQ_NOT_OK: { result = MEMIF_JOB_FAILED; break; } case NVM_REQ_INTEGRITY_FAILED: { result = MEMIF_BLOCK_INCONSISTENT; break; } case NVM_REQ_NV_INVALIDATED: { result = MEMIF_BLOCK_INVALID; break; } default: { /* Unknown state */ result = MEMIF_JOB_FAILED; break; } } } else { result = MEMIF_JOB_FAILED; } # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) result = WrapNv_MemDrvGetJobResult(); # endif /* WRAPNV_USECASE_* */ return result; } # if defined( WRAPNV_USECASE_NVM ) /*********************************************************************************************************************** * WrapNv_SetDataIndex **********************************************************************************************************************/ /*! \brief Sets the data index (dataset) of current block * \pre Global variables (gWrapNvBlockMaxDataset, gWrapNvBlockNumber and gWrapNvBlockDataset) have to be initialized * \return return WRAPNV_E_OK in case data index could be set or if it must not be set at all (e.g. only one * dataset configured/available) * WRAPNV_E_NOT_OK in case NvM couldn't set data data index **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_SetDataIndex( void ) { WrapNv_ReturnType result; /* Initialize variables */ result = WRAPNV_E_OK; /* At least two datasets must be configured/available to set the data index for the NVM */ if (gWrapNvBlockMaxDataset > 1u) { if (E_OK != NvM_SetDataIndex(gWrapNvBlockNumber, (uint8)(gWrapNvBlockDataset & 0xFFu))) { result = WRAPNV_E_NOT_OK; } } return result; } # endif /* WRAPNV_USECASE_NVM */ /*********************************************************************************************************************** * WrapNv_InitInternal **********************************************************************************************************************/ /*! \brief Initializes internal states/variables **********************************************************************************************************************/ STATIC FUNC(void, WRAPNV_CODE) WrapNv_InitInternal( void ) { /* Initialize state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; gWrapNvCurrentOperation = WRAPNV_OPERATION_IDLE; /* Initialize variables */ gWrapNvRecordNumber = 0xFFFFu; gWrapNvBlockDataset = 0xFFFFu; gWrapNvReadDataOffset = 0xFFFFu; gWrapNvReadDataLength = 0xFFFFu; gWrapNvReadDataBuffer = NULL_PTR; gWrapNvWriteDataBuffer = NULL_PTR; } /*********************************************************************************************************************** * WrapNv_Cancel **********************************************************************************************************************/ /*! \brief Cancels current pending job * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Cancel( void ) { WrapNv_ReturnType result; /* Setup the cancel request */ gWrapNvCurrentState = WRAPNV_STATE_CANCEL; result = WrapNv_MainFunction(); /* Reset internal states */ WrapNv_InitInternal(); return result; } /*********************************************************************************************************************** * WrapNv_Read **********************************************************************************************************************/ /*! \brief Initialize the read operation * \param[in] id Id of record * \param[in] idx Dataset of block * \param[out] buffer Pointer to data buffer * \param[in] access Type of access * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Read( uint16 id, uint16 idx, tWrapNvRamData buffer, tWrapNvAccessType access) { WrapNv_ReturnType result; uint8 errorId; P2CONST(tWrapNvRecordTbl, AUTOMATIC, WRAPNV_CONST) localRecordPtr; P2CONST(tWrapNvBlockTbl, AUTOMATIC, WRAPNV_CONST) localBlockPtr; /* Initialize variable */ result = WRAPNV_E_NOT_OK; errorId = WRAPNV_E_NO_ERROR; if (WRAPNV_STATE_IDLE != gWrapNvCurrentState) { errorId = WRAPNV_E_NOT_IDLE; } /* Check if ID is valid */ else if (id >= kWrapNvNrOfRecord) { errorId = WRAPNV_E_PARAM_ID; } /* Check if dataset is valid */ else if ( (idx >= kWrapNvRecordTbl[id].recordBlockPtr->blockMaxDatasets) || (idx > 0xFFu)) { errorId = WRAPNV_E_PARAM_DATASET; } else { localRecordPtr = &kWrapNvRecordTbl[id]; localBlockPtr = localRecordPtr->recordBlockPtr; gWrapNvRecordNumber = id; gWrapNvBlockNumber = localBlockPtr->blockNumber; gWrapNvBlockDataset = idx; # if defined( WRAPNV_USECASE_NVM ) gWrapNvBlockMaxDataset = localBlockPtr->blockMaxDatasets; # endif /* WRAPNV_USECASE_NVM */ gWrapNvBlockDefaultValue = localBlockPtr->blockDefaultValue; if (access == WRAPNV_ACCESS_DATAELEMENT) { gWrapNvReadDataOffset = localRecordPtr->recordDataOffset; gWrapNvReadDataLength = localRecordPtr->recordDataLength; } else { gWrapNvReadDataOffset = 0u; gWrapNvReadDataLength = localBlockPtr->blockLength; } gWrapNvReadDataBuffer = buffer; gWrapNvWriteDataOffset = 0u; gWrapNvWriteDataLength = 0u; gWrapNvWriteDataBuffer = NULL_PTR; # if defined( WRAPNV_USECASE_NVM ) gWrapNvBlockAccessBuffer = gWrapNvBlockBuffer; # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) gWrapNvBlockAccessBuffer = NULL_PTR; # endif /* WRAPNV_USECASE_* */ gWrapNvCurrentState = WRAPNV_STATE_READ_INIT; result = WrapNv_MainFunction(); } # if (WRAPNV_DEV_ERROR_REPORT == STD_ON) if(errorId != WRAPNV_E_NO_ERROR) { WrapNv_Det_ReportError(WRAPNV_APIID_READ, errorId ); } # else (void)errorId; # endif /* (WRAPNV_DEV_ERROR_REPORT == STD_ON) */ return result; } /*********************************************************************************************************************** * WrapNv_ReadPartial **********************************************************************************************************************/ /*! \brief Initialize operation for reading only partial of the data * \param[in] id Id of record * \param[in] idx Dataset of block * \param[out] buffer Pointer to data buffer * \param[in] offset Offset in the entry to read only partial * \param[in] length Length of the partial read * \param[in] access Type of access * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ /* PRQA S 6060, 6080 1 */ /* MD_MSR_STPAR, MD_MSR_STMIF */ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartial( uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length, tWrapNvAccessType access) { WrapNv_ReturnType result; uint8 errorId; P2CONST(tWrapNvRecordTbl, AUTOMATIC, WRAPNV_CONST) localRecordPtr; P2CONST(tWrapNvBlockTbl, AUTOMATIC, WRAPNV_CONST) localBlockPtr; /* Initialize variable */ result = WRAPNV_E_NOT_OK; errorId = WRAPNV_E_NO_ERROR; if (WRAPNV_STATE_IDLE != gWrapNvCurrentState) { errorId = WRAPNV_E_NOT_IDLE; } /* Check if ID is valid */ else if (id >= kWrapNvNrOfRecord) { errorId = WRAPNV_E_PARAM_ID; } /* Check if dataset is valid */ else if ( (idx >= kWrapNvRecordTbl[id].recordBlockPtr->blockMaxDatasets) || (idx > 0xFFu)) { errorId = WRAPNV_E_PARAM_DATASET; } else if ( ( (access == WRAPNV_ACCESS_DATAELEMENT) && ( (offset + length) > kWrapNvRecordTbl[id].recordDataLength) ) || ( (access == WRAPNV_ACCESS_BLOCKELEMENT) && ( (offset + length) > kWrapNvRecordTbl[id].recordBlockPtr->blockLength) ) ) { errorId = WRAPNV_E_PARAM_READ; } else { localRecordPtr = &kWrapNvRecordTbl[id]; localBlockPtr = localRecordPtr->recordBlockPtr; gWrapNvRecordNumber = id; gWrapNvBlockNumber = localBlockPtr->blockNumber; gWrapNvBlockDataset = idx; # if defined( WRAPNV_USECASE_NVM ) gWrapNvBlockMaxDataset = localBlockPtr->blockMaxDatasets; # endif /* WRAPNV_USECASE_NVM */ gWrapNvBlockDefaultValue = localBlockPtr->blockDefaultValue; if (access == WRAPNV_ACCESS_DATAELEMENT) { gWrapNvReadDataOffset = localRecordPtr->recordDataOffset + offset; gWrapNvReadDataLength = length; } else { gWrapNvReadDataOffset = offset; gWrapNvReadDataLength = length; } gWrapNvReadDataBuffer = buffer; gWrapNvWriteDataOffset = 0u; gWrapNvWriteDataLength = 0u; gWrapNvWriteDataBuffer = NULL_PTR; # if defined( WRAPNV_USECASE_NVM ) gWrapNvBlockAccessBuffer = gWrapNvBlockBuffer; # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) gWrapNvBlockAccessBuffer = NULL_PTR; # endif /* WRAPNV_USECASE_* */ gWrapNvCurrentState = WRAPNV_STATE_READ_INIT; result = WrapNv_MainFunction(); } # if (WRAPNV_DEV_ERROR_REPORT == STD_ON) if(errorId != WRAPNV_E_NO_ERROR) { WrapNv_Det_ReportError(WRAPNV_APIID_READPARTIAL, errorId ); } # else (void)errorId; # endif /* (WRAPNV_DEV_ERROR_REPORT == STD_ON) */ return result; } /*********************************************************************************************************************** * WrapNv_Delete **********************************************************************************************************************/ /*! \brief Initialize the delete operation * \param[in] id Id of record * \param[in] idx Dataset of block * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Delete( uint16 id, uint16 idx ) { WrapNv_ReturnType result; uint8 errorId; P2CONST(tWrapNvRecordTbl, AUTOMATIC, WRAPNV_CONST) localRecordPtr; P2CONST(tWrapNvBlockTbl, AUTOMATIC, WRAPNV_CONST) localBlockPtr; /* Initialize variable */ result = WRAPNV_E_NOT_OK; errorId = WRAPNV_E_NO_ERROR; if (WRAPNV_STATE_IDLE != gWrapNvCurrentState) { errorId = WRAPNV_E_NOT_IDLE; } /* Check if ID is valid */ else if (id >= kWrapNvNrOfRecord) { errorId = WRAPNV_E_PARAM_ID; } /* Check if dataset is valid */ else if ( (idx >= kWrapNvRecordTbl[id].recordBlockPtr->blockMaxDatasets) || (idx > 0xFFu)) { errorId = WRAPNV_E_PARAM_DATASET; } else { localRecordPtr = &kWrapNvRecordTbl[id]; localBlockPtr = localRecordPtr->recordBlockPtr; gWrapNvRecordNumber = id; gWrapNvBlockNumber = localBlockPtr->blockNumber; gWrapNvBlockDataset = idx; # if defined( WRAPNV_USECASE_NVM ) gWrapNvBlockMaxDataset = localBlockPtr->blockMaxDatasets; # endif /* WRAPNV_USECASE_NVM */ gWrapNvBlockDefaultValue = localBlockPtr->blockDefaultValue; gWrapNvReadDataOffset = 0u; gWrapNvReadDataLength = 0u; gWrapNvReadDataBuffer = NULL_PTR; gWrapNvWriteDataOffset = 0u; gWrapNvWriteDataLength = 0u; gWrapNvWriteDataBuffer = NULL_PTR; gWrapNvBlockAccessBuffer = NULL_PTR; gWrapNvCurrentState = WRAPNV_STATE_DELETE_INIT; result = WrapNv_MainFunction(); } # if (WRAPNV_DEV_ERROR_REPORT == STD_ON) if(errorId != WRAPNV_E_NO_ERROR) { WrapNv_Det_ReportError(WRAPNV_APIID_DELETE, errorId ); } # else (void)errorId; # endif /* (WRAPNV_DEV_ERROR_REPORT == STD_ON) */ return result; } /*********************************************************************************************************************** * WrapNv_Write **********************************************************************************************************************/ /*! \brief Initialize the write operation * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] access Type of access * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_Write( uint16 id, uint16 idx, tWrapNvConstData buffer, tWrapNvAccessType access) { WrapNv_ReturnType result; uint8 errorId; P2CONST(tWrapNvRecordTbl, AUTOMATIC, WRAPNV_CONST) localRecordPtr; P2CONST(tWrapNvBlockTbl, AUTOMATIC, WRAPNV_CONST) localBlockPtr; /* Initialize variable */ result = WRAPNV_E_NOT_OK; errorId = WRAPNV_E_NO_ERROR; if (WRAPNV_STATE_IDLE != gWrapNvCurrentState) { errorId = WRAPNV_E_NOT_IDLE; } /* Check if ID is valid */ else if (id >= kWrapNvNrOfRecord) { errorId = WRAPNV_E_PARAM_ID; } /* Check if dataset is valid */ else if ( (idx >= kWrapNvRecordTbl[id].recordBlockPtr->blockMaxDatasets) || (idx > 0xFFu)) { errorId = WRAPNV_E_PARAM_DATASET; } else { localRecordPtr = &kWrapNvRecordTbl[id]; localBlockPtr = localRecordPtr->recordBlockPtr; gWrapNvRecordNumber = id; gWrapNvBlockNumber = localBlockPtr->blockNumber; gWrapNvBlockDataset = idx; # if defined( WRAPNV_USECASE_NVM ) gWrapNvBlockMaxDataset = localBlockPtr->blockMaxDatasets; # endif /* WRAPNV_USECASE_NVM */ gWrapNvBlockDefaultValue = localBlockPtr->blockDefaultValue; if ( (localBlockPtr->blockDataAccess == WRAPNV_RECORDACCESS_STRUCTURED) && (access == WRAPNV_ACCESS_DATAELEMENT) ) { gWrapNvReadDataOffset = 0u; gWrapNvReadDataLength = localBlockPtr->blockLength; gWrapNvReadDataBuffer = gWrapNvBlockBuffer; /* Map the read buffer to the same buffer as the access buffer */ gWrapNvWriteDataOffset = localRecordPtr->recordDataOffset; gWrapNvWriteDataLength = localRecordPtr->recordDataLength; gWrapNvWriteDataBuffer = buffer; gWrapNvBlockAccessBuffer = gWrapNvBlockBuffer; gWrapNvCurrentState = WRAPNV_STATE_READ_MODIFY_INIT; } else { gWrapNvReadDataOffset = 0u; gWrapNvReadDataLength = 0u; gWrapNvReadDataBuffer = NULL_PTR; gWrapNvWriteDataOffset = 0u; gWrapNvWriteDataLength = 0u; gWrapNvWriteDataBuffer = NULL_PTR; gWrapNvBlockAccessBuffer = (tWrapNvRamData)buffer; /* PRQA S 0311 */ /* MD_WrapNv_0311 */ gWrapNvCurrentState = WRAPNV_STATE_WRITE_INIT; } result = WrapNv_MainFunction(); } # if (WRAPNV_DEV_ERROR_REPORT == STD_ON) if(errorId != WRAPNV_E_NO_ERROR) { WrapNv_Det_ReportError(WRAPNV_APIID_WRITE, errorId ); } # else (void)errorId; # endif /* (WRAPNV_DEV_ERROR_REPORT == STD_ON) */ return result; } /*********************************************************************************************************************** * WrapNv_ReadAsyncInternal **********************************************************************************************************************/ /*! \brief Reads specific data asynchronously from a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[out] buffer Pointer to data buffer * \param[in] opStatus Operation status of calling instance * \param[in] access Type of access * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadAsyncInternal(uint16 id, uint16 idx, tWrapNvRamData buffer, tWrapNvOpStatus opStatus, tWrapNvAccessType access) { WrapNv_ReturnType result; tWrapNvOpStatus currentOpStatus; WrapNv_EnterCritical(); /* Check if WrapNv is idle so it can accept a new request */ if (WRAPNV_OPERATION_IDLE == gWrapNvCurrentOperation) { /* Check if new job is canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Parameters will be stored in WrapNv_Read() call */ currentOpStatus = WRAPNV_OPSTATUS_INIT; gWrapNvCurrentOperation = WRAPNV_OPERATION_READ; } } else { /* Check if this is a different request to the current pending request */ if ((id == gWrapNvRecordNumber) && (idx == gWrapNvBlockDataset) && (buffer == gWrapNvReadDataBuffer) && (WRAPNV_OPERATION_READ == gWrapNvCurrentOperation) ) { /* Check if the current job should be canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Process current request */ currentOpStatus = WRAPNV_OPSTATUS_PENDING; } } else { /* Wait until other request has been finished */ currentOpStatus = WRAPNV_OPSTATUS_IDLE; } } WrapNv_LeaveCritical(); /* Only init and pending states are allowed at this point */ switch (currentOpStatus) { case WRAPNV_OPSTATUS_INIT: { result = WrapNv_Read(id, idx, buffer, access); break; } case WRAPNV_OPSTATUS_PENDING: { result = WrapNv_MainFunction(); break; } case WRAPNV_OPSTATUS_IDLE: /* Used when two instances access the WrapNv */ { result = WRAPNV_E_PENDING; break; } case WRAPNV_OPSTATUS_CANCEL: { result = WrapNv_Cancel(); break; } default: { /* PRQA S 2880 1 */ /* MD_MSR_Unreachable */ result = WRAPNV_E_NOT_OK; break; } } /* Check if current operation has finished */ if (WRAPNV_E_PENDING != result) { gWrapNvCurrentOperation = WRAPNV_OPERATION_IDLE; } return result; } /*********************************************************************************************************************** * WrapNv_ReadPartialAsyncInternal **********************************************************************************************************************/ /*! \brief Reads partial data asynchronously from a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[out] buffer Pointer to data buffer * \param[in] offset Offset in the entry to read only partial * \param[in] length Length of the partial read * \param[in] opStatus Operation status of calling instance * \param[in] access Type of access * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ /* PRQA S 6060 1 */ /* MD_MSR_STPAR */ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartialAsyncInternal(uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length, tWrapNvOpStatus opStatus, tWrapNvAccessType access) { WrapNv_ReturnType result; tWrapNvOpStatus currentOpStatus; WrapNv_EnterCritical(); /* Check if WrapNv is idle so it can accept a new request */ if (WRAPNV_OPERATION_IDLE == gWrapNvCurrentOperation) { /* Check if new job is canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Parameters will be stored in WrapNv_ReadPartial() call */ currentOpStatus = WRAPNV_OPSTATUS_INIT; gWrapNvCurrentOperation = WRAPNV_OPERATION_READPARTIAL; } } else { /* Check if this is a different request to the current pending request */ if ((id == gWrapNvRecordNumber) && (idx == gWrapNvBlockDataset) && (buffer == gWrapNvReadDataBuffer) && (offset == gWrapNvReadDataOffset) && (length == gWrapNvReadDataLength) && (WRAPNV_OPERATION_READPARTIAL == gWrapNvCurrentOperation) ) { /* Check if the current job should be canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Process current request */ currentOpStatus = WRAPNV_OPSTATUS_PENDING; } } else { /* Wait until other request has been finished */ currentOpStatus = WRAPNV_OPSTATUS_IDLE; } } WrapNv_LeaveCritical(); /* Only init and pending states are allowed at this point */ switch (currentOpStatus) { case WRAPNV_OPSTATUS_INIT: { result = WrapNv_ReadPartial(id, idx, buffer, offset, length, access); break; } case WRAPNV_OPSTATUS_PENDING: { result = WrapNv_MainFunction(); break; } case WRAPNV_OPSTATUS_IDLE: /* Used when two instances access the WrapNv */ { result = WRAPNV_E_PENDING; break; } case WRAPNV_OPSTATUS_CANCEL: { result = WrapNv_Cancel(); break; } default: { /* PRQA S 2880 1 */ /* MD_MSR_Unreachable */ result = WRAPNV_E_NOT_OK; break; } } /* Check if current operation has finished */ if (WRAPNV_E_PENDING != result) { gWrapNvCurrentOperation = WRAPNV_OPERATION_IDLE; } return result; } /*********************************************************************************************************************** * WrapNv_WriteAsyncInternal **********************************************************************************************************************/ /*! \brief Writes specific data asynchronously to a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] opStatus Operation status of calling instance * \param[in] access Type of access * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_WriteAsyncInternal(uint16 id, uint16 idx, tWrapNvConstData buffer, tWrapNvOpStatus opStatus, tWrapNvAccessType access) { WrapNv_ReturnType result; tWrapNvOpStatus currentOpStatus; WrapNv_EnterCritical(); /* Check if WrapNv is idle so it can accept a new request */ if (WRAPNV_OPERATION_IDLE == gWrapNvCurrentOperation) { /* Check if new job is canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Parameters will be stored in WrapNv_Write() call */ currentOpStatus = WRAPNV_OPSTATUS_INIT; gWrapNvCurrentOperation = WRAPNV_OPERATION_WRITE; } } else { /* Check if this is a different request to the current pending request */ if ((id == gWrapNvRecordNumber) && (idx == gWrapNvBlockDataset) && ((buffer == gWrapNvWriteDataBuffer) || (buffer == gWrapNvBlockAccessBuffer)) && (WRAPNV_OPERATION_WRITE == gWrapNvCurrentOperation) ) { /* Check if the current job should be canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Process current request */ currentOpStatus = WRAPNV_OPSTATUS_PENDING; } } else { /* Wait until other request has been finished */ currentOpStatus = WRAPNV_OPSTATUS_IDLE; } } WrapNv_LeaveCritical(); /* Only init and pending states are allowed at this point */ switch (currentOpStatus) { case WRAPNV_OPSTATUS_INIT: { result = WrapNv_Write(id, idx, buffer, access); break; } case WRAPNV_OPSTATUS_PENDING: { result = WrapNv_MainFunction(); break; } case WRAPNV_OPSTATUS_IDLE: /* Used when two instances access the WrapNv */ { result = WRAPNV_E_PENDING; break; } case WRAPNV_OPSTATUS_CANCEL: { result = WrapNv_Cancel(); break; } default: { /* PRQA S 2880 1 */ /* MD_MSR_Unreachable */ result = WRAPNV_E_NOT_OK; break; } } /* Check if current operation has finished */ if (WRAPNV_E_PENDING != result) { gWrapNvCurrentOperation = WRAPNV_OPERATION_IDLE; } return result; } /*********************************************************************************************************************** * WrapNv_MainFunction **********************************************************************************************************************/ /*! \brief Main task of the NV-Wrapper to get the current status of the read/write operation * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ /* PRQA S 6030, 6080 1 */ /* MD_MSR_STCYC, MD_MSR_STMIF */ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_MainFunction( void ) { WrapNv_ReturnType result = WRAPNV_E_PENDING; uint16_least index; switch (gWrapNvCurrentState) { case WRAPNV_STATE_READ_INIT: /* Intentional fall through */ case WRAPNV_STATE_READ_MODIFY_INIT: { if (MEMIF_IDLE == WrapNv_GetStatus()) { # if defined( WRAPNV_USECASE_NVM ) result = WrapNv_SetDataIndex(); if (WRAPNV_E_OK == result) { /* PRQA S 0314 1 */ /* MD_WrapNv_0314 */ result = NvM_ReadBlock(gWrapNvBlockNumber, (P2VAR(void, AUTOMATIC, NVM_APPL_DATA))gWrapNvBlockAccessBuffer); } # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) result = WrapNv_MemDrvRead(gWrapNvBlockNumber | gWrapNvBlockDataset, gWrapNvReadDataOffset, gWrapNvReadDataBuffer, gWrapNvReadDataLength); # endif /* WRAPNV_USECASE_* */ /* If read request was successful, remap result to WRAPNV_E_PENDING */ if (WRAPNV_E_OK == result) { result = WRAPNV_E_PENDING; if (WRAPNV_STATE_READ_INIT == gWrapNvCurrentState) { gWrapNvCurrentState = WRAPNV_STATE_READ_PENDING; } else { gWrapNvCurrentState = WRAPNV_STATE_READ_MODIFY_PENDING; } } else { /* Error occurred, go back to idle state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; } } break; } case WRAPNV_STATE_READ_PENDING: /* Intentional fall through */ case WRAPNV_STATE_READ_MODIFY_PENDING: { if (MEMIF_IDLE == WrapNv_GetStatus()) { switch( WrapNv_GetJobResult() ) { case MEMIF_JOB_OK: { # if defined( WRAPNV_USECASE_NVM ) for (index = 0u; index < gWrapNvReadDataLength; index++) { gWrapNvReadDataBuffer[index] = gWrapNvBlockAccessBuffer[gWrapNvReadDataOffset + index]; } # endif /* WRAPNV_USECASE_NVM */ result = WRAPNV_E_OK; break; } case MEMIF_BLOCK_INCONSISTENT: case MEMIF_BLOCK_INVALID: { if (gWrapNvBlockDefaultValue != NULL_PTR) { for (index = 0u; index < gWrapNvReadDataLength; index++) { gWrapNvReadDataBuffer[index] = gWrapNvBlockDefaultValue[gWrapNvReadDataOffset + index]; } } else { /* No explicit default value configured - fill read buffer with default value */ for (index = 0u; index < gWrapNvReadDataLength; index++) { gWrapNvReadDataBuffer[index] = WRAPNV_DEFAULT_VALUE; } } result = WRAPNV_E_OK; break; } default: { result = WRAPNV_E_NOT_OK; break; } } if (WRAPNV_E_OK == result) { if (WRAPNV_STATE_READ_PENDING == gWrapNvCurrentState) { /* No more action required - reset state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; } else { /* This is a read-modify-write operation - remap WRAPNV_E_OK state to WRAPNV_E_PENDING */ result = WRAPNV_E_PENDING; gWrapNvCurrentState = WRAPNV_STATE_MODIFY_DATA; } } else { /* Error occurred, go back to idle state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; } } break; } case WRAPNV_STATE_MODIFY_DATA: { /* Modify data with new information */ for (index = 0u; index < gWrapNvWriteDataLength; index++) { gWrapNvBlockAccessBuffer[gWrapNvWriteDataOffset + index] = gWrapNvWriteDataBuffer[index]; } gWrapNvCurrentState = WRAPNV_STATE_WRITE_INIT; } /* Intentional fall through */ case WRAPNV_STATE_WRITE_INIT: /* PRQA S 2003 */ /* MD_WrapNv_2003 */ { if (MEMIF_IDLE == WrapNv_GetStatus()) { # if defined( WRAPNV_USECASE_NVM ) result = WrapNv_SetDataIndex(); if (WRAPNV_E_OK == result) { /* PRQA S 0314 1 */ /* MD_WrapNv_0314 */ result = NvM_WriteBlock(gWrapNvBlockNumber, (P2CONST(void, AUTOMATIC, NVM_APPL_DATA))gWrapNvBlockAccessBuffer); } # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) result = WrapNv_MemDrvWrite(gWrapNvBlockNumber | gWrapNvBlockDataset, gWrapNvBlockAccessBuffer); # endif /* WRAPNV_USECASE_* */ /* If write request was successful, remap result to WRAPNV_E_PENDING */ if (WRAPNV_E_OK == result) { result = WRAPNV_E_PENDING; gWrapNvCurrentState = WRAPNV_STATE_WRITE_PENDING; } else { /* Error occurred, go back to idle state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; } } break; } case WRAPNV_STATE_DELETE_INIT: { if (MEMIF_IDLE == WrapNv_GetStatus()) { # if defined( WRAPNV_USECASE_NVM ) result = WrapNv_SetDataIndex(); if (WRAPNV_E_OK == result) { result = NvM_InvalidateNvBlock(gWrapNvBlockNumber); } # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) result = WrapNv_MemDrvInvalidateBlock(gWrapNvBlockNumber | gWrapNvBlockDataset); # endif /* WRAPNV_USECASE_* */ /* If invalidate request was successful, remap result to WRAPNV_E_PENDING */ if (WRAPNV_E_OK == result) { result = WRAPNV_E_PENDING; gWrapNvCurrentState = WRAPNV_STATE_DELETE_PENDING; } else { /* Error occurred, go back to idle state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; } } break; } case WRAPNV_STATE_WRITE_PENDING: /* Intentional fall through */ case WRAPNV_STATE_DELETE_PENDING: { if (MEMIF_IDLE == WrapNv_GetStatus()) { if (MEMIF_JOB_OK == WrapNv_GetJobResult()) { result = WRAPNV_E_OK; } else { result = WRAPNV_E_NOT_OK; } /* Regardless of result, go back to idle state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; } break; } case WRAPNV_STATE_CANCEL: { # if defined( WRAPNV_USECASE_NVM ) result = WrapNv_SetDataIndex(); if (WRAPNV_E_OK == result) { result = NvM_CancelJobs(gWrapNvBlockNumber); } # elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) WrapNv_MemDrvCancel(); result = WRAPNV_E_OK; # endif /* WRAPNV_USECASE_* */ /* Regardless of result, go back to idle state */ gWrapNvCurrentState = WRAPNV_STATE_IDLE; break; } default: { result = WRAPNV_E_NOT_OK; break; } } return result; } /*********************************************************************************************************************** * WrapNv_PollMainFunctions **********************************************************************************************************************/ /*! \brief Function to poll all sub modules * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ STATIC FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_PollMainFunctions( void ) { WrapNv_ReturnType result; result = WrapNv_MainFunction(); # if (WRAPNV_MAINFUNCTION_POLLING == STD_ON) WrapNv_PollMainFunctionsInternalIdle(); if (WrapNv_TriggerFct_Callout() == WRAPNV_E_OK) { WrapNv_PollMainFunctionsInternalTimer(); } # endif return result; } #endif /* WRAPNV_USECASE_* */ /********************************************************************************************************************** * GLOBAL FUNCTIONS *********************************************************************************************************************/ /*********************************************************************************************************************** * WrapNv_Init **********************************************************************************************************************/ /*! \brief Initializes NV-Wrapper to access FEE/EA/NVM/EEPM/DrvEEP and also async tasks from the NvM **********************************************************************************************************************/ FUNC(void, WRAPNV_CODE) WrapNv_Init( void ) { #if defined( WRAPNV_USECASE_DRVEEP ) (void)EepromDriver_InitSync(((void *)0)); #elif defined( WRAPNV_USECASE_EEPM ) (void)EepMgrInitPowerOn(kEepMgrInitFull); #elif defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) || \ defined( WRAPNV_USECASE_NVM ) WrapNv_InitConfig(); WrapNv_InitInternal(); # if defined ( WRAPNV_USECASE_NVM ) && defined( WRAPNV_ENABLE_NVM_MULTIBLOCK_HANDLING ) (void)WrapNv_NvM_ReadAllSync(); # endif /* WRAPNV_USECASE_NVM && WRAPNV_ENABLE_NVM_MULTIBLOCK_HANDLING */ #endif /* WRAPNV_USECASE_* */ } /*********************************************************************************************************************** * WrapNv_Deinit **********************************************************************************************************************/ /*! \brief De-initializes NV-Wrapper tasks from NVM **********************************************************************************************************************/ FUNC(void, WRAPNV_CODE) WrapNv_Deinit( void ) { #if defined( WRAPNV_USECASE_NVM ) && defined( WRAPNV_ENABLE_NVM_MULTIBLOCK_HANDLING ) (void)WrapNv_NvM_WriteAllSync(); #endif /* WRAPNV_USECASE_NVM && WRAPNV_ENABLE_NVM_MULTIBLOCK_HANDLING */ } #if defined( WRAPNV_USECASE_FEE ) || \ defined( WRAPNV_USECASE_EA ) || \ defined( WRAPNV_USECASE_NVM ) /*********************************************************************************************************************** * WrapNv_ReadSync **********************************************************************************************************************/ /*! \brief Reads specific data synchronously from a NV block * \pre Function must only be called from where MainFunction polling is allowed. * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \return kFblOk if succeeded, kFblFailed otherwise **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadSync( uint16 id, uint16 idx, tWrapNvRamData buffer ) { WrapNv_ReturnType result; result = WrapNv_Read(id, idx, buffer, WRAPNV_ACCESS_DATAELEMENT); while (WRAPNV_E_PENDING == result) { result = WrapNv_PollMainFunctions(); } return result; } /*********************************************************************************************************************** * WrapNv_ReadBlockSync **********************************************************************************************************************/ /*! \brief Reads an entire WrapNv block synchronously from a NV block * \pre Function must only be called from where MainFunction polling is allowed. * \param[in] id Id of record contained in the block * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \return kFblOk if succeeded, kFblFailed otherwise **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadBlockSync(uint16 id, uint16 idx, tWrapNvRamData buffer) { WrapNv_ReturnType result; result = WrapNv_Read(id, idx, buffer, WRAPNV_ACCESS_BLOCKELEMENT); while (WRAPNV_E_PENDING == result) { result = WrapNv_PollMainFunctions(); } return result; } /*********************************************************************************************************************** * WrapNv_ReadPartialSync **********************************************************************************************************************/ /*! \brief Reads partial data synchronously from a NV block * \pre Function must only be called from where MainFunction polling is allowed. * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] offset Offset in the entry to read only partial * \param[in] length Length of the partial read * \return kFblOk if succeeded, kFblFailed otherwise **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartialSync( uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length ) { WrapNv_ReturnType result; result = WrapNv_ReadPartial(id, idx, buffer, offset, length, WRAPNV_ACCESS_DATAELEMENT); while (WRAPNV_E_PENDING == result) { result = WrapNv_PollMainFunctions(); } return result; } /*********************************************************************************************************************** * WrapNv_ReadPartialBlockSync **********************************************************************************************************************/ /*! \brief Reads partial block synchronously from a NV block * \pre Function must only be called from where MainFunction polling is allowed. * \param[in] id Id of record contained in the block * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] offset Offset in the entry to read only partial * \param[in] length Length of the partial read * \return kFblOk if succeeded, kFblFailed otherwise **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartialBlockSync(uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length) { WrapNv_ReturnType result; result = WrapNv_ReadPartial(id, idx, buffer, offset, length, WRAPNV_ACCESS_BLOCKELEMENT); while (WRAPNV_E_PENDING == result) { result = WrapNv_PollMainFunctions(); } return result; } /*********************************************************************************************************************** * WrapNv_WriteSync **********************************************************************************************************************/ /*! \brief Writes specific data synchronously to a NV block * \pre Function must only be called from where MainFunction polling is allowed. * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \return kFblOk if succeeded, kFblFailed otherwise **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_WriteSync( uint16 id, uint16 idx, tWrapNvConstData buffer ) { WrapNv_ReturnType result; result = WrapNv_Write(id, idx, buffer, WRAPNV_ACCESS_DATAELEMENT); while (WRAPNV_E_PENDING == result) { result = WrapNv_PollMainFunctions(); } return result; } /*********************************************************************************************************************** * WrapNv_WriteBlockSync **********************************************************************************************************************/ /*! \brief Writes specific block synchronously to a NV block * \pre Function must only be called from where MainFunction polling is allowed. * \param[in] id Id of record contained in the block * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \return kFblOk if succeeded, kFblFailed otherwise **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_WriteBlockSync(uint16 id, uint16 idx, tWrapNvConstData buffer) { WrapNv_ReturnType result; result = WrapNv_Write(id, idx, buffer, WRAPNV_ACCESS_BLOCKELEMENT); while (WRAPNV_E_PENDING == result) { result = WrapNv_PollMainFunctions(); } return result; } /*********************************************************************************************************************** * WrapNv_DeleteSync **********************************************************************************************************************/ /*! \brief Delete specific NV block synchronously * \pre Function must only be called from where MainFunction polling is allowed. * \param[in] id Id of record * \param[in] idx Dataset of block * \return kFblOk if succeeded, kFblFailed otherwise **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_DeleteSync( uint16 id, uint16 idx ) { WrapNv_ReturnType result; result = WrapNv_Delete(id, idx); while (WRAPNV_E_PENDING == result) { result = WrapNv_PollMainFunctions(); } return result; } /*********************************************************************************************************************** * WrapNv_ReadAsync **********************************************************************************************************************/ /*! \brief Reads specific data asynchronously from a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[out] buffer Pointer to data buffer * \param[in] opStatus Operation status of calling instance * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadAsync( uint16 id, uint16 idx, tWrapNvRamData buffer, tWrapNvOpStatus opStatus) { WrapNv_ReturnType result; result = WrapNv_ReadAsyncInternal(id, idx, buffer, opStatus, WRAPNV_ACCESS_DATAELEMENT); return result; } /*********************************************************************************************************************** * WrapNv_ReadBlockAsync **********************************************************************************************************************/ /*! \brief Reads specific block asynchronously from a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] opStatus Operation status of calling instance * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadBlockAsync(uint16 id, uint16 idx, tWrapNvRamData buffer, tWrapNvOpStatus opStatus) { WrapNv_ReturnType result; result = WrapNv_ReadAsyncInternal(id, idx, buffer, opStatus, WRAPNV_ACCESS_BLOCKELEMENT); return result; } /*********************************************************************************************************************** * WrapNv_ReadPartialAsync **********************************************************************************************************************/ /*! \brief Reads specific data asynchronously from a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] offset Offset in the entry to read only partial * \param[in] length Length of the partial read * \param[in] opStatus Operation status of calling instance * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ /* PRQA S 6060 1 */ /* MD_MSR_STPAR */ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartialAsync( uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length, tWrapNvOpStatus opStatus) { WrapNv_ReturnType result; result = WrapNv_ReadPartialAsyncInternal(id, idx, buffer, offset, length, opStatus, WRAPNV_ACCESS_DATAELEMENT); return result; } /*********************************************************************************************************************** * WrapNv_ReadPartialBlockAsync **********************************************************************************************************************/ /*! \brief Reads partial data in WrapNv block asynchronously from a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] offset Offset in the entry to read only partial * \param[in] length Length of the partial read * \param[in] opStatus Operation status of calling instance * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ /* PRQA S 6060 1 */ /* MD_MSR_STPAR */ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_ReadPartialBlockAsync(uint16 id, uint16 idx, tWrapNvRamData buffer, uint16 offset, uint16 length, tWrapNvOpStatus opStatus) { WrapNv_ReturnType result; result = WrapNv_ReadPartialAsyncInternal(id, idx, buffer, offset, length, opStatus, WRAPNV_ACCESS_BLOCKELEMENT); return result; } /*********************************************************************************************************************** * WrapNv_WriteAsync **********************************************************************************************************************/ /*! \brief Writes specific data asynchronously to a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] opStatus Operation status of calling instance * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_WriteAsync( uint16 id, uint16 idx, tWrapNvConstData buffer, tWrapNvOpStatus opStatus) { WrapNv_ReturnType result; result = WrapNv_WriteAsyncInternal(id, idx, buffer, opStatus, WRAPNV_ACCESS_DATAELEMENT); return result; } /*********************************************************************************************************************** * WrapNv_WriteBlockAsync **********************************************************************************************************************/ /*! \brief Writes specific block asynchronously to a NV block * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] buffer Pointer to data buffer * \param[in] opStatus Operation status of calling instance * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_WriteBlockAsync(uint16 id, uint16 idx, tWrapNvConstData buffer, tWrapNvOpStatus opStatus) { WrapNv_ReturnType result; result = WrapNv_WriteAsyncInternal(id, idx, buffer, opStatus, WRAPNV_ACCESS_BLOCKELEMENT); return result; } /*********************************************************************************************************************** * WrapNv_DeleteAsync **********************************************************************************************************************/ /*! \brief Delete specific NV block asynchronously * \param[in] id Id of record * \param[in] idx Dataset of block * \param[in] opStatus Operation status of calling instance * \return result WRAPNV_E_OK on job completion, WRAPNV_E_NOT_OK if job execution failed, * WRAPNV_E_PENDING if job needs more time **********************************************************************************************************************/ FUNC(WrapNv_ReturnType, WRAPNV_CODE) WrapNv_DeleteAsync( uint16 id, uint16 idx, tWrapNvOpStatus opStatus) { WrapNv_ReturnType result; tWrapNvOpStatus currentOpStatus; WrapNv_EnterCritical(); /* Check if WrapNv is idle so it can accept a new request */ if (WRAPNV_OPERATION_IDLE == gWrapNvCurrentOperation) { /* Check if new job is canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Parameters will be stored in WrapNv_Delete() call */ currentOpStatus = WRAPNV_OPSTATUS_INIT; gWrapNvCurrentOperation = WRAPNV_OPERATION_DELETE; } } else { /* Check if this is a different request to the current pending request */ if ( (id == gWrapNvRecordNumber) && (idx == gWrapNvBlockDataset) && (WRAPNV_OPERATION_DELETE == gWrapNvCurrentOperation) ) { /* Check if the current job should be canceled */ if (opStatus == WRAPNV_OPSTATUS_CANCEL) { currentOpStatus = WRAPNV_OPSTATUS_CANCEL; } else { /* Process current request */ currentOpStatus = WRAPNV_OPSTATUS_PENDING; } } else { /* Wait until other request has been finished */ currentOpStatus = WRAPNV_OPSTATUS_IDLE; } } WrapNv_LeaveCritical(); /* Only init and pending states are allowed at this point */ switch (currentOpStatus) { case WRAPNV_OPSTATUS_INIT: { result = WrapNv_Delete(id, idx); break; } case WRAPNV_OPSTATUS_PENDING: { result = WrapNv_MainFunction(); break; } case WRAPNV_OPSTATUS_IDLE: /* Used when two instances access the WrapNv */ { result = WRAPNV_E_PENDING; break; } case WRAPNV_OPSTATUS_CANCEL: { result = WrapNv_Cancel(); break; } default: { /* PRQA S 2880 1 */ /* MD_MSR_Unreachable */ result = WRAPNV_E_NOT_OK; break; } } /* Check if current operation has finished */ if (WRAPNV_E_PENDING != result) { gWrapNvCurrentOperation = WRAPNV_OPERATION_IDLE; } return result; } # if defined( WRAPNV_USECASE_NVM ) # if defined( WRAPNV_ENABLE_NVMAPIS_HANDLING ) /*********************************************************************************************************************** * WrapNv_NvM_WriteBlockSync **********************************************************************************************************************/ /*! \brief Synchronous wrapper to the NvM API NvM_WriteBlock * \param[in] blockId NvM ID of NvM block * \param[in] buffer Pointer to the RAM buffer NvM shall write * \return result E_OK on successful operation, E_NOT_OK if operation failed **********************************************************************************************************************/ FUNC(Std_ReturnType, WRAPNV_CODE) WrapNv_NvM_WriteBlockSync( NvM_BlockIdType blockId, tWrapNvNvMConstData buffer ) { Std_ReturnType result = E_NOT_OK; NvM_RequestResultType operationStatus = NVM_REQ_PENDING; result = NvM_WriteBlock(blockId, buffer); while ((result == E_OK) && (operationStatus == NVM_REQ_PENDING)) { WrapNv_PollMainFunctionsInternalIdle(); if (WrapNv_TriggerFct_Callout() == WRAPNV_E_OK) { WrapNv_PollMainFunctionsInternalTimer(); } result = NvM_GetErrorStatus(blockId, &operationStatus); } return result; } /*********************************************************************************************************************** * WrapNv_NvM_ReadBlockSync **********************************************************************************************************************/ /*! \brief Synchronous wrapper to the NvM API NvM_ReadBlock * \param[in] blockId NvM ID of NvM block * \param[in] buffer Pointer to the RAM buffer NvM shall write * \return result E_OK on successful operation, E_NOT_OK if operation failed **********************************************************************************************************************/ FUNC(Std_ReturnType, WRAPNV_CODE) WrapNv_NvM_ReadBlockSync( NvM_BlockIdType blockId, tWrapNvNvMRamData buffer ) { Std_ReturnType result = E_NOT_OK; NvM_RequestResultType operationStatus = NVM_REQ_PENDING; result = NvM_ReadBlock(blockId, buffer); while ((result == E_OK) && (operationStatus == NVM_REQ_PENDING)) { WrapNv_PollMainFunctionsInternalIdle(); if (WrapNv_TriggerFct_Callout() == WRAPNV_E_OK) { WrapNv_PollMainFunctionsInternalTimer(); } result = NvM_GetErrorStatus(blockId, &operationStatus); } return result; } # endif /* WRAPNV_ENABLE_NVMAPIS_HANDLING */ # if defined( WRAPNV_ENABLE_NVM_MULTIBLOCK_HANDLING ) /*********************************************************************************************************************** * WrapNv_NvM_WriteAllSync **********************************************************************************************************************/ /*! \brief Executes the NvM API NvM_WriteAll synchronously * \return result E_OK on successful operation, E_NOT_OK if operation failed **********************************************************************************************************************/ FUNC(Std_ReturnType, WRAPNV_CODE) WrapNv_NvM_WriteAllSync( void ) { Std_ReturnType result = E_OK; NvM_RequestResultType operationStatus = NVM_REQ_PENDING; NvM_WriteAll(); while ((result == E_OK) && (operationStatus == NVM_REQ_PENDING)) { WrapNv_PollMainFunctionsInternalIdle(); if (WrapNv_TriggerFct_Callout() == WRAPNV_E_OK) { WrapNv_PollMainFunctionsInternalTimer(); } result = NvM_GetErrorStatus(NvMConf___MultiBlockRequest, &operationStatus); } return result; } /*********************************************************************************************************************** * WrapNv_NvM_ReadAllSync **********************************************************************************************************************/ /*! \brief Executes the NvM API NvM_ReadAll synchronously * \return result E_OK on successful operation, E_NOT_OK if operation failed **********************************************************************************************************************/ FUNC(Std_ReturnType, WRAPNV_CODE) WrapNv_NvM_ReadAllSync( void ) { Std_ReturnType result = E_OK; NvM_RequestResultType operationStatus = NVM_REQ_PENDING; NvM_ReadAll(); while ((result == E_OK) && (operationStatus == NVM_REQ_PENDING)) { WrapNv_PollMainFunctionsInternalIdle(); if (WrapNv_TriggerFct_Callout() == WRAPNV_E_OK) { WrapNv_PollMainFunctionsInternalTimer(); } result = NvM_GetErrorStatus(NvMConf___MultiBlockRequest, &operationStatus); } return result; } # endif /* WRAPNV_ENABLE_NVM_MULTIBLOCK_HANDLING */ # endif /* WRAPNV_USECASE_NVM */ #endif /* WRAPNV_USECASE_* */ #define WRAPNV_STOP_SEC_CODE #include "MemMap.h" /* PRQA S 5087 */ /* MD_MSR_MemMap */ /*********************************************************************************************************************** * MISRA DEVIATIONS **********************************************************************************************************************/ /* Justification for module-specific MISRA deviations: MD_WrapNv_0311: Reason: Provide simplified function interface and reduce stack consumption by avoiding separate pointers for read and write buffer. Risk: The content of the write buffer might be accidentally overwritten. Prevention: Covered by code review. MD_WrapNv_0314: Reason: API is defined with pointer to void parameter, so pointer has to be casted to or from void. Risk: Wrong data access or undefined behavior for platforms where the byte alignment is not arbitrary. Prevention: Code inspection and test with the target compiler/platform in the component test. MD_WrapNv_2003: Reason: Intentionally switch case with out break statement to proceed the next step immediately Risk: No identifiable risk. Prevention: Covered by code review. MD_WrapNv_3218: Reason: The usage of variables depend on configuration aspects and may be used only once. Risk: No identifiable risk. Prevention: No prevention required. */ /*********************************************************************************************************************** * END OF FILE: WRAPNV.C **********************************************************************************************************************/