/* BEGIN_FILE_HDR ************************************************************************************************ * NOTICE * This software is the property of HiRain Technologies. Any information contained in this * doc should not be reproduced, or used, or disclosed without the written authorization from * HiRain Technologies. ************************************************************************************************ * File Name : Fee.c ************************************************************************************************ * Module Name : Fee_Z20K14X * Title : Fee.c ************************************************************************************************ * Platform : ARM * Peripheral : FEE * Autosar Version : 4.7.0 * Package Version : 01.00.00 ************************************************************************************************ * Description : This module can make Flash Emulate EEPROM of Z20K14X Mcu. * ************************************************************************************************ * Limitations : This File should work with Flash Module. * ************************************************************************************************ * ************************************************************************************************ * Revision History: * * Version Date Initials CR# Descriptions * --------- ---------- ------------ ---------- --------------- * 01.00.00 2023/03/13 huan.ji N/A Original * * ************************************************************************************************ * END_FILE_HDR*/ #ifdef __cplusplus extern "C"{ #endif /******************************************************************************************************** INCLUDE FILES *********************************************************************************************************/ #include "Fee.h" #include "Fee_Cfg.h" #include "Fee_InternalTypes.h" #include "Fee_Cbk.h" #include "SchM_Fee.h" #include "Fee_Version.h" #if (FEE_DEV_ERROR_DETECT == STD_OFF) #else #include "Det.h" #endif /* FEE_DEV_ERROR_DETECT == STD_OFF */ /********************************************************************************************************************** MODULE VERSION MACROS **********************************************************************************************************************/ /****FILE VERSION CHECKS****/ /* check Version with cfg file */ #if((FEE_AR_RELEASE_MAJOR_VERSION != FEE_AR_RELEASE_MAJOR_VERSION_CFG) || \ (FEE_AR_RELEASE_MINOR_VERSION != FEE_AR_RELEASE_MINOR_VERSION_CFG)) #error "AutoSar Version Numbers of CanTp and its cfg file are different" #endif #if((FEE_SW_MAJOR_VERSION != FEE_SW_MAJOR_VERSION_CFG) || \ (FEE_SW_MINOR_VERSION != FEE_SW_MINOR_VERSION_CFG)) #error "SW Version Numbers of CanTp and its cfg file are different" #endif /****LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)****/ /****LOCAL MACROS****/ /****LOCAL CONSTANTS****/ /****LOCAL VARIABLES****/ #define FEE_START_SEC_VAR_INIT_8 #include "Fee_MemMap.h" /* Internal variable used to trigger a cluster swap. Used by the swap job.*/ static boolean Fee_bSwapToBePerformed; /**Pointer to user data buffer. Used by the read Fee jobs*/ static uint8 *Fee_pJobReadDataDestPtr = NULL_PTR; /**Pointer to user data buffer. Used by the write Fee jobs*/ static const uint8 *Fee_pJobWriteDataDestPtr = NULL_PTR; /**Internal cluster group iterator. Used by the scan and swap jobs * Warning: do not use it outside scan and swap functions * (because it will be Out of Range)*/ static uint8 Fee_uJobIntClrGrpIt = (uint8)0; /*Internal cluster iterator. Used by the scan and swap jobs*/ static uint8 Fee_uJobIntClrIt = (uint8)0; /*Data buffer used by all jobs to store immediate data*/ static uint8 Fee_aDataBuffer[FEE_DATA_BUFFER_SIZE] = {(uint8)0}; #define FEE_STOP_SEC_VAR_INIT_8 #include "Fee_MemMap.h" #define FEE_START_SEC_VAR_INIT_16 #include "Fee_MemMap.h" /*Fee block index. Used by all Fee jobs*/ static uint16 Fee_uJobBlockIndex = 0U; /*Internal block iterator. Used by the swap job*/ static uint16 Fee_uJobIntBlockIt = 0U; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else /*Used to keep the number of foreign blocks found when parsing the data flash. * It represents the number of elements from the Fee_ForeignBlockConfig array.*/ static uint16 Fee_uForeignBlocksNumber = 0U; #endif #define FEE_STOP_SEC_VAR_INIT_16 #include "Fee_MemMap.h" #define FEE_START_SEC_VAR_INIT_32 #include "Fee_MemMap.h" /*Run-time information about blocks touching the Reserved Area:Fee_aReservedAreaTouched_Object*/ static uint32 Fee_aReservedAreaTouched[(FEE_MAX_NR_OF_BLOCKS+((sizeof( uint32 )*8U)-1U))/(sizeof( uint32 )*8U)] = { 0UL }; #define FEE_STOP_SEC_VAR_INIT_32 #include "Fee_MemMap.h" #define FEE_START_SEC_VAR_INIT_UNSPECIFIED #include "Fee_MemMap.h" /*Fee block offset. Used by the read Fee job*/ static Fls_LengthType Fee_uJobBlockOffset = 0UL; /*Number of bytes to read. Used by the read Fee job*/ static Fls_LengthType Fee_uJobBlockLength = 0UL; /*Internal flash helper address iterator. Used by the scan and swap jobs*/ static Fls_AddressType Fee_uJobIntAddrIt = 0UL; /*Internal address of current block header. Used by the swap job*/ static Fls_AddressType Fee_uJobIntHdrAddr = 0UL; /*Internal address of current data block. Used by the swap job.*/ static Fls_AddressType Fee_uJobIntDataAddr = 0UL; /*Internal state of Fee module*/ static MemIf_StatusType Fee_eModuleStatus = MEMIF_UNINIT; /*Result of last Fee module job*/ static MemIf_JobResultType Fee_eJobResult = MEMIF_JOB_OK; /*Currently executed job (including internal one)*/ static Fee_JobType Fee_eJob = FEE_JOB_DONE; /*Fee job which started internal management job(s) such as swap..*/ static Fee_JobType Fee_eJobIntOriginalJob = FEE_JOB_DONE; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else /*Used to keep the config of the foreign blocks*/ static Fee_BlockConfigType Fee_ForeignBlockConfig[FEE_MAX_NR_OF_BLOCKS - FEE_CRT_CFG_NR_OF_BLOCKS]={{0U}}; #endif #define FEE_STOP_SEC_VAR_INIT_UNSPECIFIED #include "Fee_MemMap.h" #define FEE_START_SEC_VAR_NO_INIT_UNSPECIFIED #include "Fee_MemMap.h" /*Run-time information of all configured Fee blocks. Contains status, and data information. Used by all jobs:Fee_aBlockInfo_Object*/ static Fee_BlockInfoType Fee_aBlockInfo[FEE_MAX_NR_OF_BLOCKS]; /*Run-time information of all configured cluster groups*/ static Fee_ClusterGroupInfoType Fee_aClrGrpInfo[FEE_NUMBER_OF_CLUSTER_GROUPS]; #define FEE_STOP_SEC_VAR_NO_INIT_UNSPECIFIED #include "Fee_MemMap.h" /****GLOBAL FUNCTION DECLARATION****/ #define FEE_START_SEC_CODE #include "Fee_MemMap.h" /****LOCAL FUNCTION PROTOTYPES****/ static INLINE void Fee_UntouchReservedAreaByClrGrp(const uint8 uClrGrpIndex); static void Fee_SerializeBlockHdr(uint16 uBlockNumber, uint16 uLength, const Fls_AddressType uTargetAddress, const boolean bImmediateBlock, #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED ) #else const Fee_BlockAssignmentType uBlockAssignment, #endif uint8 *pBlockHdrPtr ); static Std_ReturnType Fee_BlankCheck(const uint8 *pTargetPtr, const uint8 * const pTargetEndPtr); static Std_ReturnType Fee_DeserializeFlag(const uint8 * const pTargetPtr, const uint8 u8FlagPattern, boolean *pFlagValue); static Fee_BlockStatusType Fee_DeserializeBlockHdr(uint16 * const pBlockNumber, uint16 * const pLength, Fls_AddressType * const pTargetAddress, boolean * const pImmediateBlock, #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else uint8 * const uBlockAssignment, #endif const uint8 *pBlockHdrPtr ); static Fee_ClusterStatusType Fee_DeserializeClusterHdr(uint32 * const pClrID, Fls_AddressType * const pStartAddress, Fls_LengthType * const pClusteSize, const uint8 *pClrHdrPtr); static void Fee_SerializeClusterHdr(const uint32 uClrID, const Fls_AddressType uStartAddress, Fls_LengthType uClusteSize, uint8 *pClrHdrPtr); static uint16 Fee_GetBlockIndex(uint16 uBlockNumber); static uint16 Fee_AlignToVirtualPageSize(uint16 uBlockSize); static void Fee_CopyDataToPageBuffer(const uint8 *pSourcePtr, uint8 *pTargetPtr, uint16 uLength); static void Fee_SerializeFlag(uint8 *pTargetPtr, const uint8 u8FlagPattern); static MemIf_JobResultType Fee_JobIntSwapClrVld( void ); static MemIf_JobResultType Fee_JobIntSwapBlock( void ); static MemIf_JobResultType Fee_JobIntSwapClrFmt( void ); static MemIf_JobResultType Fee_JobIntSwapClrErase( void ); static MemIf_JobResultType Fee_JobIntSwap( void ); static MemIf_JobResultType Fee_JobIntScanBlockHdrRead( void ); static MemIf_JobResultType Fee_JobIntScanClrErase( void ); static MemIf_JobResultType Fee_JobIntScanClr( void ); static MemIf_JobResultType Fee_JobIntScanClrFmt( void ); static MemIf_JobResultType Fee_JobIntScanClrFmtDone( void ); static MemIf_JobResultType Fee_JobIntScanBlockHdrParse(const boolean bBufferValid); static MemIf_JobResultType Fee_JobIntScanClrHdrRead( void ); static MemIf_JobResultType Fee_JobIntScan( void ); static MemIf_JobResultType Fee_JobIntScanClrHdrParse(const boolean bBufferValid); static MemIf_JobResultType Fee_JobRead( void ); static MemIf_JobResultType Fee_JobIntSwapBlockVld( void ); static MemIf_JobResultType Fee_JobIntSwapDataRead(const boolean bBufferValid); static MemIf_JobResultType Fee_JobIntSwapDataWrite(const boolean bBufferValid); static MemIf_JobResultType Fee_JobIntSwapClrVldDone( void ); static MemIf_JobResultType Fee_JobWriteHdr( void ); static MemIf_JobResultType Fee_JobWriteData( void ); static MemIf_JobResultType Fee_JobWrite( void ); static MemIf_JobResultType Fee_JobWriteUnalignedData( void ); static MemIf_JobResultType Fee_JobWriteValidate( void ); static MemIf_JobResultType Fee_JobWriteDone( void ); static MemIf_JobResultType Fee_JobInvalBlock( void ); static MemIf_JobResultType Fee_JobInvalBlockDone( void ); static MemIf_JobResultType Fee_JobEraseImmediate( void ); static MemIf_JobResultType Fee_JobEraseImmediateDone( void ); static MemIf_JobResultType Fee_JobSchedule( void ); #if (STD_ON == FEE_LEGACY_MODE) #else static sint8 Fee_ReservedAreaWritable( void ); #endif /*STD_ON == FEE_LEGACY_MODE*/ #define FEE_STOP_SEC_CODE #include "Fee_MemMap.h" /****LOCAL FUNCTIONS****/ #define FEE_START_SEC_CODE #include "Fee_MemMap.h" /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_UntouchReservedAreaByClrGrp * Description : Removes the information about touching the Reserved Area for all blocks * within a cluster group specified by uClrGrpIndex. * * Inputs : uClrGrpIndex * * Outputs : None. * * Limitations : 1. Shall be only used in this file. * ************************************************************************************************ END_FUNCTION_HDR */ static INLINE void Fee_UntouchReservedAreaByClrGrp(const uint8 uClrGrpIndex) { uint32 uBlockIt = 0UL; uint32 uIdx = 0UL; uint32 uMask = 0x00000001UL; uint8 uBlockClusterGrp = 0U; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) while(uBlockIt < FEE_CRT_CFG_NR_OF_BLOCKS) #else while(uBlockIt < ((uint32)FEE_CRT_CFG_NR_OF_BLOCKS + (uint32)Fee_uForeignBlocksNumber)) #endif { #if(STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockClusterGrp = FEE_BLOCKCONFIG(uBlockIt, clrGrp); #else if (uBlockIt < FEE_CRT_CFG_NR_OF_BLOCKS) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockClusterGrp = FEE_BLOCKCONFIG(uBlockIt, clrGrp); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockClusterGrp = FEE_FOREIGNBLOCKCONFIG(uBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, clrGrp); } #endif if(uBlockClusterGrp != uClrGrpIndex) { /* Do nothing. */ } else { Fee_aReservedAreaTouched[uIdx] &= (~uMask); } if (uMask != 0x80000000UL) { uMask = uMask << 1U; } else { uMask = 0x00000001UL; uIdx++; } uBlockIt++; } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_SerializeBlockHdr * * Description : Serialize Fee block parameters into a write buffer * * Inputs : uBlockNumber Fee block number. * uLength Size of Fee block in bytes. * uTargetAddress Logical address of Fee block in Fls adress space. * bImmediateBlock Type of Fee block. Set to TRUE for immediate block. * * Outputs : pBlockHdrPtr Pointer to serialization buffer. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static void Fee_SerializeBlockHdr(uint16 uBlockNumber, uint16 uLength, const Fls_AddressType uTargetAddress, const boolean bImmediateBlock, #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else const Fee_BlockAssignmentType uBlockAssignment, #endif uint8 *pBlockHdrPtr ) { uint32 u32checkSum = 0UL; uint8 *pTargetEndPtr = NULL_PTR; pTargetEndPtr = FEE_OPERATIONADD(pBlockHdrPtr, FEE_BLOCK_OVERHEAD); /* Calculate the block header checksum */ u32checkSum = FEE_CHECKSUM((uint32)uBlockNumber, (uint32)uLength, uTargetAddress); /* Use MSB of the checksum for the immediate block flag so the checksum is 31-bit */ if( !bImmediateBlock ) { u32checkSum &= 0x7fffffffU; } else { u32checkSum += 1U; u32checkSum |= 0x80000000U; } FEE_SERIALIZE( uBlockNumber, uint16, pBlockHdrPtr ) FEE_SERIALIZE( uLength, uint16, pBlockHdrPtr ) FEE_SERIALIZE( uTargetAddress, Fls_AddressType, pBlockHdrPtr ) FEE_SERIALIZE( u32checkSum, uint32, pBlockHdrPtr ) #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else FEE_SERIALIZE( (uint8)uBlockAssignment, uint8, pBlockHdrPtr ) #endif /* Fill rest of the header with the erase pattern */ while(pBlockHdrPtr < pTargetEndPtr) { *pBlockHdrPtr = FEE_ERASED_VALUE; pBlockHdrPtr++; } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_BlankCheck * * Description : Check whether specified data buffer contains only the FEE_ERASED_VALUE value * * Inputs : pTargetPtr pointer to start of the checked buffer. * pTargetEndPtr pointer to end + 1 of the checked buffer. * * Outputs : E_OK The buffer contains only erased value. * E_NOT_OK The buffer doesn't contain only erased value. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static Std_ReturnType Fee_BlankCheck(const uint8 *pTargetPtr, const uint8 * const pTargetEndPtr) { Std_ReturnType uRetVal = (Std_ReturnType)E_OK; while(pTargetPtr < pTargetEndPtr) { if(*pTargetPtr != FEE_ERASED_VALUE) { uRetVal = (Std_ReturnType)E_NOT_OK; break; } else { /* Pattern match */ } pTargetPtr++; } return( uRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_DeserializeFlag * * Description : Deserialize the valid or invalid flag from a read buffer. * * Inputs : pTargetPtr Pointer to the read buffer. * u8FlagPattern FEE_VALIDATED_VALUE or FEE_INVALIDATED_VALUE. * pFlagValue TRUE if flag of above type is set. * * Outputs : E_OK The flag is set or cleared and rest of the read buffer * (FEE_VIRTUAL_PAGE_SIZE - 1) contains FEE_ERASED_VALUE * E_NOT_OK Buffer doesn't contain valid flag data. It's garbled... * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static Std_ReturnType Fee_DeserializeFlag(const uint8 * const pTargetPtr, const uint8 u8FlagPattern,boolean *pFlagValue) { Std_ReturnType uRetVal = (Std_ReturnType)E_OK; if((*pTargetPtr == u8FlagPattern) || (*pTargetPtr == FEE_ERASED_VALUE)) { /* The bytePattern can be either present or not */ if(*pTargetPtr == u8FlagPattern) { *pFlagValue = (boolean)TRUE; } else { *pFlagValue = (boolean)FALSE; } /* Check rest of the FEE_VIRTUAL_PAGE_SIZE */ /* @violates @ref Fee_c_REF_6 Array indexing shall be the only allowed form of pointer arithmetic. */ uRetVal = Fee_BlankCheck( pTargetPtr+1, pTargetPtr+FEE_VIRTUAL_PAGE_SIZE ); } else { uRetVal = (Std_ReturnType)E_NOT_OK; } return( uRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_DeserializeBlockHdr * * Description : Deserialize Fee block header parameters from read buffer. * * Inputs : pBlockNumber Fee block number. * pLength Size of Fee block in bytes. * pTargetAddress Logical address of Fee block in Fls adress space. * pImmediateBlock Type of Fee block. Set to TRUE for immediate block. * pBlockHdrPtr Pointer to read buffer. * * Outputs : FEE_BLOCK_VALID Fee block is valid. * FEE_BLOCK_INVALID Fee block is invalid (has been invalidated). * FEE_BLOCK_INCONSISTENT Fee block is inconsistent, it may contain corrupted data... * FEE_BLOCK_HEADER_INVALID Fee block header is invalid (garbled). * FEE_BLOCK_HEADER_BLANK Fee block header is filled with FEE_ERASED_VALUE. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static Fee_BlockStatusType Fee_DeserializeBlockHdr(uint16 * const pBlockNumber, uint16 * const pLength, Fls_AddressType * const pTargetAddress, boolean * const pImmediateBlock, #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else uint8 * const uBlockAssignment, #endif const uint8 *pBlockHdrPtr ) { Fee_BlockStatusType eRetVal = FEE_BLOCK_HEADER_INVALID; uint32 u32ReadCheckSum = 0UL; uint32 u32CalcCheckSum = 0UL; const uint8 *pTargetEndPtr = NULL_PTR; boolean bFlagValid = (boolean)FALSE; boolean bFlagInvalid = (boolean)FALSE; #if (STD_ON == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else uint8 u8ReservedSpace = 0U; #endif if( Fee_BlankCheck( pBlockHdrPtr, pBlockHdrPtr+FEE_BLOCK_OVERHEAD ) == ((Std_ReturnType)E_OK) ) { eRetVal = FEE_BLOCK_HEADER_BLANK; } else { /* Check 1st part of the header */ pTargetEndPtr = FEE_OPERATIONSUB((pBlockHdrPtr + FEE_BLOCK_OVERHEAD), (2U * FEE_VIRTUAL_PAGE_SIZE)); FEE_DESERIALIZE( pBlockHdrPtr, *pBlockNumber, uint16 ) FEE_DESERIALIZE( pBlockHdrPtr, *pLength, uint16 ) FEE_DESERIALIZE( pBlockHdrPtr, *pTargetAddress, Fls_AddressType ) FEE_DESERIALIZE( pBlockHdrPtr, u32ReadCheckSum, uint32 ) #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* pBlockHdrPtr must be advanced with 1 bytes. the reason is to avoid blank check for this area reserved for blockAssignment even when SWAP_FOREIGN is disabled to allow disabling SWAP_FOREIGN at production time. */ FEE_DESERIALIZE( pBlockHdrPtr, u8ReservedSpace, uint8) /* variable u8ReservedSpace not used */ (void)u8ReservedSpace; #else FEE_DESERIALIZE( pBlockHdrPtr, *uBlockAssignment, uint8 ) #endif /* Use MSB of checksum for immediate block flag so the checksum is 31-bit long */ u32CalcCheckSum = FEE_CHECKSUM(*pLength, *pTargetAddress, *pBlockNumber); if((0x80000000U & u32ReadCheckSum) != 0U) { *pImmediateBlock = (boolean)TRUE; u32CalcCheckSum += 1U; } else { *pImmediateBlock = (boolean)FALSE; } /* Ignore MSB since it's used for ImmediateBlock flag */ if((0x7fffffffU & u32CalcCheckSum) != (0x7fffffffU & u32ReadCheckSum)) { /* FEE_BLOCK_HEADER_INVALID */ } else if(Fee_BlankCheck( pBlockHdrPtr, pTargetEndPtr ) == ((Std_ReturnType)E_NOT_OK)) { /* FEE_BLOCK_HEADER_INVALID */ } else if(Fee_DeserializeFlag(pTargetEndPtr, FEE_VALIDATED_VALUE, &bFlagValid) == ((Std_ReturnType)E_NOT_OK)) { /* FEE_BLOCK_HEADER_INVALID */ } else if(Fee_DeserializeFlag( pTargetEndPtr+FEE_VIRTUAL_PAGE_SIZE, FEE_INVALIDATED_VALUE, &bFlagInvalid) == ((Std_ReturnType)E_NOT_OK)) { /* FEE_BLOCK_HEADER_INVALID */ } else { /* Block header is valid */ if((bFlagInvalid != (boolean)TRUE) && (bFlagValid != (boolean)TRUE)) { eRetVal = FEE_BLOCK_INCONSISTENT; } else if(bFlagInvalid != ((boolean)TRUE) && (bFlagValid != (boolean)FALSE)) { eRetVal = FEE_BLOCK_VALID; } #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) else if((bFlagInvalid != (boolean)FALSE) && (bFlagValid != (boolean)FALSE)) { eRetVal = FEE_BLOCK_INVALIDATED; } #endif else { eRetVal = FEE_BLOCK_INVALID; } } } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_DeserializeClusterHdr * * Description : Deserialize Fee block header parameters from read buffer. * * Inputs : pClrID 32-bit cluster ID. * pStartAddress Logical address of Fee cluster in Fls address space. * pClusteSize Size of Fee cluster in bytes. * pClrHdrPtr Pointer to read buffer. * * Outputs : FEE_CLUSTER_VALID Fee cluster is valid. * FEE_CLUSTER_INVALID Fee cluster has been invalidated. * FEE_CLUSTER_INCONSISTENT Fee cluster is inconsistent, it may contain corrupted data. * FEE_CLUSTER_HEADER_INVALID Fee cluster header is invalid (garbled). * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static Fee_ClusterStatusType Fee_DeserializeClusterHdr(uint32 * const pClrID, Fls_AddressType * const pStartAddress, Fls_LengthType * const pClusteSize, const uint8 *pClrHdrPtr) { Fee_ClusterStatusType eRetVal = FEE_CLUSTER_HEADER_INVALID; uint32 u32CheckSum = 0UL; boolean bFlagValid = (boolean)FALSE; boolean bFlagInvalid = (boolean)FALSE; const uint8 *pTargetEndPtr = NULL_PTR; /* Check 1st part of the header */ pTargetEndPtr = FEE_OPERATIONSUB((pClrHdrPtr + FEE_CLUSTER_OVERHEAD), (2U * FEE_VIRTUAL_PAGE_SIZE)); FEE_DESERIALIZE( pClrHdrPtr, *pClrID, uint32 ) FEE_DESERIALIZE( pClrHdrPtr, *pStartAddress, Fls_AddressType ) FEE_DESERIALIZE( pClrHdrPtr, *pClusteSize, Fls_LengthType ) FEE_DESERIALIZE( pClrHdrPtr, u32CheckSum, uint32 ) if(u32CheckSum != (*pClrID+*pStartAddress+*pClusteSize)) { /* FEE_CLUSTER_HEADER_INVALID */ } else if(Fee_BlankCheck( pClrHdrPtr, pTargetEndPtr ) == ((Std_ReturnType)E_NOT_OK)) { /* FEE_CLUSTER_HEADER_INVALID */ } else if(Fee_DeserializeFlag( pTargetEndPtr, FEE_VALIDATED_VALUE, &bFlagValid) == ((Std_ReturnType)E_NOT_OK)) { /* FEE_CLUSTER_HEADER_INVALID */ } else if(Fee_DeserializeFlag( pTargetEndPtr+FEE_VIRTUAL_PAGE_SIZE, FEE_INVALIDATED_VALUE, &bFlagInvalid) == ((Std_ReturnType)E_NOT_OK)) { /* FEE_CLUSTER_HEADER_INVALID */ } else { if((bFlagValid != (boolean)TRUE) && (bFlagInvalid != (boolean)TRUE)) { eRetVal = FEE_CLUSTER_INCONSISTENT; } if( (bFlagValid != (boolean)FALSE) && (bFlagInvalid != (boolean)TRUE) ) { eRetVal = FEE_CLUSTER_VALID; } else { eRetVal = FEE_CLUSTER_INVALID; } } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_SerializeClusterHdr * * Description : Serialize Fee cluster header parameters to write buffer. * * Inputs : uClrID 32-bit cluster ID. * uStartAddress Logical address of Fee cluster in Fls address space. * uClusteSize Size of Fee cluster in bytes. * * Outputs : pClrHdrPtr Pointer to write buffer. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static void Fee_SerializeClusterHdr(const uint32 uClrID, const Fls_AddressType uStartAddress, Fls_LengthType uClusteSize, uint8 *pClrHdrPtr) { uint32 u32CheckSum = 0UL; uint8 *pTargetEndPtr = NULL_PTR; pTargetEndPtr = FEE_OPERATIONADD(pClrHdrPtr, FEE_CLUSTER_OVERHEAD); /* Calculate the cluster header checksum */ u32CheckSum = FEE_CHECKSUM(uClrID, uStartAddress, uClusteSize); FEE_SERIALIZE( uClrID, uint32, pClrHdrPtr ) FEE_SERIALIZE( uStartAddress, Fls_AddressType, pClrHdrPtr ) FEE_SERIALIZE( uClusteSize, Fls_LengthType, pClrHdrPtr ) FEE_SERIALIZE( u32CheckSum, uint32, pClrHdrPtr ) /* Fill rest of the header with the erase pattern */ while(pClrHdrPtr < pTargetEndPtr) { *pClrHdrPtr = FEE_ERASED_VALUE; pClrHdrPtr++; } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_GetBlockIndex * * Description : Searches ordered list of Fee blocks and returns index of block. * with matching BlockNumber. * * Inputs : uBlockNumber Fee block number (FeeBlockNumber). * * Outputs : Fee block index. * 0xFFFF if uBlockNumber is invalid. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static uint16 Fee_GetBlockIndex( uint16 uBlockNumber ) { sint32 sLow = 0L; sint32 sHigh = (sint32)FEE_CRT_CFG_NR_OF_BLOCKS - 1; sint32 sMiddle = 0; uint16 uRetVal = 0xFFFFU; while( sLow <= sHigh ) { sMiddle = sLow + (( sHigh - sLow ) / 2); if( uBlockNumber < FEE_BLOCKCONFIG(sMiddle, blockNumber)) { sHigh = sMiddle - 1; } else if( uBlockNumber > FEE_BLOCKCONFIG(sMiddle, blockNumber) ) { sLow = sMiddle + 1; } else { uRetVal = (uint16)sMiddle; break; } } return( uRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_AlignToVirtualPageSize * * Description : Adjusts passed size so it's integer multiple of pre-configured + * FEE_VIRTUAL_PAGE_SIZE. * * Inputs : uBlockSize Fee block size (FeeBlockSize). * * Outputs : Adjusted Fee block size to integer multiple of FEE_VIRTUAL_PAGE_SIZE. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static uint16 Fee_AlignToVirtualPageSize( uint16 uBlockSize ) { /* Check whether the block size is integer multiple of FEE_VIRTUAL_PAGE_SIZE */ if((uBlockSize % FEE_VIRTUAL_PAGE_SIZE) != 0U) { uBlockSize = FEE_BLOCKSIZE; } else { /* block size is an integer multiple of FEE_VIRTUAL_PAGE_SIZE */ } return( (uint16)uBlockSize ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_CopyDataToPageBuffer * * Description : Copy data from user to internal write buffer and fills * rest of the write buffer with FEE_ERASED_VALUE. * * Inputs : pSourcePtr Pointer to user data buffer * pTargetPtr Pointer to internal write buffer * uLength Number of bytes to copy. * * Outputs : None. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static void Fee_CopyDataToPageBuffer( const uint8 *pSourcePtr, uint8 *pTargetPtr, uint16 uLength) { uint8 *pTargetEndPtr = FEE_OPERATIONADD(pTargetPtr, uLength); uint8 *pPageEndPtr = FEE_OPERATIONADD(pTargetPtr, FEE_VIRTUAL_PAGE_SIZE); /* Copy data to page buffer */ while(pTargetPtr < pTargetEndPtr) { *pTargetPtr = *pSourcePtr; pTargetPtr++; pSourcePtr++; } /* Fill rest of the page buffer with FEE_ERASED_VALUE */ while(pTargetPtr < pPageEndPtr) { *pTargetPtr = FEE_ERASED_VALUE; pTargetPtr++; } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_SerializeFlag * * Description : Serialize validation or invalidation flag to write buffer. * * Inputs : pTargetPtr Pointer to write buffer. * u8FlagPattern FEE_VALIDATED_VALUE or FEE_INVALIDATED_VALUE. * * Outputs : pTargetPtr Pointer to write buffer. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static void Fee_SerializeFlag(uint8 *pTargetPtr, const uint8 u8FlagPattern) { uint8 *pTargetEndPtr =FEE_OPERATIONADD(pTargetPtr, FEE_VIRTUAL_PAGE_SIZE); *pTargetPtr = u8FlagPattern; for( pTargetPtr++ ; pTargetPtr < pTargetEndPtr; pTargetPtr++ ) { *pTargetPtr = FEE_ERASED_VALUE; } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapClrVld * * Description : Validate current Fee cluster in current Fee cluster group by * writing FEE_VALIDATED_VALUE into flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job * MEMIF_JOB_FAILED Underlying Fls didn't accept the write * job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapClrVld( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uStartAddr = 0UL; /* Get start address of swap cluster */ uStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, startAddr); /* Serialize validation pattern to write buffer */ Fee_SerializeFlag( Fee_aDataBuffer, FEE_VALIDATED_VALUE ); /* Write validation pattern to flash */ if(Fls_Write((uStartAddr+FEE_CLUSTER_OVERHEAD ) - (2U*FEE_VIRTUAL_PAGE_SIZE), Fee_aDataBuffer, FEE_VIRTUAL_PAGE_SIZE) == ((Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls write job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } /* Schedule subsequent Fee job */ Fee_eJob = FEE_JOB_INT_SWAP_CLR_VLD_DONE; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapBlock * * Description : Copy next block from source to target cluster. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept the write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapBlock( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uDataAddr = 0UL; uint16 uBlockSize = 0U; uint16 uAlignedBlockSize = 0U; uint16 uBlockNumber = 0U; uint8 uBlockClusterGrp = 0U; boolean bImmediateBlock = (boolean)FALSE; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else Fee_BlockAssignmentType uBlockAssignment = FEE_PROJECT_RESERVED; #endif /* Find first valid or inconsistent block in same cluster group */ #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) while(Fee_uJobIntBlockIt < FEE_CRT_CFG_NR_OF_BLOCKS) #else while(Fee_uJobIntBlockIt < (FEE_CRT_CFG_NR_OF_BLOCKS + Fee_uForeignBlocksNumber)) #endif { /* get cluster group */ #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockClusterGrp = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, clrGrp); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < Fee_uJobIntBlockIt) { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockClusterGrp = FEE_FOREIGNBLOCKCONFIG(Fee_uJobIntBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, clrGrp); } else { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockClusterGrp = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, clrGrp); } #endif /* process only valid and inconsistent blocks from the current cluster */ if ((Fee_uJobIntClrGrpIt == uBlockClusterGrp) && ((FEE_BLOCK_VALID == FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus)) || (FEE_BLOCK_INCONSISTENT == FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus)) || (FEE_BLOCK_INCONSISTENT_COPY == FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus)) ) ) { break; } else { /* No match. Try next one... */ } Fee_uJobIntBlockIt++; } #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) if(Fee_uJobIntBlockIt == FEE_CRT_CFG_NR_OF_BLOCKS) #else if(Fee_uJobIntBlockIt == FEE_OPERATIONADD(FEE_CRT_CFG_NR_OF_BLOCKS, Fee_uForeignBlocksNumber)) #endif { /* No more matching blocks. Validate the cluster */ eRetVal = Fee_JobIntSwapClrVld(); } else { #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockSize); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < Fee_uJobIntBlockIt) { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockSize = FEE_FOREIGNBLOCKCONFIG(Fee_uJobIntBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, blockSize); } else { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockSize); } #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ bImmediateBlock = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, immediateData); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < Fee_uJobIntBlockIt) { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ bImmediateBlock = FEE_FOREIGNBLOCKCONFIG(Fee_uJobIntBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, immediateData); } else { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ bImmediateBlock = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, immediateData); } #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockNumber = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockNumber); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < Fee_uJobIntBlockIt) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockNumber = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockNumber); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockNumber = FEE_FOREIGNBLOCKCONFIG(Fee_uJobIntBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, blockNumber); } #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockAssignment = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockAssignment); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < Fee_uJobIntBlockIt) { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockAssignment = FEE_FOREIGNBLOCKCONFIG(Fee_uJobIntBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, blockAssignment); } else { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockAssignment = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockAssignment); } #endif #endif #if (STD_ON == FEE_LEGACY_MODE) if(((boolean)TRUE == bImmediateBlock) || (FEE_BLOCK_VALID == FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus)) \ ) #else /* Data space no more allocated even for inconsistent immediate (pre-erased) blocks */ if(FEE_BLOCK_VALID == FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus)) #endif { /* Align Fee block size to the virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* Calculate data address */ uDataAddr = FEE_OPERATIONSUB(Fee_uJobIntDataAddr, uAlignedBlockSize); /* Update the block address info */ Fee_uJobIntDataAddr = uDataAddr; /* Initialize the data transfer iterator */ Fee_uJobIntAddrIt = uDataAddr; } else { #if (STD_ON == FEE_LEGACY_MODE) /* Don't allocate data space for inconsistent and not immediate block */ #else /* Don't allocate data space for inconsistent block */ #endif uDataAddr = 0U; } /* Serialize block header to the write buffer */ Fee_SerializeBlockHdr( uBlockNumber, uBlockSize, uDataAddr, bImmediateBlock, #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else uBlockAssignment, #endif Fee_aDataBuffer ); if( FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_INVALID || FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_INCONSISTENT || FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_HEADER_INVALID || FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_INVALIDATED || FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_HEADER_BLANK || #if (STD_OFF == FEE_MARK_EMPTY_BLOCKS_INVALID) FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_NEVER_WRITTEN || FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_INCONSISTENT_COPY #else FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) == FEE_BLOCK_INCONSISTENT_COPY #endif ) { /* Nothing to read. Move on to next block */ Fee_uJobIntBlockIt++; Fee_eJob = FEE_JOB_INT_SWAP_BLOCK; } else { /* Read block data */ Fee_eJob = FEE_JOB_INT_SWAP_DATA_READ; } /* Write header to flash */ if( ((Std_ReturnType)E_OK) == Fls_Write( Fee_uJobIntHdrAddr, Fee_aDataBuffer, FEE_BLOCK_OVERHEAD-(2U*FEE_VIRTUAL_PAGE_SIZE)) ) { /* Fls write job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } else { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } /* Move on to next block header */ Fee_uJobIntHdrAddr = FEE_OPERATIONADD(Fee_uJobIntHdrAddr, FEE_BLOCK_OVERHEAD); } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapClrFmt * * Description : Format current Fee cluster in current Fee cluster group by * writing cluster header into flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept the write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapClrFmt( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uStartAddr = 0UL; Fls_LengthType uLength = 0UL; uint32 uActClrID = 0UL; uStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, startAddr); uLength = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, length); uActClrID = FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClrID); /* Build cluster header with new uActClrID + 1 */ Fee_SerializeClusterHdr( uActClrID+1U, uStartAddr, uLength, Fee_aDataBuffer ); /* Write the cluster header to flash */ if((Fls_Write( uStartAddr, Fee_aDataBuffer, FEE_CLUSTER_OVERHEAD-(2U*FEE_VIRTUAL_PAGE_SIZE)) == (Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } /* Schedule cluster format done job */ Fee_eJob = FEE_JOB_INT_SWAP_BLOCK; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapClrErase * * Description : Erase current Fee cluster in current Fee cluster group by erasing flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase job * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapClrErase( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uStartAddr = 0UL; Fls_LengthType uLength = 0UL; uStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, startAddr); uLength = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, length); /* Erase cluster */ if( ((Std_ReturnType)E_OK) == Fls_Erase( uStartAddr, uLength ) ) { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } else { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } /* Schedule cluster format job */ Fee_eJob = FEE_JOB_INT_SWAP_CLR_FMT; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwap * * Description : Initialize the cluster swap internal operation on * current cluster group. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase job * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwap( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; /* Store type of original job so Fee can re-schedule this job once the swap is complete */ Fee_eJobIntOriginalJob = Fee_eJob; /* Reset the block iterator */ Fee_uJobIntBlockIt = 0U; /* Get cluster index the block belongs to */ Fee_uJobIntClrIt = FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClr); /* Calculate index of cluster to swap to */ Fee_uJobIntClrIt++; if( Fee_uJobIntClrIt == FEE_CLRGRP(Fee_uJobIntClrGrpIt, clrCount) ) { /* Cluster roll over */ Fee_uJobIntClrIt = 0U; } else { /* Do nothing */ } /* Calculate header and data address iterators */ Fee_uJobIntHdrAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, startAddr); Fee_uJobIntDataAddr = FEE_OPERATIONADD(Fee_uJobIntHdrAddr, FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, length)); /* Move on to the first block header */ Fee_uJobIntHdrAddr += FEE_CLUSTER_OVERHEAD; /* Erase the swap cluster */ eRetVal = Fee_JobIntSwapClrErase(); return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanBlockHdrRead * * Description : Read the Fee block header into internal buffer. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the read job * MEMIF_JOB_FAILED Underlying Fls didn't accept the read job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanBlockHdrRead( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; /* Read the block header */ if( ((Std_ReturnType)E_OK) != Fls_Read( Fee_uJobIntAddrIt, Fee_aDataBuffer, FEE_BLOCK_OVERHEAD ) ) { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } Fee_eJob = FEE_JOB_INT_SCAN_BLOCK_HDR_PARSE; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanClrErase * * Description : Erase first Fee cluster in current cluster group. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase job * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanClrErase( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uStartAddr = 0UL; Fls_LengthType uLength = 0UL; /* Get address and size of first cluster in the current cluster group */ uStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, 0, startAddr); uLength = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, 0, length); if( ((Std_ReturnType)E_OK) == Fls_Erase( uStartAddr, uLength ) ) { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } else { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } /* Schedule cluster format job */ Fee_eJob = FEE_JOB_INT_SCAN_CLR_FMT; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanClr * * Description : Scan active cluster of current cluster group or erase and format * first cluster if an active cluster can't be found. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase or read job. * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase or read job. * MEMIF_JOB_OK There is no more cluster groups to scan. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanClr( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; uint8 uClrIndex = (uint8)0; Fls_AddressType uClrStartAddr = 0UL; Fls_LengthType uClrLength = 0UL; if(Fee_uJobIntClrGrpIt != FEE_NUMBER_OF_CLUSTER_GROUPS) { if(FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClrID) != 0U) { /* Active cluster found */ /* Get index of active cluster */ uClrIndex = FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClr); uClrStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, uClrIndex, startAddr); /* Calculate logical address of first block header in active cluster */ Fee_uJobIntAddrIt = FEE_OPERATIONADD(FEE_CLUSTER_OVERHEAD, uClrStartAddr); /* Initialize the block header pointer */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt) = Fee_uJobIntAddrIt; /* Initialize the block data pointer */ uClrLength = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, uClrIndex, length); FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) = FEE_OPERATIONADD(uClrStartAddr, uClrLength); /* Active cluster found so read the first block header */ eRetVal = Fee_JobIntScanBlockHdrRead(); } else { /* call the cluster format notification */ FEE_NVM_CLUSTER_FORMAT_NOTIFICATION /* No active cluster found in current group so erase and format the first one... */ eRetVal = Fee_JobIntScanClrErase(); } } else { /* Nor more cluster groups to scan */ Fee_eJob = FEE_JOB_DONE; } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanClrFmt * * Description : Format first Fee cluster in current Fee cluster group by writing * cluster header into flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase or read job. * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase or read job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanClrFmt( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uStartAddr = 0UL; Fls_LengthType uLength = 0UL; /* Get address and size of first cluster in the current cluster group */ uStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, 0, startAddr); uLength = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, 0, length); /* Build cluster header with clusterID = 1 */ Fee_SerializeClusterHdr( 1U, uStartAddr, uLength, Fee_aDataBuffer ); /* Make the cluster valid right away as it's empty anyway... */ Fee_SerializeFlag( (Fee_aDataBuffer+FEE_CLUSTER_OVERHEAD)-(2U*FEE_VIRTUAL_PAGE_SIZE), FEE_VALIDATED_VALUE); /* Write the cluster header to flash */ if(Fls_Write( uStartAddr, Fee_aDataBuffer, FEE_CLUSTER_OVERHEAD-FEE_VIRTUAL_PAGE_SIZE) == ((Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } /* Schedule cluster format done job */ Fee_eJob = FEE_JOB_INT_SCAN_CLR_FMT_DONE; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanClrFmtDone * * Description : Finalize format of first Fee cluster in current Fee cluster group. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase or * read job * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase * or read job * MEMIF_JOB_OK There is no more cluster groups to scan. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanClrFmtDone( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uClrStartAddr = 0UL; Fls_LengthType uClrLength = 0UL; /* Assign Index and ID of active cluster */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClr) = 0U; FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClrID) = 1U; uClrStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, 0, startAddr); uClrLength = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, 0, length); /* Initialize the block header pointer */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt) = FEE_OPERATIONADD(uClrStartAddr, FEE_CLUSTER_OVERHEAD); /* Initialize the block data pointer */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) = FEE_OPERATIONADD(uClrStartAddr, uClrLength); /* Move on to next cluster group */ Fee_uJobIntClrGrpIt++; /* Scan next cluster group if any */ eRetVal = Fee_JobIntScanClr(); return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanBlockHdrParse * * Description : Parse Fee block header. * * Inputs : bBufferValid FALSE if previous Fls read job has failed. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase or * read job * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase * or read job * MEMIF_JOB_OK There is no more cluster groups to scan. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanBlockHdrParse(const boolean bBufferValid) { MemIf_JobResultType eRetVal = MEMIF_JOB_FAILED; Fee_BlockStatusType eBlockStatus; uint16 uBlockNumber = 0U; uint16 uBlockSize = 0U; Fls_AddressType uDataAddr = 0UL; boolean bImmediateData = (boolean)FALSE; uint16 uBlockIndex = 0U; uint16 uAlignedBlockSize = 0U; uint16 uBlockRuntimeInfoIndex = 0U; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else uint8 uBlockAssignment = (uint8)FEE_PROJECT_RESERVED; uint16 uForeignBlockIndex = 0U; boolean bForeign = (boolean)FALSE; boolean bForeignBlockOverflow = (boolean)FALSE; #endif boolean bFeeSwapNeeded = (boolean)FALSE; /* Deserialize block header from read buffer */ eBlockStatus = Fee_DeserializeBlockHdr( &uBlockNumber, &uBlockSize, &uDataAddr, &bImmediateData, #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else /* @violates @ref Fee_c_REF_4 Taking address of near auto variable. */ &uBlockAssignment, #endif Fee_aDataBuffer ); #if (STD_OFF == FEE_LEGACY_MODE) /* Fee_bSwapToBePerformed was set because previously processed block wasn't properly recognized. => perform a swap to prevent a risk that this block overlaps the Reserved Area. */ #else /* Clear swap variable except for last header */ if(eBlockStatus == FEE_BLOCK_HEADER_BLANK ) { /* Do nothing. */ } else { Fee_bSwapToBePerformed = (boolean)FALSE; } #endif if( (eBlockStatus == FEE_BLOCK_HEADER_INVALID) || (bBufferValid == (boolean)FALSE)) { if(Fee_bSwapToBePerformed == ((boolean)TRUE)) { Fee_bSwapToBePerformed = (boolean)FALSE; FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) = FEE_OPERATIONADD(Fee_uJobIntAddrIt, (2U * FEE_BLOCK_OVERHEAD)); /* End of header list so move on to next cluster group */ Fee_uJobIntClrGrpIt++; eRetVal = Fee_JobIntScanClr(); } else { /* Invalidate the block index so Fee won't skip the Fee_uJobBlockIndex block */ Fee_uJobBlockIndex = 0xffffU; /* Move on to next block header */ Fee_uJobIntAddrIt = FEE_OPERATIONADD(Fee_uJobIntAddrIt, FEE_BLOCK_OVERHEAD); /* Update the block header pointer */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt) = Fee_uJobIntAddrIt; /* Set swap-to-be-performed flag */ Fee_bSwapToBePerformed = (boolean)TRUE; /* Read next header */ eRetVal = Fee_JobIntScanBlockHdrRead(); } } else if(eBlockStatus == FEE_BLOCK_HEADER_BLANK) { /* If SwapToBePerformed is set, it means that last header is corrupted and ONLY now the uDataAddrIt variable will be updated to cause swap. */ if(Fee_bSwapToBePerformed == ((boolean)FALSE)) { /* Do nothing. */ } else { Fee_bSwapToBePerformed = (boolean)FALSE; FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) = FEE_OPERATIONADD(Fee_uJobIntAddrIt, (2U * FEE_BLOCK_OVERHEAD)); } /* End of header list so move on to next cluster group */ Fee_uJobIntClrGrpIt++; eRetVal = Fee_JobIntScanClr(); } else { /* Look for found block in the block configuration */ uBlockIndex = Fee_GetBlockIndex( uBlockNumber ); #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else /* initialize bForeign as false */ bForeign = (boolean)FALSE; /* check if block was found in the configuration */ if(uBlockIndex != 0xFFFFU) { /* Do nothing. */ } else { /* check if block is foreign*/ #if (STD_OFF == FEE_BOOTLOADER_CONFIG) if (FEE_PROJECT_BOOTLOADER == (Fee_BlockAssignmentType)uBlockAssignment) #else if (FEE_PROJECT_APPLICATION == (Fee_BlockAssignmentType)uBlockAssignment) #endif { /* block is foreign */ bForeign = (boolean)TRUE; /* search for block index in the foreign blocks config */ if (1UL > Fee_uForeignBlocksNumber) { /* Do nothing. */ } else { while(uBlockNumber < Fee_uForeignBlocksNumber) { if(uBlockNumber == FEE_FOREIGNBLOCKCONFIG(uBlockNumber, blockNumber)) { uForeignBlockIndex = uBlockNumber; break; } uBlockNumber++; } } if(uForeignBlockIndex != 0xFFFFU) { /* Do nothing. */ } else { /* assume there is no overflow */ bForeignBlockOverflow = (boolean)FALSE; /* it's a new foreign block */ if(FEE_OPERATIONSUB(FEE_MAX_NR_OF_BLOCKS, FEE_CRT_CFG_NR_OF_BLOCKS) < Fee_uForeignBlocksNumber) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_FOREIGN_BLOCKS_OVF); #endif /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION /* set job failed*/ bForeignBlockOverflow = (boolean)TRUE; } else { uForeignBlockIndex = Fee_uForeignBlocksNumber; /* update the foreign block config */ FEE_FOREIGNBLOCKCONFIG(uForeignBlockIndex, blockNumber) = uBlockNumber; FEE_FOREIGNBLOCKCONFIG(uForeignBlockIndex, blockSize)= uBlockSize; FEE_FOREIGNBLOCKCONFIG(uForeignBlockIndex, clrGrp) = Fee_uJobIntClrGrpIt; FEE_FOREIGNBLOCKCONFIG(uForeignBlockIndex, immediateData) = bImmediateData; FEE_FOREIGNBLOCKCONFIG(uForeignBlockIndex, blockAssignment) = (Fee_BlockAssignmentType)uBlockAssignment; /* increment the number of foreign blocks */ Fee_uForeignBlocksNumber = FEE_OPERATIONADD(Fee_uForeignBlocksNumber, 1U); } } } } if(bForeignBlockOverflow == (boolean)FALSE) { #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) if(uBlockIndex != 0xFFFFU) #else if( (uBlockIndex != 0xFFFFU) || bForeign == ((boolean)TRUE)) #endif { /* prepare index to be used for the runtime info data*/ #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) uBlockRuntimeInfoIndex = uBlockIndex; #else if(bForeign == (boolean)TRUE) { uBlockRuntimeInfoIndex = FEE_OPERATIONADD(FEE_CRT_CFG_NR_OF_BLOCKS, uForeignBlockIndex); } else { uBlockRuntimeInfoIndex = uBlockIndex; } #endif uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* Check whether found block belongs to current cluster group, and its size and type match the configuration, and its data pointer points to an acceptable area.*/ bFeeSwapNeeded = (boolean)FALSE; if (((FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt)-uAlignedBlockSize) >=uDataAddr) && ((FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt)+(2U*FEE_BLOCK_OVERHEAD)) <= uDataAddr)) { #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if(bForeign == (boolean)TRUE) { /* Do nothing. */ } else #endif { if(Fee_uJobIntClrGrpIt == (FEE_BLOCKCONFIG(uBlockIndex, clrGrp)) && (uBlockSize == FEE_BLOCKCONFIG(uBlockIndex, blockSize)) && (bImmediateData == FEE_BLOCKCONFIG(uBlockIndex, immediateData))) { bFeeSwapNeeded = (boolean)FALSE; } else { bFeeSwapNeeded = (boolean)TRUE; } } } else { bFeeSwapNeeded = (boolean)TRUE; } /* check if swap is needed */ if(bFeeSwapNeeded == (boolean)TRUE) { /* Block header doesn't match Fee config or the FEE algorithm during next write cluster swap occurs */ Fee_bSwapToBePerformed = (boolean)TRUE; } else { /* Update block run-time information */ #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else /* Update block run-time information when: - new valid block is found - block was invalidated - block contains immediate data (basically just ignore INCONSISTENT non-immediate blocks) */ sint8 sRetVal = FALSE; Fls_LengthType uAvailClrSpace = 0UL; uint32 uReservedSpace = 0UL; uint32 uIdx = 0UL; uIdx = ((uint32)uBlockRuntimeInfoIndex) >> 5U; #if (STD_ON == FEE_LEGACY_MODE) if( (eBlockStatus != FEE_BLOCK_INCONSISTENT) || (bImmediateData == ((boolean)TRUE))) #else /* no special treatment of immediate data needed any more */ if(eBlockStatus != FEE_BLOCK_INCONSISTENT) #endif { /* Mark invalidated blocks as invalid */ if(eBlockStatus != FEE_BLOCK_INVALIDATED) { /* Do nothing */ } else { eBlockStatus = FEE_BLOCK_INVALID; } #endif FEE_BLOCKINFO(uBlockRuntimeInfoIndex, eBlockStatus) = eBlockStatus; /* Update the block data pointer */ FEE_BLOCKINFO(uBlockRuntimeInfoIndex, uDataAddr) = uDataAddr; FEE_BLOCKINFO(uBlockRuntimeInfoIndex, uInvalidAddr) = FEE_OPERATIONSUB((Fee_uJobIntAddrIt + FEE_BLOCK_OVERHEAD), FEE_VIRTUAL_PAGE_SIZE); FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) = uDataAddr; #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else } else { /* header is valid but data is corrupted, in this case it is important to update uDataAddrIt to avoid corrupted space, cluster swap is not needed */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) = uDataAddr; } #endif #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) && (STD_OFF == FEE_LEGACY_MODE) /* Check for blocks potentially overlaping the Reserved Area */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt) = FEE_OPERATIONADD(Fee_uJobIntAddrIt, FEE_BLOCK_OVERHEAD); /* Reserved space of cluster group*/ uReservedSpace = FEE_CLRGRP(Fee_uJobIntClrGrpIt, reservedSize); /* Calculate available space in active cluster */ uAvailClrSpace = FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) - FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt); if(uAvailClrSpace < FEE_OPERATIONADD(FEE_BLOCK_OVERHEAD, uReservedSpace)) { sRetVal = TRUE; } if(sRetVal == FALSE) { /* Do nothing */ } else { if( !bImmediateData ) { /* Non-immediate data found in the Reserved Area => swap */ Fee_bSwapToBePerformed = (boolean)TRUE; /* Note that if FEE_LEGACY_MODE == STD_OFF, Fee_bSwapToBePerformed is not reset to FALSE upon recognition of the next written header => the swap is mandatory. */ } else { /* Mark the imm. block as touching the Reserved Area (we are esp. interested only about inconsistent imm. blocks here, but it does not matter if also consistent imm. block will be marked) */ Fee_aReservedAreaTouched[ uIdx ] |= (uint32)(0x00000001UL << ((uint32)uBlockRuntimeInfoIndex & 0x1FUL)); } } #endif } } else { /* Invalid block number (removed from Fee config...) next write cluster swap occurs */ Fee_bSwapToBePerformed = (boolean)TRUE; } /* Move on to next block header */ Fee_uJobIntAddrIt = FEE_OPERATIONADD(Fee_uJobIntAddrIt, FEE_BLOCK_OVERHEAD); /* Update the block header pointer */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt) = Fee_uJobIntAddrIt; /* Read next header */ eRetVal = Fee_JobIntScanBlockHdrRead(); #if (FEE_SWAP_FOREIGN_BLOCKS_ENABLED == STD_ON) } else { /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; } #endif } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanClrHdrRead * * Description : Read Fee cluster header. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase or * read job. * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase * or read job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanClrHdrRead( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uReadAddress = 0UL; /* Get address of current cluster */ uReadAddress = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, startAddr); if(Fls_Read( uReadAddress, Fee_aDataBuffer, FEE_CLUSTER_OVERHEAD ) != ((Std_ReturnType)E_NOT_OK)) { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } else { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } /* Schedule cluster scan job */ Fee_eJob = FEE_JOB_INT_SCAN_CLR_HDR_PARSE; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScan * * Description : Initialize the cluster scan job. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase or * read job. * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase * or read job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScan( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; /* Reset iterators to first cluster of first cluster group */ Fee_uJobIntClrGrpIt = 0U; Fee_uJobIntClrIt = 0U; /* Schedule reading of first cluster header */ eRetVal = Fee_JobIntScanClrHdrRead(); return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntScanClrHdrParse * * Description : Parse Fee cluster header. * * Inputs : bBufferValid FALSE if previous Fls read job has failed. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the erase or * read job. * MEMIF_JOB_FAILED Underlying Fls didn't accept the erase * or read job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntScanClrHdrParse(const boolean bBufferValid) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fee_ClusterStatusType eClrStatus = FEE_CLUSTER_VALID; uint32 uClrID = 0UL; Fls_AddressType uClrStartAddr = 0UL; Fls_LengthType uClrSize = 0UL; Fls_AddressType uCfgStartAddr = 0UL; Fls_LengthType uCfgClrSize = 0UL; /* Get configured cluster start address and size */ uCfgStartAddr = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, startAddr); uCfgClrSize = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, length); /* Deserialize cluster parameters from the read buffer */ eClrStatus = Fee_DeserializeClusterHdr( &uClrID, &uClrStartAddr, &uClrSize, Fee_aDataBuffer ); if(FEE_PARAMDIF) { /* Found valid and active cluster */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClr) = Fee_uJobIntClrIt; FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClrID) = uClrID; } else { /* Invalid, inconsistent, or cluster with low ID */ } /* Move on to next cluster */ Fee_uJobIntClrIt++; if(Fee_uJobIntClrIt == FEE_CLRGRP(Fee_uJobIntClrGrpIt, clrCount) ) { /* Move on to next cluster group */ Fee_uJobIntClrGrpIt++; Fee_uJobIntClrIt = 0U; } else { /* next cluster in current cluster group */ } if(Fee_uJobIntClrGrpIt == FEE_NUMBER_OF_CLUSTER_GROUPS) { Fee_uJobIntClrGrpIt = 0U; /* Done reading all cluster headers. Now scan active clusters */ eRetVal = Fee_JobIntScanClr(); } else { /* Read next cluster header */ eRetVal = Fee_JobIntScanClrHdrRead(); } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobRead * * Description : Read Fee block. * * Inputs : bBufferValid FALSE if previous Fls read job has failed. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the read job * MEMIF_JOB_FAILED Underlying Fls didn't accept read job * MEMIF_BLOCK_INVALID Requested Fee block is invalid * MEMIF_BLOCK_INCONSISTENT Requested Fee block is inconsistent. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobRead( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_FAILED; Fee_BlockStatusType eBlockStatus = FEE_BLOCK_VALID; Fls_AddressType uBlockAddress = 0UL; eBlockStatus = FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus); uBlockAddress = FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr); if(eBlockStatus == FEE_BLOCK_VALID) { if(Fls_Read( uBlockAddress+Fee_uJobBlockOffset, Fee_pJobReadDataDestPtr, Fee_uJobBlockLength) != ((Std_ReturnType)E_NOT_OK)) { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } else { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } } #if (STD_ON == FEE_MARK_EMPTY_BLOCKS_INVALID) #else else if(eBlockStatus == FEE_BLOCK_NEVER_WRITTEN) { /* in case the block was never written */ eRetVal = MEMIF_BLOCK_INCONSISTENT; } #endif /* (STD_ON == FEE_MARK_EMPTY_BLOCKS_INVALID) */ else if(eBlockStatus == FEE_BLOCK_INVALID) { eRetVal = MEMIF_BLOCK_INVALID; } else if( (eBlockStatus == FEE_BLOCK_INCONSISTENT) || (eBlockStatus == FEE_BLOCK_INCONSISTENT_COPY) ) { #if (STD_ON == FEE_LEGACY_MODE) #if (STD_OFF == FEE_MARK_EMPTY_BLOCKS_INVALID) #else /* In the LEGACY mode, if immediate data was only pre-erased, but never written, Fee must return MEMIF_BLOCK_INCONSISTENT state */ if(FEE_BLOCKCONFIG(Fee_uJobBlockIndex, immediateData)) { eRetVal = MEMIF_BLOCK_INVALID; } else #endif /* (STD_OFF == FEE_MARK_EMPTY_BLOCKS_INVALID) */ { eRetVal = MEMIF_BLOCK_INCONSISTENT; } #else /* No special treatment of immediate blocks needed anymore */ eRetVal = MEMIF_BLOCK_INCONSISTENT; #endif /* ( STD_ON == FEE_LEGACY_MODE ) */ } else { /* Something is wrong... MEMIF_JOB_FAILED */ } /* There is no consecutive job to schedule */ Fee_eJob = FEE_JOB_DONE; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapBlockVld * * Description : Validate Fee block. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job * MEMIF_JOB_FAILED Underlying Fls did not accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapBlockVld( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; /* Serialize validation pattern to buffer */ Fee_SerializeFlag( Fee_aDataBuffer, FEE_VALIDATED_VALUE ); /* Write header to flash */ if(Fls_Write( Fee_uJobIntHdrAddr-(2U*FEE_VIRTUAL_PAGE_SIZE), Fee_aDataBuffer, FEE_VIRTUAL_PAGE_SIZE) != ((Std_ReturnType)E_NOT_OK)) { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } else { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } /* Finalize the write operation */ Fee_eJob = FEE_JOB_INT_SWAP_BLOCK; return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapDataRead * * Description : Read data from source cluster to internal Fee buffer. * * Inputs : bBufferValid FALSE if previous Fls read job has failed. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the read job * MEMIF_JOB_FAILED Underlying Fls didn't accept read job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapDataRead(const boolean bBufferValid) { MemIf_JobResultType eRetVal = MEMIF_JOB_FAILED; Fls_AddressType uReadAddr = 0UL; uint16 uAlignedBlockSize = 0U; uint16 uBlockSize = 0U; /* Get size of swaped block */ #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockSize); #else if (Fee_uJobIntBlockIt < FEE_CRT_CFG_NR_OF_BLOCKS) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobIntBlockIt, blockSize); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockSize = FEE_FOREIGNBLOCKCONFIG(Fee_uJobIntBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS,blockSize); } #endif /* Get size of swaped block aligned to virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* Calculate remaining number of bytes to read */ Fee_uJobBlockLength = FEE_OPERATIONSUB((Fee_uJobIntDataAddr + uAlignedBlockSize), Fee_uJobIntAddrIt); if(bBufferValid == (boolean)FALSE) { /* There was error while reading the source cluster. Change the block status to FEE_BLOCK_INCONSISTENT_COPY to mark the status change during swap, leave the block (in flash) INCONSITENT and move on to next block */ FEE_BLOCKINFO(Fee_uJobIntBlockIt, eBlockStatus) = FEE_BLOCK_INCONSISTENT_COPY; Fee_uJobIntBlockIt++; eRetVal = Fee_JobIntSwapBlock(); } else if(Fee_uJobBlockLength == 0U) { /* No more bytes to copy. Validate the block and move on to next block... */ Fee_uJobIntBlockIt++; eRetVal = Fee_JobIntSwapBlockVld(); } else { if(FEE_DATA_BUFFER_SIZE >= Fee_uJobBlockLength) { /* Block data fits into the buffer */ } else { Fee_uJobBlockLength = FEE_DATA_BUFFER_SIZE; } /* Calculate source address */ uReadAddr = FEE_OPERATIONSUB(FEE_BLOCKINFO(Fee_uJobIntBlockIt, uDataAddr) + Fee_uJobIntAddrIt, Fee_uJobIntDataAddr); /* Read the block data */ if(Fls_Read( uReadAddr, Fee_aDataBuffer, Fee_uJobBlockLength ) == ((Std_ReturnType)E_OK)) { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } else { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } Fee_eJob = FEE_JOB_INT_SWAP_DATA_WRITE; } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapDataWrite * * Description : Write data from internal Fee buffer to target cluster. * * Inputs : bBufferValid FALSE if previous Fls read job has failed. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapDataWrite(const boolean bBufferValid) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; if( !bBufferValid ) { eRetVal = Fee_JobIntSwapDataRead( (boolean)FALSE ); } else { if( (Fls_Write( Fee_uJobIntAddrIt, Fee_aDataBuffer, Fee_uJobBlockLength ) == (Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } Fee_uJobIntAddrIt = FEE_OPERATIONADD(Fee_uJobIntAddrIt, Fee_uJobBlockLength); Fee_eJob = FEE_JOB_INT_SWAP_DATA_READ; } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobIntSwapClrVldDone * * Description : Finalize cluster validation. * * Inputs : bBufferValid FALSE if previous Fls read job has failed. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobIntSwapClrVldDone( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; uint16 uBlockIt = 0U; Fls_AddressType uHdrAddrIt = 0UL; Fls_AddressType uDataAddrIt = 0UL; uint16 uBlockSize = 0U; uint16 uAlignedBlockSize = 0U; #if (STD_OFF == FEE_LEGACY_MODE) #else boolean bImmediateBlock = (boolean)FALSE; #endif uint8 uBlockClusterGrp = 0U; #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) && (STD_OFF == FEE_LEGACY_MODE) /* Swap is done => re-initialize info about the blocks touching the Reserved Area within a cluster group where the swap has happened. */ Fee_UntouchReservedAreaByClrGrp( Fee_uJobIntClrGrpIt ); #endif uHdrAddrIt = FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, startAddr); uDataAddrIt = FEE_OPERATIONADD(uHdrAddrIt, FEE_CLRGRPS(Fee_uJobIntClrGrpIt, Fee_uJobIntClrIt, length)); /* Move on to the first block header */ uHdrAddrIt = FEE_OPERATIONADD(uHdrAddrIt, FEE_CLUSTER_OVERHEAD); /* Sync block info */ #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) while(uBlockIt < FEE_CRT_CFG_NR_OF_BLOCKS ) #else while( uBlockIt < (FEE_CRT_CFG_NR_OF_BLOCKS + Fee_uForeignBlocksNumber)) #endif { #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockClusterGrp = FEE_BLOCKCONFIG(uBlockIt, clrGrp); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < uBlockIt) { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockClusterGrp = FEE_FOREIGNBLOCKCONFIG(uBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, clrGrp); } else { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockClusterGrp = FEE_BLOCKCONFIG(uBlockIt, clrGrp); } #endif if(Fee_uJobIntClrGrpIt == uBlockClusterGrp) { /* Valid blocks and inconsistent blocks with allocated data were copied, update the block info and internal pointers accordingly. */ if( (FEE_BLOCK_VALID == FEE_BLOCKINFO(uBlockIt, eBlockStatus)) || (FEE_BLOCK_INCONSISTENT == FEE_BLOCKINFO(uBlockIt, eBlockStatus)) || (FEE_BLOCK_INCONSISTENT_COPY == FEE_BLOCKINFO(uBlockIt, eBlockStatus)) ) { /* Sync uInvalidAddr */ FEE_BLOCKINFO(uBlockIt, uInvalidAddr) = FEE_OPERATIONSUB((uHdrAddrIt + FEE_BLOCK_OVERHEAD), FEE_VIRTUAL_PAGE_SIZE); /* check if block is immediate */ #if (STD_OFF == FEE_LEGACY_MODE) #else #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ bImmediateBlock = FEE_BLOCKCONFIG(uBlockIt, immediateData); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < uBlockIt) { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ bImmediateBlock = FEE_FOREIGNBLOCKCONFIG(uBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, immediateData); } else { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ bImmediateBlock = FEE_BLOCKCONFIG(uBlockIt, immediateData); } #endif #endif /* Update the block data address info */ if( (FEE_BLOCK_VALID == FEE_BLOCKINFO(uBlockIt, eBlockStatus)) || (FEE_BLOCK_INCONSISTENT_COPY == FEE_BLOCKINFO(uBlockIt, eBlockStatus)) #if (STD_ON == FEE_LEGACY_MODE) || ( ((boolean)TRUE == bImmediateBlock) && (FEE_BLOCK_INCONSISTENT == FEE_BLOCKINFO(uBlockIt, eBlockStatus)) ) #endif ) { #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(uBlockIt, blockSize); #else if (FEE_CRT_CFG_NR_OF_BLOCKS < uBlockIt) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(uBlockIt, blockSize); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockSize = FEE_FOREIGNBLOCKCONFIG(uBlockIt-FEE_CRT_CFG_NR_OF_BLOCKS, blockSize); } #endif /* Align block size to the virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* "Allocate" data already swapped (written to the flash) */ uDataAddrIt = FEE_OPERATIONSUB(uDataAddrIt, uAlignedBlockSize); if(FEE_BLOCKINFO(uBlockIt, eBlockStatus) != FEE_BLOCK_INCONSISTENT_COPY) { /* store the data address to the block runtime record */ FEE_BLOCKINFO(uBlockIt, uDataAddr) = uDataAddrIt; } else { /* Damaged data read during copy, but already allocated => inconsistent */ FEE_BLOCKINFO(uBlockIt, eBlockStatus) = FEE_BLOCK_INCONSISTENT; /* Mark inconsistency in the runtime info (no data) for the next swap attempt */ FEE_BLOCKINFO(uBlockIt, uDataAddr) = 0U; } } else { /* (Inconsistent plain block in LEGACY == ON) or (Inconsistent plain or immediate block in LEGACY == OFF) -- no data written (swapped, allocated)/available */ FEE_BLOCKINFO(uBlockIt, uDataAddr) = 0U; } /* Advance the header pointer */ uHdrAddrIt = FEE_OPERATIONADD(uHdrAddrIt, FEE_BLOCK_OVERHEAD); } else { /* Not a usable block */ /* clear the addresses of the block not present in the new active cluster */ FEE_BLOCKINFO(uBlockIt, uDataAddr) = 0U; FEE_BLOCKINFO(uBlockIt, uInvalidAddr) = 0U; } } uBlockIt++; } /* Switch to the new cluster */ FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClr) = Fee_uJobIntClrIt; FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uActClrID)++; FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uHdrAddrIt) = uHdrAddrIt; FEE_CLRGRPINFO(Fee_uJobIntClrGrpIt, uDataAddrIt) = uDataAddrIt; /* restore original Fee_eJob */ if(Fee_eJobIntOriginalJob != FEE_JOB_INT_SCAN_CLR) { /* Do nothing */ } else { Fee_uJobIntClrGrpIt++; } /* Internal job has finished so transition from MEMIF_BUSYINTERNAL to MEMIF_BUSY */ Fee_eModuleStatus = MEMIF_BUSY; /* And now cross fingers and re-schedule original job ... */ Fee_eJob = Fee_eJobIntOriginalJob; eRetVal = Fee_JobSchedule(); return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobWriteHdr * * Description : Write Fee block header to flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobWriteHdr( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_FAILED; uint16 uBlockSize = 0U; uint16 uAlignedBlockSize = 0U; uint8 uClrGrpIndex = (uint8)0; Fls_AddressType uDataAddr = 0U; Fls_AddressType uHdrAddr = 0U; #if (STD_OFF == FEE_LEGACY_MODE) #else Fls_LengthType uAvailClrSpace = 0UL; #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if (FEE_CRT_CFG_NR_OF_BLOCKS <= Fee_uJobBlockIndex) { #if (FEE_DEV_ERROR_DETECT == STD_OFF) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO); #endif /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { #endif /* Index of cluster group the Fee block belongs to */ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); #if (STD_OFF == FEE_LEGACY_MODE) #else /* Calculate available space in active cluster */ uAvailClrSpace = FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt) - FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt); #endif /* Get size of Fee block */ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockSize); /* Align Fee block size to the virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); #if (STD_OFF == FEE_LEGACY_MODE) if((boolean)Fee_ReservedAreaWritable() == (boolean)TRUE) #else /* One FEE_BLOCK_OVERHEAD must be left blank to have a clear separation between header block space and data block space */ if(uAvailClrSpace >= (((uint32)uAlignedBlockSize)+(2U*FEE_BLOCK_OVERHEAD))) #endif { /* Calculate data and header addresses */ uDataAddr = FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt) - uAlignedBlockSize; uHdrAddr = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt); /* Serialize block header to the write buffer */ Fee_SerializeBlockHdr( FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockNumber), uBlockSize, uDataAddr, FEE_BLOCKCONFIG(Fee_uJobBlockIndex, immediateData), #if (FEE_SWAP_FOREIGN_BLOCKS_ENABLED == STD_ON) FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockAssignment), #endif Fee_aDataBuffer ); /* Write header to flash */ if(((Std_ReturnType)E_OK) != Fls_Write( uHdrAddr, Fee_aDataBuffer, FEE_BLOCK_OVERHEAD-(2U*FEE_VIRTUAL_PAGE_SIZE))) { /* Fls read job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } } else { /* The block won't fit into current cluster. Init swap sequence... */ /* Get cluster group index the block belongs to */ Fee_uJobIntClrGrpIt = uClrGrpIndex; eRetVal = Fee_JobIntSwap(); } #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else } #endif return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobWriteData * * Description : Write Fee block data to flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobWriteData( void ) { Fls_AddressType uDataAddr = (Fls_AddressType)0; MemIf_JobResultType eRetVal = MEMIF_JOB_OK; uint16 uBlockSize = 0U; uint16 uAlignedBlockSize = 0U; Fls_LengthType uWriteLength = 0UL; uint8 uClrGrp = 0U; const uint8 *pWriteDataPtr = NULL_PTR; #if(STD_ON == FEE_LEGACY_MODE) #else #if(STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else uint32 uIdx = 0UL; uIdx = ((uint32)Fee_uJobBlockIndex) >> 5U; Fls_LengthType uAvailClrSpace = 0UL; uint32 uReservedSpace = 0UL; sint8 sIsReservedAreaTouched = TRUE; #endif #endif #if(STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) #else Fls_AddressType uHdrAddr = 0U; uint8 uClrGrpIndex = (uint8)0; #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if (Fee_uJobBlockIndex >= FEE_CRT_CFG_NR_OF_BLOCKS) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO); #endif /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { #endif #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) #else #if (STD_ON == FEE_LEGACY_MODE) if((boolean)TRUE == FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData)) { /* Do nothing. */ } else #else /* No special treatment of immediate blocks needed anymore; dataAddr and invalidAddr has to be updated for a newly written imm/non-imm block */ #endif { /* Index of cluster group the Fee block belongs to */ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); /* Get size of Fee block */ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockSize); /* Align Fee block size to the virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* Calculate data and header addresses */ uDataAddr = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt), uAlignedBlockSize); uHdrAddr = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt); FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr) = uDataAddr; FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) = FEE_OPERATIONSUB((uHdrAddr + FEE_BLOCK_OVERHEAD), FEE_VIRTUAL_PAGE_SIZE); } /* Mark the block as inconsistent since the block header has been written */ FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) = FEE_BLOCK_INCONSISTENT; #endif /* (FEE_BLOCK_ALWAYS_AVAILABLE == STD_OFF) */ /* Get size of Fee block */ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockSize); /* Align Fee block size to the virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* Index of cluster group the Fee block belongs to */ uClrGrp = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); #if (STD_OFF == FEE_LEGACY_MODE) /* Header has been written so update both header and data addresses; no special treatment of immediate blocks needed anymore */ FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt) = FEE_OPERATIONADD(FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt), FEE_BLOCK_OVERHEAD); FEE_CLRGRPINFO(uClrGrp, uDataAddrIt) = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrp, uDataAddrIt), uAlignedBlockSize); #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else /* When FEE_BLOCK_ALWAYS_AVAILABLE is enabled, Fee_BlockInfo is not updated immediatelly upon a header write. In case of FEE Cancel, the information about the incosistent (due to incomplete write) immediate block potentially residing in the Reserved Area might be lost and therefore it need to be extra handled. */ /* Reserved space of cluster group*/ uReservedSpace = FEE_CLRGRP(uClrGrp, reservedSize); /* Calculate available space in active cluster */ uAvailClrSpace = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrp, uDataAddrIt), FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt)); if(uAvailClrSpace < FEE_OPERATIONADD(FEE_BLOCK_OVERHEAD, uReservedSpace)) { sIsReservedAreaTouched = TRUE; } if((sIsReservedAreaTouched != FALSE) && (FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData)) != 0UL) { /* Store the information about immediate blook touching the Reserved Area. */ Fee_aReservedAreaTouched[ uIdx ] |= (uint32)(0x00000001UL << ((uint32)Fee_uJobBlockIndex & 0x1FUL)); } #endif #else if( FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData) ) { /* Don't update header and data pointes as it's immediate write */ } else { /* Header has been written so update both header and data addresses */ FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt) = FEE_OPERATIONADD(FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt), FEE_BLOCK_OVERHEAD); FEE_CLRGRPINFO(uClrGrp, uDataAddrIt) = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrp, uDataAddrIt), uAlignedBlockSize); } #endif if(FEE_VIRTUAL_PAGE_SIZE <= uBlockSize) { pWriteDataPtr = Fee_pJobWriteDataDestPtr; if(uBlockSize != uAlignedBlockSize) { uWriteLength = FEE_OPERATIONSUB(((uint32)uAlignedBlockSize), FEE_VIRTUAL_PAGE_SIZE); /* Schedule write of unaligned data */ Fee_eJob = FEE_JOB_WRITE_UNALIGNED_DATA; } else { uWriteLength = uBlockSize; /* Schedule write of validation pattern */ Fee_eJob = FEE_JOB_WRITE_VALIDATE; } } else { /* Go through buffer... */ Fee_CopyDataToPageBuffer( Fee_pJobWriteDataDestPtr, Fee_aDataBuffer, uBlockSize ); pWriteDataPtr = Fee_aDataBuffer; uWriteLength = FEE_VIRTUAL_PAGE_SIZE; /* Schedule write of validation pattern */ Fee_eJob = FEE_JOB_WRITE_VALIDATE; } #if (STD_ON == FEE_LEGACY_MODE) #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else if( FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData) ) { #endif /* Use Block info because it has been updated into Fee_JobEraseImmediateDone */ uDataAddr = FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr); #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else } else { /* Use ClrGrp info */ uDataAddr = FEE_CLRGRPINFO(uClrGrp, uDataAddrIt); } #endif #else uDataAddr = FEE_CLRGRPINFO(uClrGrp, uDataAddrIt); #endif if(Fls_Write( uDataAddr, pWriteDataPtr, uWriteLength ) == ((Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else } #endif return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobWrite * * Description : Write Fee block to flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobWrite( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_FAILED; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if (FEE_CRT_CFG_NR_OF_BLOCKS <= Fee_uJobBlockIndex) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO); #endif /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { #endif #if (STD_ON == FEE_LEGACY_MODE) if( FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData) ) { if(FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) != FEE_BLOCK_INCONSISTENT) { /* The immediate block is not pre-erased and ready to be written */ eRetVal = MEMIF_JOB_FAILED; } else { /* The immediate block is ready to be written */ eRetVal = Fee_JobWriteData(); } } else #else /* No special treatment of immediate data needed any more; pre-erased space not required */ #endif { /* Write block header */ eRetVal = Fee_JobWriteHdr(); /* Schedule next job */ if(Fee_eJob != FEE_JOB_INT_SWAP_CLR_FMT) { Fee_eJob = FEE_JOB_WRITE_DATA; } else { /* Block din't fit into the cluster. Cluster swap has been enforced... */ } } #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else } #endif return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobWriteUnalignedData * * Description : Write unaligned rest of Fee block data to flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobWriteUnalignedData( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uDataAddr = 0U; uint16 uWriteOffset = 0U; uint16 uWriteLength = 0U; uint16 uBlockSize = 0U; #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else uint16 uClrGrp = 0U; #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if (FEE_CRT_CFG_NR_OF_BLOCKS <= Fee_uJobBlockIndex) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO); #endif /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { #endif #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else /* Index of cluster group the Fee block belongs to */ uClrGrp = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); #endif /* Get size of Fee block */ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockSize); /* Calculate number of bytes already written */ uWriteOffset = (uBlockSize / FEE_VIRTUAL_PAGE_SIZE) * FEE_VIRTUAL_PAGE_SIZE; /* Calculate length remaining data to write */ uWriteLength = uBlockSize % FEE_VIRTUAL_PAGE_SIZE; Fee_CopyDataToPageBuffer( Fee_pJobWriteDataDestPtr+uWriteOffset, Fee_aDataBuffer, uWriteLength ); #if (STD_ON == FEE_LEGACY_MODE) #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else if( FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData) ) { #endif /* Use Block info because it has been updated into Fee_JobEraseImmediateDone */ uDataAddr = FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr); #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else } else { /* Use ClrGrp info */ uDataAddr = FEE_CLRGRPINFO(uClrGrp, uDataAddrIt); } #endif #else /* No special treatment of immediate data needed any more */ #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) /* Use Block info because it has been updated */ uDataAddr = FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr); #else /* Use ClrGrp info */ uDataAddr = FEE_CLRGRPINFO(uClrGrp, uDataAddrIt); #endif #endif if(Fls_Write( uDataAddr+uWriteOffset, Fee_aDataBuffer, FEE_VIRTUAL_PAGE_SIZE ) == ((Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls write job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } /* Schedule write of validation pattern */ Fee_eJob = FEE_JOB_WRITE_VALIDATE; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else } #endif return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobWriteValidate * * Description : Validate Fee block by writing validation flag to flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobWriteValidate( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; Fls_AddressType uHdrAddr = (Fls_AddressType)0; #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else uint8 uClrGrpIndex = (uint8)0; #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if (FEE_CRT_CFG_NR_OF_BLOCKS <= Fee_uJobBlockIndex) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO); #endif /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { #endif #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else /* Index of cluster group the Fee block belongs to */ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); #endif /* Serialize validation pattern to buffer */ Fee_SerializeFlag( Fee_aDataBuffer, FEE_VALIDATED_VALUE ); #if (STD_ON == FEE_LEGACY_MODE) #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else if( FEE_BLOCKCONFIG(Fee_uJobBlockIndex, immediateData) ) { #endif /* Use Block info because it has been updated into Fee_JobEraseImmediateDone */ uHdrAddr = FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) - FEE_VIRTUAL_PAGE_SIZE; #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else } else { /* Use ClrGrp info */ uHdrAddr = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt) - (2U * FEE_VIRTUAL_PAGE_SIZE); } #endif #else #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) /* Use Block info */ uHdrAddr = FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) - FEE_VIRTUAL_PAGE_SIZE; #else /* Use ClrGrp info */ uHdrAddr = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt) - (2U * FEE_VIRTUAL_PAGE_SIZE); #endif #endif /* Write validation pattern to flash */ if(Fls_Write( uHdrAddr, Fee_aDataBuffer, FEE_VIRTUAL_PAGE_SIZE) == ((Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } /* Finalize the write operation */ Fee_eJob = FEE_JOB_WRITE_DONE; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else } #endif return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobWriteDone * * Description : Finalize validation of Fee block. * * Inputs : None. * * Outputs : MEMIF_JOB_OK * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobWriteDone( void ) { #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else Fls_AddressType uDataAddr = (Fls_AddressType)0; Fls_AddressType uHdrAddr = (Fls_AddressType)0; uint8 uClrGrpIndex = (uint8)0; /* Index of cluster group the Fee block belongs to */ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); /* Calculate data and header addresses */ uDataAddr = FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt); uHdrAddr = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt); #if (STD_OFF == FEE_LEGACY_MODE) #else if(FEE_BLOCKCONFIG(Fee_uJobBlockIndex, immediateData) == (boolean)FALSE) #endif { /* Update the block address info */ FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr) = uDataAddr; FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) = uHdrAddr - FEE_VIRTUAL_PAGE_SIZE; } #endif /* Mark the Fee block as valid */ FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) = FEE_BLOCK_VALID; /* No more Fls jobs to schedule */ Fee_eJob = FEE_JOB_DONE; return( MEMIF_JOB_OK ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobInvalBlock * * Description : Invalidate Fee block by writing the invalidation flag to flash. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * MEMIF_JOB_OK The Fee block is already invalid. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobInvalBlock( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; if(FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) != FEE_BLOCK_INVALID) { #if (STD_ON == FEE_MARK_EMPTY_BLOCKS_INVALID) #else if(FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) == FEE_BLOCK_NEVER_WRITTEN) { /* set status as INVALID */ FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) = FEE_BLOCK_INVALID; /* No more subsequent Fls jobs to schedule */ Fee_eJob = FEE_JOB_DONE; /* Fee job completed */ eRetVal = MEMIF_JOB_OK; } else #endif { /* Serialize invalidation pattern to buffer */ Fee_SerializeFlag( Fee_aDataBuffer, FEE_INVALIDATED_VALUE ); /* Write invalidation pattern to flash */ if(Fls_Write( FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr), Fee_aDataBuffer, FEE_VIRTUAL_PAGE_SIZE) == ((Std_ReturnType)E_NOT_OK)) { /* Fls write job hasn't been accepted */ eRetVal = MEMIF_JOB_FAILED; } else { /* Fls read job has been accepted */ eRetVal = MEMIF_JOB_PENDING; } /* Finalize the invalidation operation */ Fee_eJob = FEE_JOB_INVAL_BLOCK_DONE; } } else { /* No more subsequent Fls jobs to schedule */ Fee_eJob = FEE_JOB_DONE; /* Fee job completed */ eRetVal = MEMIF_JOB_OK; } return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobInvalBlockDone * * Description : Invalidate Fee block by writing the invalidation flag to flash. * * Inputs : None. * * Outputs : MEMIF_JOB_OK The Fee block is already invalid. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobInvalBlockDone( void ) { /* Mark the Fee block as in valid */ FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) = FEE_BLOCK_INVALID; /* No more subsequent Fls jobs to schedule */ Fee_eJob = FEE_JOB_DONE; /* Fee job completed */ return( MEMIF_JOB_OK ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobEraseImmediate * * Description : Erase (pre-allocate) immediate Fee block. * * Inputs : None. * * Outputs : MEMIF_JOB_PENDING Underlying Fls accepted the write job. * MEMIF_JOB_FAILED Underlying Fls didn't accept write job. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobEraseImmediate( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_OK; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if (FEE_CRT_CFG_NR_OF_BLOCKS <= Fee_uJobBlockIndex) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_ERASEIMMEDIATEBLOCK_ID, FEE_E_INVALID_BLOCK_NO); #endif /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { #endif #if (STD_ON == FEE_LEGACY_MODE) /* Write block header */ eRetVal = Fee_JobWriteHdr(); /* Schedule next job */ if(Fee_eJob != FEE_JOB_INT_SWAP_CLR_FMT) { Fee_eJob = FEE_JOB_ERASE_IMMEDIATE_DONE; } else { /* Block din't fit into the cluster. Cluster swap has been enforced... */ } #else /* Original code */ #if (STD_OFF == FEE_LEGACY_IMM_ERASE_MODE) /* In standard mode, perform swap if reserved area has been touched, or do nothing. */ if(Fee_ReservedAreaWritable() == TRUE) { /* Do effectively nothing */ Fee_eJob = FEE_JOB_DONE; } else { /* Reserved area is not writable, force the swap */ Fee_uJobIntClrGrpIt = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); /* Get cluster group index */ eRetVal = Fee_JobIntSwap(); } #else /* Legacy mode enabled, Fee_JobEraseImmediate shall invalidate the block */ if(Fee_ReservedAreaWritable() == TRUE) { /* Otherwise trigger invalidate operation (in legacy mode) */ eRetVal = Fee_JobInvalBlock(); } else { /* In legacy mode, pronounce the block to be erased as invalidated and then force the swap */ FEE_BLOCKCONFIG(Fee_uJobBlockIndex, eBlockStatus) = FEE_BLOCK_INVALID; Fee_uJobIntClrGrpIt = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); /* Get cluster group index */ eRetVal = Fee_JobIntSwap(); } #endif #endif /* (FEE_LEGACY_MODE == STD_OFF) */ #if (FEE_SWAP_FOREIGN_BLOCKS_ENABLED == STD_ON) } #endif return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobEraseImmediateDone * * Description : Finalize erase (pre-allocation) of Fee block. * * Inputs : None. * * Outputs : MEMIF_JOB_OK * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobEraseImmediateDone( void ) { uint16 uBlockSize = 0U; uint16 uAlignedBlockSize = 0U; uint16 uClrGrp = 0U; MemIf_JobResultType eRetVal = MEMIF_JOB_OK; #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) #else Fls_AddressType uDataAddr = (Fls_AddressType)0; Fls_AddressType uHdrAddr = (Fls_AddressType)0; uint8 uClrGrpIndex = (uint8)0; #endif #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else if (FEE_CRT_CFG_NR_OF_BLOCKS <= Fee_uJobBlockIndex) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_ERASEIMMEDIATEBLOCK_ID, FEE_E_INVALID_BLOCK_NO); #endif /* set job as failed */ eRetVal = MEMIF_JOB_FAILED; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { #endif /* Mark the Fee immediate block as inconsistent so it can be written later on */ FEE_BLOCKINFO(Fee_uJobBlockIndex, eBlockStatus) = FEE_BLOCK_INCONSISTENT; /* Get size of Fee block */ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockSize); /* Align Fee block size to the virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* Index of cluster group the Fee block belongs to */ uClrGrp = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) #else /* Index of cluster group the Fee block belongs to */ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); uDataAddr = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt), uAlignedBlockSize); uHdrAddr = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt); /* Update the block address info */ FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr) = uDataAddr; FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) = FEE_OPERATIONSUB((uHdrAddr + FEE_BLOCK_OVERHEAD), FEE_VIRTUAL_PAGE_SIZE); #endif /* Header has been written so update both header and data addresses */ FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt) = FEE_OPERATIONADD(FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt), FEE_BLOCK_OVERHEAD); FEE_CLRGRPINFO(uClrGrp, uDataAddrIt) = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrp, uDataAddrIt), uAlignedBlockSize); #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else /* As Fee immediate block is inconsistent it is not possible to get previous data, so update Block info */ FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrp, uHdrAddrIt), FEE_VIRTUAL_PAGE_SIZE); FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr) = FEE_CLRGRPINFO(uClrGrp, uDataAddrIt); #endif /* No more subsequent Fls jobs to schedule */ Fee_eJob = FEE_JOB_DONE; /* set job as ook */ eRetVal = MEMIF_JOB_OK; /* Fee job completed */ #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else } #endif return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobSchedule * * Description : Schedule subsequent jobs. * * Inputs : None. * * Outputs : MemIf_JobResultType. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static MemIf_JobResultType Fee_JobSchedule( void ) { MemIf_JobResultType eRetVal = MEMIF_JOB_FAILED; if(Fee_eJob == FEE_JOB_READ) { eRetVal = Fee_JobRead(); } else if(Fee_eJob == FEE_JOB_WRITE) { eRetVal = Fee_JobWrite(); } else if(Fee_eJob == FEE_JOB_WRITE_DATA) { eRetVal = Fee_JobWriteData(); } else if(Fee_eJob == FEE_JOB_WRITE_UNALIGNED_DATA) { eRetVal = Fee_JobWriteUnalignedData(); } else if(Fee_eJob == FEE_JOB_WRITE_VALIDATE) { eRetVal = Fee_JobWriteValidate(); } else if(Fee_eJob == FEE_JOB_WRITE_DONE) { eRetVal = Fee_JobWriteDone(); } else if(Fee_eJob == FEE_JOB_INVAL_BLOCK) { eRetVal = Fee_JobInvalBlock(); } else if(Fee_eJob == FEE_JOB_INVAL_BLOCK_DONE) { eRetVal = Fee_JobInvalBlockDone(); } else if(Fee_eJob == FEE_JOB_ERASE_IMMEDIATE) { eRetVal = Fee_JobEraseImmediate(); } else if(Fee_eJob == FEE_JOB_ERASE_IMMEDIATE_DONE) { eRetVal = Fee_JobEraseImmediateDone(); } else if(Fee_eJob == FEE_JOB_INT_SCAN) { eRetVal = Fee_JobIntScan(); } else if(Fee_eJob == FEE_JOB_INT_SCAN_CLR) { eRetVal = Fee_JobIntScanClr(); } else if(Fee_eJob == FEE_JOB_INT_SCAN_CLR_HDR_PARSE) { eRetVal = Fee_JobIntScanClrHdrParse( (boolean)TRUE ); } else if(Fee_eJob == FEE_JOB_INT_SCAN_CLR_FMT) { eRetVal = Fee_JobIntScanClrFmt(); } else if(Fee_eJob == FEE_JOB_INT_SCAN_CLR_FMT_DONE) { eRetVal = Fee_JobIntScanClrFmtDone(); } else if(Fee_eJob == FEE_JOB_INT_SCAN_BLOCK_HDR_PARSE) { eRetVal = Fee_JobIntScanBlockHdrParse( (boolean)TRUE ); }/* Swap related jobs */ else if(Fee_eJob == FEE_JOB_INT_SWAP_CLR_FMT) { eRetVal = Fee_JobIntSwapClrFmt(); } else if(Fee_eJob == FEE_JOB_INT_SWAP_BLOCK) { eRetVal = Fee_JobIntSwapBlock(); } else if(Fee_eJob == FEE_JOB_INT_SWAP_DATA_READ) { eRetVal = Fee_JobIntSwapDataRead( (boolean)TRUE ); } else if(Fee_eJob == FEE_JOB_INT_SWAP_DATA_WRITE) { eRetVal = Fee_JobIntSwapDataWrite( (boolean)TRUE ); } else if(Fee_eJob == FEE_JOB_INT_SWAP_CLR_VLD_DONE) { eRetVal = Fee_JobIntSwapClrVldDone(); } else if(Fee_eJob == FEE_JOB_DONE) { /* Do nothing */ } else { /* Compiler_Warning: This default branch will never be reached in FTE */ } return( eRetVal ); } #if (STD_ON == FEE_LEGACY_MODE) #else /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_ReservedAreaWritable * * Description : Checks whether the block specified by Fee_JobBlockIndex is writable into the reserved area. * * Inputs : None. * * Outputs : TRUE The block is writable into the reserved area. * FALSE The block is not writable into the reserved area. * * Limitations : None * ************************************************************************************************ END_FUNCTION_HDR */ static sint8 Fee_ReservedAreaWritable( void ) { sint8 sRetVal = TRUE; uint16 uBlockSize = 0U; uint16 uAlignedBlockSize = 0U; Fls_LengthType uAvailClrSpace = 0UL; uint8 uClrGrpIndex = (uint8)0; uint32 uReservedSpace = 0UL; boolean bImmediateData = (boolean)FALSE; #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) #else sint8 sIsReservedAreaTouched = TRUE; uint32 uIdx = 0UL; uIdx = ((uint32)Fee_uJobBlockIndex) >> 5U; #endif /* Index of cluster group the Fee block belongs to */ #if (FEE_SWAP_FOREIGN_BLOCKS_ENABLED == STD_ON) if (Fee_uJobBlockIndex < FEE_CRT_CFG_NR_OF_BLOCKS) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uClrGrpIndex = FEE_FOREIGNBLOCKCONFIG(Fee_uJobBlockIndex-FEE_CRT_CFG_NR_OF_BLOCKS, clrGrp); } #else /* the config is part of Fee_BlockConfig*/ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); #endif /* Reserved space of cluster group*/ uReservedSpace = FEE_CLRGRP(uClrGrpIndex, reservedSize); /* Calculate available space in active cluster */ uAvailClrSpace = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt), FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt)); /* Get size of Fee block */ #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, blockSize); #else if (Fee_uJobBlockIndex < FEE_CRT_CFG_NR_OF_BLOCKS) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uBlockSize = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uBlockSize = FEE_FOREIGNBLOCKCONFIG(Fee_uJobBlockIndex-FEE_CRT_CFG_NR_OF_BLOCKS, blockSize); } #endif /* Align Fee block size to the virtual page boundary */ uAlignedBlockSize = Fee_AlignToVirtualPageSize( uBlockSize ); /* Hard Stop condition: One FEE_BLOCK_OVERHEAD must be left blank to have a clear separation between header block space and data block space */ if(uAvailClrSpace < (((uint32)uAlignedBlockSize) + (2U * FEE_BLOCK_OVERHEAD))) { sRetVal = FALSE; } else if(uAvailClrSpace < (((uint32)uAlignedBlockSize) + (2U * FEE_BLOCK_OVERHEAD) + uReservedSpace)) { #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) /* the config is part of Fee_BlockConfig*/ bImmediateData = FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData); #else if (Fee_uJobBlockIndex < FEE_CRT_CFG_NR_OF_BLOCKS) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ bImmediateData = FEE_BLOCKCONFIG(Fee_uJobBlockIndex,immediateData); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ bImmediateData = FEE_FOREIGNBLOCKCONFIG(Fee_uJobBlockIndex-FEE_CRT_CFG_NR_OF_BLOCKS, immediateData); } #endif /* Block targets reserved area */ #if (STD_OFF == FEE_BLOCK_ALWAYS_AVAILABLE) if(bImmediateData == (boolean)TRUE) #else if( 0U != (Fee_aReservedAreaTouched[ uIdx ] & (uint32)(0x00000001UL << ((uint32)Fee_uJobBlockIndex & 0x1FUL)))) { sIsReservedAreaTouched = TRUE; } else { sIsReservedAreaTouched = FALSE; } if( (bImmediateData == (boolean)TRUE) && (sIsReservedAreaTouched == FALSE)) #endif { /* Immediate block - only writable if not already present in the reserved area */ if( (FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr) == 0UL) && (FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) == 0UL)) { /* The block is not written in the cluster at all => writable */ sRetVal = TRUE; } else { /* The block is written in the cluster - is it written in the reserved area? */ if((FEE_BLOCKINFO(Fee_uJobBlockIndex, uDataAddr) - (FEE_BLOCKINFO(Fee_uJobBlockIndex, uInvalidAddr) + FEE_VIRTUAL_PAGE_SIZE)) >= (FEE_BLOCK_OVERHEAD + uReservedSpace) ) { /* The block is not written in the reserved area */ sRetVal = TRUE; } else { /* The block is already written in the reserved area */ sRetVal = FALSE; } } } else { #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) /* Non-immediate block or immediate block for which an attempt for a write to the Reserved area was made is not writable into reserved area */ #else /* Non-immediate block is not writable into reserved area */ #endif sRetVal = FALSE; } } else { /* Block does not target reserved area */ sRetVal = TRUE; } return sRetVal; } #endif /* FEE_LEGACY_MODE == STD_OFF */ /*================================================================================================== * GLOBAL FUNCTIONS ==================================================================================================*/ /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_Init * * Description : The function Fee_Init shall initialize the Flash EEPROM * Emulation module. * * Inputs : ConfigPtr. * * Outputs : TRUE The block is writable into the reserved area. * FALSE The block is not writable into the reserved area. * * Limitations : ConfigPtr must be NULL_PTR. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_Init(const Fee_ConfigType *ConfigPtr) { uint32 uInvalIndex = 0U; #if (STD_OFF == FEE_DEV_ERROR_DETECT) (void)ConfigPtr; #else if (ConfigPtr != NULL_PTR) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID,FEE_INIT_ID, FEE_E_PARAM_POINTER); } else if(Fee_eModuleStatus == MEMIF_BUSY) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_INIT_ID, FEE_E_BUSY ); } else if(Fee_eModuleStatus == MEMIF_BUSY_INTERNAL) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_INIT_ID, FEE_E_BUSY_INTERNAL); } else #endif /* FEE_DEV_ERROR_DETECT == STD_OFF */ { /* Initialize all block info records */ for(uInvalIndex=0U; uInvalIndex < FEE_MAX_NR_OF_BLOCKS; uInvalIndex++) { #if (STD_OFF == FEE_MARK_EMPTY_BLOCKS_INVALID) /* for blocks which were never written Fee returns INCONSISTENT status */ FEE_BLOCKINFO(uInvalIndex, eBlockStatus) = FEE_BLOCK_NEVER_WRITTEN; #else /* for blocks which were never written Fee returns INVALID status */ FEE_BLOCKINFO(uInvalIndex, eBlockStatus) = FEE_BLOCK_INVALID; #endif #if (STD_ON == FEE_LEGACY_MODE) #else FEE_BLOCKINFO(uInvalIndex, uDataAddr) = 0U; FEE_BLOCKINFO(uInvalIndex, uInvalidAddr) = 0U; #endif } #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else /* Initialize all foreign block config records */ uInvalIndex = 0U; while(uInvalIndex < (FEE_MAX_NR_OF_BLOCKS - FEE_CRT_CFG_NR_OF_BLOCKS)) { FEE_FOREIGNBLOCKCONFIG(uInvalIndex, blockNumber) = 0U; FEE_FOREIGNBLOCKCONFIG(uInvalIndex, blockSize) = 0U; FEE_FOREIGNBLOCKCONFIG(uInvalIndex, clrGrp) = 0U; FEE_FOREIGNBLOCKCONFIG(uInvalIndex, immediateData) = (boolean)FALSE; FEE_FOREIGNBLOCKCONFIG(uInvalIndex, blockAssignment) = FEE_PROJECT_RESERVED; uInvalIndex++; } #endif /* Invalidate all cluster groups */ for(uInvalIndex=0U; uInvalIndex < FEE_NUMBER_OF_CLUSTER_GROUPS; uInvalIndex++) { FEE_CLRGRPINFO(uInvalIndex, uActClrID) = 0U; } #if (STD_ON == FEE_BLOCK_ALWAYS_AVAILABLE) && (STD_OFF == FEE_LEGACY_MODE) uInvalIndex = 0U; while(uInvalIndex < (sizeof( Fee_aReservedAreaTouched )/sizeof( *Fee_aReservedAreaTouched ))) { Fee_aReservedAreaTouched[ uInvalIndex ] = 0x00000000UL; uInvalIndex++; } #endif /* Schedule init job */ Fee_eJob = FEE_JOB_INT_SCAN; Fee_eModuleStatus = MEMIF_BUSY_INTERNAL; Fee_eJobResult = MEMIF_JOB_PENDING; #if (STD_OFF == FEE_SWAP_FOREIGN_BLOCKS_ENABLED) #else Fee_uForeignBlocksNumber = 0U; #endif } } #if (defined(__DOXYGEN__) || (STD_ON == FEE_SETMODE_API_SUPPORTED)) /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_SetMode * * Description : Call the Fls_SetMode function of the underlying flash driver. * * Inputs : Mode Flash modes. * * Outputs : None. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_SetMode( MemIf_ModeType Mode ) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) if( MEMIF_IDLE == Fee_eModuleStatus ) #else if( MEMIF_UNINIT == Fee_eModuleStatus ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_SETMODE_ID, FEE_E_UNINIT ); } else if( MEMIF_BUSY == Fee_eModuleStatus ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_SETMODE_ID, FEE_E_BUSY ); } else if( MEMIF_BUSY_INTERNAL == Fee_eModuleStatus ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_SETMODE_ID, FEE_E_BUSY_INTERNAL); } else #endif /* FEE_DEV_ERROR_DETECT == STD_OFF */ { Fls_SetMode( Mode ); } } #endif /* (FEE_SETMODE_API_SUPPORTED == STD_ON) || defined(__DOXYGEN__) */ /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_Read * * Description : The function Fee_Read shall take the block start address and * offset and calculate the corresponding memory read address. * * Inputs : uBlockNumber Number of logical block, also denoting * start address of that block in flash memory. * uBlockOffset Read address offset inside the block. * pDataBufferPtr Pointer to data buffer. * uLength Number of bytes to read. * * Outputs : E_OK The read job was accepted by the * underlying memory driver. * E_NOT_OK The read job has not been accepted. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ Std_ReturnType Fee_Read(uint16 uBlockNumber, uint16 uBlockOffset, uint8 *pDataBufferPtr, uint16 uLength) { Std_ReturnType uRetVal = (Std_ReturnType)E_OK; uint16 uBlockIndex = Fee_GetBlockIndex( uBlockNumber ); /* Start of exclusive area. Implementation depends on integrator. */ SchM_Enter_Fee_FEE_EXCLUSIVE_AREA_0(); if(Fee_eModuleStatus == MEMIF_UNINIT) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_READ_ID, FEE_E_UNINIT ); #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ uRetVal = (Std_ReturnType)E_NOT_OK; } else if(Fee_eModuleStatus == MEMIF_BUSY) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_READ_ID, FEE_E_BUSY ); #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ uRetVal = (Std_ReturnType)E_NOT_OK; } else if(Fee_eModuleStatus == MEMIF_BUSY_INTERNAL) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_READ_ID, FEE_E_BUSY_INTERNAL); #endif /* FEE_DEV_ERROR_DETECT == STD_OFF */ uRetVal = (Std_ReturnType)E_NOT_OK; } #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else else if(uBlockIndex == 0xFFFFU) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_READ_ID, FEE_E_INVALID_BLOCK_NO); uRetVal = (Std_ReturnType)E_NOT_OK; } else if(FEE_BLOCKCONFIG(uBlockIndex, blockSize) <= uBlockOffset) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_READ_ID, FEE_E_INVALID_BLOCK_OFS); uRetVal = (Std_ReturnType)E_NOT_OK; } else if((uLength == 0U) || (FEE_BLOCKCONFIG(uBlockIndex, blockSize) < (uBlockOffset+uLength))) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_READ_ID, FEE_E_INVALID_BLOCK_LEN); uRetVal = (Std_ReturnType)E_NOT_OK; } else if(pDataBufferPtr == NULL_PTR) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_READ_ID, FEE_E_PARAM_POINTER); uRetVal = (Std_ReturnType)E_NOT_OK; } #endif /* FEE_DEV_ERROR_DETECT == STD_OFF */ else { /* Configure the read job */ Fee_uJobBlockIndex = uBlockIndex; Fee_uJobBlockOffset = uBlockOffset; Fee_uJobBlockLength = uLength; Fee_pJobReadDataDestPtr = pDataBufferPtr; Fee_eJob = FEE_JOB_READ; Fee_eModuleStatus = MEMIF_BUSY; /* Execute the read job */ Fee_eJobResult = MEMIF_JOB_PENDING; } /* End of exclusive area. Implementation depends on integrator. */ SchM_Exit_Fee_FEE_EXCLUSIVE_AREA_0(); return( uRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_Write * * Description : The function Fee_Write shall take the block start address and * calculate the corresponding memory write address. The block * address offset shall be fixed to zero. * The function Fee_Write shall copy the given or computed * parameters to module internal variables, initiate a write job, * set the FEE module status to MEMIF_BUSY, set the job result to * MEMIF_JOB_PENDING and return with E_OK.The FEE module shall * execute the write job of the function Fee_Write * asynchronously within the FEE module' s main function.. * * Inputs : uBlockNumber Number of logical block, also denoting * start address of that block in emulated * EEPROM. * pDataBufferPtr Pointer to data buffer. * * Outputs : E_OK The read job was accepted by the * underlying memory driver. * E_NOT_OK The read job has not been accepted. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ Std_ReturnType Fee_Write(uint16 uBlockNumber, const uint8 *pDataBufferPtr) { Std_ReturnType uRetVal = (Std_ReturnType)E_OK; uint16 uBlockIndex = Fee_GetBlockIndex( uBlockNumber ); /* Start of exclusive area. Implementation depends on integrator. */ SchM_Enter_Fee_FEE_EXCLUSIVE_AREA_1(); if(Fee_eModuleStatus == MEMIF_UNINIT) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_UNINIT ); #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ uRetVal = (Std_ReturnType)E_NOT_OK; } else if(Fee_eModuleStatus == MEMIF_BUSY) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_BUSY ); #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ uRetVal = (Std_ReturnType)E_NOT_OK; } #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else else if(uBlockIndex == 0xFFFFU) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_INVALID_BLOCK_NO); uRetVal = (Std_ReturnType)E_NOT_OK; } else if( MEMIF_BUSY_INTERNAL == Fee_eModuleStatus ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_WRITE_ID, FEE_E_BUSY_INTERNAL); uRetVal = (Std_ReturnType)E_NOT_OK; } else if( NULL_PTR == pDataBufferPtr ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID,FEE_WRITE_ID, FEE_E_PARAM_POINTER); uRetVal = (Std_ReturnType)E_NOT_OK; } #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ else { /* Configure the write job */ Fee_uJobBlockIndex = uBlockIndex; Fee_pJobWriteDataDestPtr = pDataBufferPtr; Fee_eJob = FEE_JOB_WRITE; Fee_eModuleStatus = MEMIF_BUSY; /* Execute the write job */ Fee_eJobResult = MEMIF_JOB_PENDING; } /* End of exclusive area. Implementation depends on integrator. */ SchM_Exit_Fee_FEE_EXCLUSIVE_AREA_1(); return( uRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_Cancel * * Description : The function Fee_Cancel and the cancel function of the * underlying flash driver are asynchronous w.r.t. an ongoing * read, erase or write job in the flash memory. * * Inputs : None. * * Outputs : None. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_Cancel( void ) { /* If FEE_CANCEL_API == STD_OFF Fee_Cancel set only a Det Error Notification Note: this is to avoid robustness issues (in term of internal variables) */ #if (STD_ON == FEE_CANCEL_API) #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else if(Fee_eModuleStatus == MEMIF_UNINIT) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_CANCEL_ID, FEE_E_UNINIT ); } else { #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ if( Fee_eJobResult != MEMIF_JOB_PENDING ) { /* Leave the job result unchanged */ } else { /* Cancel ongoing Fls job if any */ if( Fee_eModuleStatus == MEMIF_BUSY ) { Fee_eJobResult = MEMIF_JOB_CANCELED; Fee_eJob = FEE_JOB_DONE; Fls_Cancel(); Fee_eModuleStatus = MEMIF_IDLE; /* No notifications from internal jobs */ } else { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_CANCEL_ID, FEE_E_INVALID_CANCEL); #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } } #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else } #endif /* STD_ON == FEE_DEV_ERROR_DETECT*/ #else #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_CANCEL_ID, FEE_E_CANCEL_API ); #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ #endif /* FLS_CANCEL_API == STD_ON */ } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_GetStatus * * Description : Return the Fee module state synchronously. * * Inputs : None. * * Outputs : MEMIF_UNINIT Module has not been initialized (yet). * MEMIF_IDLE Module is currently idle. * MEMIF_BUSY Module is currently busy. * MEMIF_BUSY_INTERNAL Module is busy with internal management * operations. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ MemIf_StatusType Fee_GetStatus( void ) { return( Fee_eModuleStatus ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_GetJobResult * * Description : Return the result of the last job synchronously. * * Inputs : None. * * Outputs : MEMIF_JOB_OK The job has been finished successfully. * MEMIF_JOB_FAILED The job has not been finished * successfully. * MEMIF_JOB_PENDING The job has not yet been finished. * MEMIF_JOB_CANCELED The job has been canceled. * MEMIF_BLOCK_INCONSISTENT The requested block is inconsistent, * it may contain corrupted data. * MEMIF_BLOCK_INVALID The requested block has been invalidated, * the requested read operation can not be performed. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ MemIf_JobResultType Fee_GetJobResult( void ) { MemIf_JobResultType eRetVal = Fee_eJobResult; #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else if(Fee_eModuleStatus == MEMIF_UNINIT) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_GETJOBRESULT_ID, FEE_E_UNINIT); eRetVal = MEMIF_JOB_FAILED; } #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ return( eRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_InvalidateBlock * * Description : Invalidate a logical block. * * Inputs : uBlockNumber Number of logical block, also denoting * start address of that block in flash memory. * * Outputs : E_OK The job was accepted by the underlying * memory driver. * E_NOT_OK The job has not been accepted by the * underlying memory driver. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ Std_ReturnType Fee_InvalidateBlock( uint16 uBlockNumber ) { Std_ReturnType uRetVal = (Std_ReturnType)E_NOT_OK; uint16 uBlockIndex = Fee_GetBlockIndex( uBlockNumber ); /* Start of exclusive area. Implementation depends on integrator. */ SchM_Enter_Fee_FEE_EXCLUSIVE_AREA_2(); #if (STD_OFF == FEE_DEV_ERROR_DETECT) if( MEMIF_IDLE == Fee_eModuleStatus ) #else if( MEMIF_UNINIT == Fee_eModuleStatus ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_INVALIDATEBLOCK_ID, FEE_E_UNINIT); } else if( 0xFFFFU == uBlockIndex ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_INVALIDATEBLOCK_ID, FEE_E_INVALID_BLOCK_NO); } else if( MEMIF_BUSY == Fee_eModuleStatus ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_INVALIDATEBLOCK_ID, FEE_E_BUSY ); } else if( MEMIF_BUSY_INTERNAL == Fee_eModuleStatus ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_INVALIDATEBLOCK_ID, FEE_E_BUSY_INTERNAL); } else #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ { /* Configure the invalidate block job */ Fee_uJobBlockIndex = uBlockIndex; Fee_eJob = FEE_JOB_INVAL_BLOCK; Fee_eModuleStatus = MEMIF_BUSY; /* Execute the invalidate block job */ Fee_eJobResult = MEMIF_JOB_PENDING; uRetVal = (Std_ReturnType)E_OK; } /* End of exclusive area. Implementation depends on integrator. */ SchM_Exit_Fee_FEE_EXCLUSIVE_AREA_2(); return( uRetVal ); } /* @implements FEE_VERSION_INFO_API==STD_ON_ActivityPartition */ #if((STD_ON == FEE_VERSION_INFO_API) || defined(__DOXYGEN__)) /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_GetVersionInfo * * Description : The version information includes: Module Id, Vendor Id, * Vendor specific version numbers. * * Inputs : pVersionInfoPtr Pointer to where to store the version * information of this module . * * Outputs : None. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_GetVersionInfo(Std_VersionInfoType *pVersionInfoPtr) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else if( NULL_PTR == pVersionInfoPtr ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID,FEE_GETVERSIONINFO_ID, FEE_E_PARAM_POINTER); } else { #endif /* STD_OFF == FEE_DEV_ERROR_DETECT*/ pVersionInfoPtr->moduleID = (uint16)FEE_MODULE_ID; pVersionInfoPtr->vendorID = (uint16)FEE_VENDOR_ID; pVersionInfoPtr->sw_major_version = (uint8)FEE_SW_MAJOR_VERSION; pVersionInfoPtr->sw_minor_version = (uint8)FEE_SW_MINOR_VERSION; pVersionInfoPtr->sw_patch_version = (uint8)FEE_SW_PATCH_VERSION; #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else } #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ } #endif /* STD_ON == FEE_VERSION_INFO_API */ /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_EraseImmediateBlock * * Description : The function Fee_EraseImmediateBlock shall take the block number * and calculate the corresponding memory block address. * The function Fee_EraseImmediateBlock shall ensure that the FEE * module can write immediate data. Whether this involves * physically erasing a memory area and therefore calling the erase * function of the underlying driver depends on the implementation. * If development error detection for the FEE module is enabled, * the function Fee_EraseImmediateBlock shall check whether the * addressed logical block is configured as containing immediate * data (configuration parameter FeeImmediateData == TRUE). * If not, the function Fee_EraseImmediateBlock * shall report the error code FEE_E_INVALID_BLOCK_NO. * * Inputs : uBlockNumber Number of logical block, also denoting. * * Outputs : E_OK The job was accepted by the underlying * memory driver. * E_NOT_OK The job has not been accepted by the underlying * memory driver. * start address of that block in emulated EEPROM. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ Std_ReturnType Fee_EraseImmediateBlock( uint16 uBlockNumber ) { Std_ReturnType uRetVal = (Std_ReturnType)E_OK; uint16 uBlockIndex = Fee_GetBlockIndex( uBlockNumber ); /* Start of exclusive area. Implementation depends on integrator. */ SchM_Enter_Fee_FEE_EXCLUSIVE_AREA_3(); #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else if( Fee_eModuleStatus == MEMIF_UNINIT ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_ERASEIMMEDIATEBLOCK_ID, FEE_E_UNINIT); uRetVal = (Std_ReturnType)E_NOT_OK; } else if( uBlockIndex == 0xFFFFU ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_ERASEIMMEDIATEBLOCK_ID, FEE_E_INVALID_BLOCK_NO); uRetVal = (Std_ReturnType)E_NOT_OK; } else if( FEE_BLOCKCONFIG(uBlockIndex, immediateData) == (boolean)FALSE ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_ERASEIMMEDIATEBLOCK_ID, FEE_E_INVALID_BLOCK_NO); uRetVal = (Std_ReturnType)E_NOT_OK; } else if( Fee_eModuleStatus == MEMIF_BUSY ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_ERASEIMMEDIATEBLOCK_ID, FEE_E_BUSY); uRetVal = (Std_ReturnType)E_NOT_OK; } else if( Fee_eModuleStatus == MEMIF_BUSY_INTERNAL ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_ERASEIMMEDIATEBLOCK_ID, FEE_E_BUSY_INTERNAL); uRetVal = (Std_ReturnType)E_NOT_OK; } else { #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ /* Configure the erase immediate block job */ Fee_uJobBlockIndex = uBlockIndex; Fee_eJob = FEE_JOB_ERASE_IMMEDIATE; Fee_eModuleStatus = MEMIF_BUSY; /* Execute the erase immediate block job */ Fee_eJobResult = MEMIF_JOB_PENDING; #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else } #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ /* End of exclusive area. Implementation depends on integrator. */ SchM_Exit_Fee_FEE_EXCLUSIVE_AREA_3(); return( uRetVal ); } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobEndNotification * * Description : The underlying flash driver shall call the function * Fee_JobEndNotification to report the successful end of * an asynchronous operation. * * Inputs : None. * * Outputs : None. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_JobEndNotification( void ) { if( Fee_eModuleStatus != MEMIF_UNINIT ) { if( Fee_eJob != FEE_JOB_DONE ) { Fee_eJobResult = Fee_JobSchedule(); if( Fee_eJobResult == MEMIF_JOB_PENDING ) { /* Nothing to do (ongoing Fls job) */ } else if( Fee_eJobResult == MEMIF_JOB_OK ) { if( Fee_eModuleStatus == MEMIF_BUSY_INTERNAL ) { /* no notifications from internal jobs */ Fee_eModuleStatus = MEMIF_IDLE; } else { Fee_eModuleStatus = MEMIF_IDLE; /* Call job end notification function */ FEE_NVM_JOB_END_NOTIFICATION } } else { if( Fee_eModuleStatus != MEMIF_BUSY_INTERNAL ) { Fee_eModuleStatus = MEMIF_IDLE; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { /* no notifications from internal jobs */ Fee_eModuleStatus = MEMIF_IDLE; } } } else { /* Last schedule Fls job finished */ Fee_eJobResult = Fls_GetJobResult(); if( Fee_eModuleStatus != MEMIF_BUSY_INTERNAL ) { Fee_eModuleStatus = MEMIF_IDLE; /* Call job end notification function */ FEE_NVM_JOB_END_NOTIFICATION } else { /* no notifications from internal jobs */ Fee_eModuleStatus = MEMIF_IDLE; } } } else { #if (STD_OFF == FEE_DEV_ERROR_DETECT) /* Do nothing. Fee is not initialized */ #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_JOBENDNOTIFICATION_ID, FEE_E_UNINIT); #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_JobErrorNotification * * Description : The underlying flash driver shall call the function * Fee_JobErrorNotification to report the failure of * an asynchronous operation. * * Inputs : None. * * Outputs : None. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_JobErrorNotification( void ) { uint8 uClrGrpIndex = 0U; if( Fee_eModuleStatus != MEMIF_UNINIT ) { if( Fee_eJobResult != MEMIF_JOB_CANCELED ) { switch( Fee_eJob ) { /* Error while reading block header. Treat block header as invalid and stop reading further block headers */ case FEE_JOB_INT_SCAN_BLOCK_HDR_PARSE: Fee_eJobResult = Fee_JobIntScanBlockHdrParse( (boolean)FALSE ); break; /* Error while reading cluster header. Treat cluster as invalid and move on to next cluster */ case FEE_JOB_INT_SCAN_CLR_HDR_PARSE: Fee_eJobResult = Fee_JobIntScanClrHdrParse( (boolean)FALSE ); break; /* Error while reading data from source cluster. Leave block as INCONSISTENT and move on to next block */ case FEE_JOB_INT_SWAP_DATA_WRITE: Fee_eJobResult = Fee_JobIntSwapDataWrite( (boolean)FALSE ); break; /* for all the following cases based on the Fee module status error notification will be called */ case FEE_JOB_WRITE: case FEE_JOB_WRITE_DATA: case FEE_JOB_WRITE_UNALIGNED_DATA: case FEE_JOB_ERASE_IMMEDIATE: case FEE_JOB_ERASE_IMMEDIATE_DONE: case FEE_JOB_WRITE_VALIDATE: case FEE_JOB_WRITE_DONE: { #if (FEE_SWAP_FOREIGN_BLOCKS_ENABLED == STD_ON) if (Fee_uJobBlockIndex < FEE_CRT_CFG_NR_OF_BLOCKS) { /* this means block is not foreign, so the config is part of Fee_BlockConfig*/ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); } else { /* this means block is foreign, so the config is part of Fee_ForeignBlockConfig*/ uClrGrpIndex = FEE_FOREIGNBLOCKCONFIG(Fee_uJobBlockIndex-FEE_CRT_CFG_NR_OF_BLOCKS, clrGrp); } #else /* the config is part of Fee_BlockConfig*/ uClrGrpIndex = FEE_BLOCKCONFIG(Fee_uJobBlockIndex, clrGrp); #endif /* Something wrong in FlashMemory (cluster swap occurs to next write) */ FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt) = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt) + (2U * FEE_BLOCK_OVERHEAD); } case FEE_JOB_READ: case FEE_JOB_INVAL_BLOCK: case FEE_JOB_INVAL_BLOCK_DONE: case FEE_JOB_INT_SCAN: case FEE_JOB_INT_SCAN_CLR: case FEE_JOB_INT_SCAN_CLR_FMT: case FEE_JOB_INT_SCAN_CLR_FMT_DONE: case FEE_JOB_INT_SWAP_BLOCK: case FEE_JOB_INT_SWAP_CLR_FMT: case FEE_JOB_INT_SWAP_DATA_READ: case FEE_JOB_INT_SWAP_CLR_VLD_DONE: case FEE_JOB_DONE: default: Fee_eJobResult = Fls_GetJobResult(); if( MEMIF_BUSY_INTERNAL == Fee_eModuleStatus ) { /* No notifications from internal jobs */ Fee_eModuleStatus = MEMIF_IDLE; } else { Fee_eModuleStatus = MEMIF_IDLE; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } break; } } else { /* Fls job has been canceled. Do nothing in this callback. The NvM_JobErrorNotification() callback will be called from the Fee_Cancel()function which called the Fls_Cancel() function */ } } else { #if (FEE_DEV_ERROR_DETECT == STD_ON) Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_JOBERRORNOTIFICATION_ID, FEE_E_UNINIT); #else /* Do nothing. Fee is not initialized */ #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_MainFunction * * Description : The function shall asynchronously handle the requested * read, write, or erase jobs respectively the internal management operations. * The function shall check, whether * the block requested for reading has been invalidated by the * upper layer module. * If so, the function shall set the job result to * MEMIF_BLOCK_INVALID and call the error notification routine * of the upper layer if configured. * The function shall check the consistency of the logical block * being read before notifying the caller. If an inconsistency * of the read data is detected, the function * shall set the job result to MEMIF_BLOCK_INCONSISTENT and call * the error notification routine of the upper layer. * * Inputs : None. * * Outputs : None. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_MainFunction( void ) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else if(Fee_eModuleStatus == MEMIF_UNINIT ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_MAINFUNCTION_ID, FEE_E_UNINIT); } else { #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ if(Fee_eJobResult == MEMIF_JOB_PENDING) { switch( Fee_eJob ) { /* for all the following jobs subsequent jobs will be called in Fee job schedule function based on Job */ case FEE_JOB_INT_SCAN: case FEE_JOB_READ: case FEE_JOB_WRITE: case FEE_JOB_INVAL_BLOCK: case FEE_JOB_ERASE_IMMEDIATE: Fee_eJobResult = Fee_JobSchedule(); break; /* for all the following jobs job end or job error notification will be called based on the job result */ case FEE_JOB_WRITE_DATA: case FEE_JOB_WRITE_UNALIGNED_DATA: case FEE_JOB_WRITE_VALIDATE: case FEE_JOB_WRITE_DONE: case FEE_JOB_INVAL_BLOCK_DONE: case FEE_JOB_ERASE_IMMEDIATE_DONE: case FEE_JOB_INT_SCAN_CLR_HDR_PARSE: case FEE_JOB_INT_SCAN_CLR: case FEE_JOB_INT_SCAN_CLR_FMT: case FEE_JOB_INT_SCAN_CLR_FMT_DONE: case FEE_JOB_INT_SCAN_BLOCK_HDR_PARSE: case FEE_JOB_INT_SWAP_BLOCK: case FEE_JOB_INT_SWAP_CLR_FMT: case FEE_JOB_INT_SWAP_DATA_READ: case FEE_JOB_INT_SWAP_DATA_WRITE: case FEE_JOB_INT_SWAP_CLR_VLD_DONE: case FEE_JOB_DONE: default: /* Internal or subsequent job */ break; } if( Fee_eJobResult == MEMIF_JOB_OK ) { if(Fee_eModuleStatus != MEMIF_BUSY_INTERNAL) { Fee_eModuleStatus = MEMIF_IDLE; /* Call job end notification function */ FEE_NVM_JOB_END_NOTIFICATION } else { /* no notifications from internal jobs */ Fee_eModuleStatus = MEMIF_IDLE; } } else if(Fee_eJobResult == MEMIF_JOB_PENDING) { /* Nothing to do */ } else { if( Fee_eModuleStatus != MEMIF_BUSY_INTERNAL ) { Fee_eModuleStatus = MEMIF_IDLE; /* Call job error notification function */ FEE_NVM_JOB_ERROR_NOTIFICATION } else { /* no notifications from internal jobs */ Fee_eModuleStatus = MEMIF_IDLE; } } } #if (FEE_DEV_ERROR_DETECT == STD_ON) } #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_GetRunTimeInfo * * Description : Read runtime information in the selected cluster * * Inputs : uClrGrpIndex Index of the selected cluster group. * pClrGrpRTInfo. * * Outputs : None. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ void Fee_GetRunTimeInfo(uint8 uClrGrpIndex, Fee_ClusterGroupRuntimeInfoType *pClrGrpRTInfo) { uint32 uActiveClrIndex = 0U; /* DET Check for cluster group should be added: - INITIALIZED driver - BUSY and BUSY_INTERNAL driver - Cluster group valid */ if( Fee_eModuleStatus == MEMIF_UNINIT ) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_GETRUNTIMEINFO_ID, FEE_E_UNINIT); #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ } else if (pClrGrpRTInfo == NULL_PTR) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID,FEE_GETRUNTIMEINFO_ID, FEE_E_PARAM_POINTER); #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ } else if( Fee_eModuleStatus == MEMIF_BUSY ) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_GETRUNTIMEINFO_ID, FEE_E_BUSY); #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ } #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else else if(Fee_eModuleStatus == MEMIF_BUSY_INTERNAL) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_GETRUNTIMEINFO_ID, FEE_E_BUSY_INTERNAL); } /* Cluster group index in valid range */ else if( FEE_NUMBER_OF_CLUSTER_GROUPS <= uClrGrpIndex ) { Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_GETRUNTIMEINFO_ID, FEE_E_CLUSTER_GROUP_IDX); } #endif /* STD_OFF == FEE_DEV_ERROR_DETECT */ else { /* Get active cluster index for selected cluster group */ uActiveClrIndex = FEE_CLRGRPINFO(uClrGrpIndex, uActClr); /* Size of the active cluster in selected cluster group */ pClrGrpRTInfo->clusterTotalSpace = FEE_CLRGRPS(uClrGrpIndex, uActiveClrIndex, length); pClrGrpRTInfo->clusterFreeSpace = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt), (FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt) + (2U*FEE_BLOCK_OVERHEAD))); pClrGrpRTInfo->blockHeaderOverhead = (uint8)FEE_CLUSTER_OVERHEAD; pClrGrpRTInfo->virtualPageSize = (uint8)FEE_VIRTUAL_PAGE_SIZE; pClrGrpRTInfo->numberOfSwap = FEE_OPERATIONSUB(FEE_CLRGRPINFO(uClrGrpIndex, uActClrID), 1U); } } /* BEGIN_FUNCTION_HDR ************************************************************************************************ * Function Name : Fee_ForceSwapOnNextWrite * * Description : While the computed amount of memory is allocated as a result of Fee_Write * call for plain data blocks, for immediate data blocks memory gets completely * pre-allocated through Fee_EraseImmediateBlock function (i.e. Fee_Write does * not change the remaining space). * As a result, swaps triggered by the planned Fee_ForceSwapOnNextWrite function * behave the same way, or in other words, an operation that really activates the * pysical swap must be either Fee_Write on plain FEE block or * Fee_EraseImmediateBlock on immediate data block. * * Inputs : uClrGrpIndex Index of the selected cluster group. * * Outputs : E_NOT_OK Module is not initialized, busy or uClrGrpIndex is not in the * valid range. * E_OK No more space available in the selected cluster.. * * Limitations : None. * ************************************************************************************************ END_FUNCTION_HDR */ Std_ReturnType Fee_ForceSwapOnNextWrite ( uint8 uClrGrpIndex ) { Std_ReturnType uRetVal = (Std_ReturnType)E_OK; /* DET Check for cluster group should be added: - INITIALIZED driver - BUSY and BUSY_INTERNAL driver - Cluster group valid */ if( MEMIF_UNINIT == Fee_eModuleStatus ) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError( (uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_FORCESWAPONNEXTWRITE_ID, FEE_E_UNINIT); #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ uRetVal = (Std_ReturnType)E_NOT_OK; } else if( MEMIF_BUSY == Fee_eModuleStatus ) { #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else Det_ReportError((uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_FORCESWAPONNEXTWRITE_ID, FEE_E_BUSY); #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ uRetVal = (Std_ReturnType)E_NOT_OK; } #if (STD_OFF == FEE_DEV_ERROR_DETECT) #else else if( MEMIF_BUSY_INTERNAL == Fee_eModuleStatus ) { Det_ReportError((uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_FORCESWAPONNEXTWRITE_ID, FEE_E_BUSY_INTERNAL); uRetVal = (Std_ReturnType)E_NOT_OK; } /* Cluster group index in valid range */ else if( FEE_NUMBER_OF_CLUSTER_GROUPS <= uClrGrpIndex ) { Det_ReportError((uint16)FEE_MODULE_ID, FEE_INSTANCE_ID, FEE_FORCESWAPONNEXTWRITE_ID, FEE_E_CLUSTER_GROUP_IDX); uRetVal = (Std_ReturnType)E_NOT_OK; } #endif /* FEE_DEV_ERROR_DETECT == STD_ON */ else { FEE_CLRGRPINFO(uClrGrpIndex, uDataAddrIt) = FEE_CLRGRPINFO(uClrGrpIndex, uHdrAddrIt) + (2U * FEE_BLOCK_OVERHEAD); } return( uRetVal ); } #define FEE_STOP_SEC_CODE #include "Fee_MemMap.h" #ifdef __cplusplus } #endif