/*SAFETYMCUSW 61 D MR:8.10,8.11 <APPROVED> "Reason -  This API will be called by application."*/
 void TI_Fee_MainFunction(void)
{
	uint8 u8EEPIndex = 0U;
	uint8 u8WriteCount=0U;	
	uint8 * DataBufferPtr;
	boolean bVSError=FALSE;		
	static uint8 Fee_u8WriteCounter=0U;
	#if(TI_FEE_FLASH_ERROR_CORRECTION_HANDLING == TI_Fee_Fix)
	TI_Fee_AddressType oBlockAddress=0U;
	uint32 **ppu32ReadHeader=0U;
	uint32 u32BlockAddressTemp=0U;	
	#endif
	uint32 u32WriteAddressTemp=0U;
	uint8 * u8WriteDataptrTemp=0U;
	uint8 u8loopindex = 0U;

	while(u8EEPIndex<TI_FEE_NUMBER_OF_EEPS)
	{
		/* Write the remaining of the VS header */
		/*SAFETYMCUSW 114 S MR:21.1 <APPROVED> "Reason -  Eventhough expression is not boolean, we check for the 
		  function return value."*/
		/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
		/*SAFETYMCUSW 114 S MR:12.6,13.2 <APPROVED> "Reason -  LDRA does not understand macro 
		  FAPI_CHECK_FSM_READY_BUSY."*/
		/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason -  ( pFapi_FmcRegistersType ) ( 0xFFF87000U ) ) casting 
		 is done in F021 library.*/ 		  
		if((TRUE == TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteVSHeader) &&
			(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady))
		{
			u32WriteAddressTemp = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oWriteAddress;			
			/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Null pointer check is done for 
			  TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8Data."*/
			u8WriteDataptrTemp = TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8Data;			
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_oWriteAddress  =  TI_Fee_GlobalVariables[u8EEPIndex].Fee_oVirtualSectorStartAddress + 8U;
			/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/									 
			/*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8Data  =  (uint8 *)(&TI_Fee_GlobalVariables[u8EEPIndex].Fee_au32VirtualSectorStateValue[2]); 	
			(void)TI_FeeInternal_WriteDataF021((boolean)FALSE,(uint16)8U, u8EEPIndex);	
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteVSHeader = FALSE;
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_oWriteAddress = u32WriteAddressTemp;			
			/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/									 
			/*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/									 
			/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Null pointer check is done for 
			  TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8Data."*/
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8Data = (uint8 *)u8WriteDataptrTemp;			
		}
		
		/* Check if the FEE is in Busy State, else handle the internal operations */		
		if((TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.WriteAsync==1U) 	  || 
		   (TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.InvalidateBlock==1U) ||
		   (TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.EraseImmediate==1U)  ||
		   (TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Read==1U)		
		  )
		{
			/* check if the Flash State machine is Busy */
			/*SAFETYMCUSW 114 S MR:21.1 <APPROVED> "Reason -  Eventhough expression is not boolean, 
			  we check for the function return value."*/
			/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
			/*SAFETYMCUSW 114 S MR:12.6,13.2 <APPROVED> "Reason -  LDRA does not understand macro 
		      FAPI_CHECK_FSM_READY_BUSY."*/
			/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason -  ( pFapi_FmcRegistersType ) ( 0xFFF87000U ) ) casting 
		      is done in F021 library.*/ 		  
			if(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady)
			{
				/* program, erase, or suspend operation is not being processed*/
				/* check the current job in progress & execute it */
				if(TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.WriteAsync==1U)
				{					
					if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_bFindNextVirtualSector == TRUE)
					{
						/* Find the next Virtual Sector to write to */
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16CopyVirtualSector = TI_FeeInternal_FindNextVirtualSector(u8EEPIndex);
							
						/* Configure it as a Copy Virtual Sector */
						if((TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16CopyVirtualSector!=0U) && 
						   (TI_Fee_GlobalVariables[u8EEPIndex].Fee_Error == Error_Nil))
						{
							/* Immediately Update the VS state to COPY */
							TI_FeeInternal_WriteVirtualSectorHeader(
							(uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16CopyVirtualSector,
							 VsState_Copy, u8EEPIndex);														
						}						
						else
						{
							/* If no Virtual Sector found, update an Error. Global error is already updated. */
							bVSError=TRUE;	
							/* Writing is not possible since no VS is found free */							
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult= JOB_FAILED;
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState = IDLE;
							TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.WriteAsync = 0U;
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_bFindNextVirtualSector = FALSE;
							#if(STD_OFF == TI_FEE_POLLING_MODE)
							TI_FEE_NVM_JOB_END_NOTIFICATION();
							#endif
						}
						if(bVSError==FALSE)
						{
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_oCopyVirtualSectorAddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oVirtualSectorStartAddress;
							/* Next data write happens after VS Header */
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextCopyVSwriteaddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oVirtualSectorStartAddress+TI_FEE_VIRTUAL_SECTOR_OVERHEAD+16U;
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextwriteaddress  =  TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextCopyVSwriteaddress;
							/* Clear the block copy status of all blocks. All blocks need to be copied in background */
							/*SAFETYMCUSW 96 S MR:6.2,10.1,10.2,12.6 <APPROVED> "Macro comes from compiler files."*/
							TI_FeeInternal_SetClearCopyBlockState(u8EEPIndex,(boolean)FALSE);
							/* update the block copy status for current block to copied. */
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_au8BlockCopyStatus[TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockIndex][TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex]= 0x01U;
							/* Update Next write address */
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextCopyVSwriteaddress;									
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress = TI_FeeInternal_AlignAddressForECC(TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress);																	
							/* Update the status to COPY. This will enable copying of all blocks from Active VS to Copy VS in background*/
							TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Copy = 1U;									
						
							if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress>=TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextwriteaddress)				   			
							{						 					  
							  /* Update the next free write address */			
							  TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextwriteaddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress+TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize;						  
							  TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress = TI_FeeInternal_AlignAddressForECC(TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress);													  
							  
							  /* Update the next free write address in COPY or ACTIVE VS */
							  if(TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Copy == 1U)
							  {
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextCopyVSwriteaddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextwriteaddress;
							  }
							  else
							  {
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextActiveVSwriteaddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_u32nextwriteaddress;
							  }
							  TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize-=TI_FEE_BLOCK_OVERHEAD;						
							}
							else
							{
							
							}						
							/* Update block offset array */							
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_au32BlockOffset[TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockIndex][TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex]=TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress;
							/* update address for current block. This will be used in fee_main for writing block header */
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_oCurrentBlockHeader = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress;
							/* Initialize the write address for block header */
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_oWriteAddress  =  TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress;	
							/* Wait till FSM is ready to accept new write */
							(void)TI_FeeInternal_PollFlashStatus();
							/* Mark the Block header to indicate start of programming to the Block*/						
							TI_FeeInternal_StartProgramBlock(u8EEPIndex);
							DataBufferPtr = TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8DataStart;
							/* initialize Write */
							/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Null pointer check is done for 
							  TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8DataStart."*/		
							TI_FeeInternal_WriteInitialize(TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress,DataBufferPtr, u8EEPIndex);													
							/* Make the write flag as TRUE. This flag will be used in main function to write data */
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteData = TRUE;
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_bFindNextVirtualSector = FALSE;
							/* Make the partial block status write flag as TRUE to indicate partial block write needs to happen.*/
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWritePartialBlockHeader	= TRUE;
						}	
					}
					/*SAFETYMCUSW 28 D <APPROVED> "Reason -  Fee_bWriteStartProgram is made FALSE after writing */  
					while(TRUE == TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteStartProgram)
					{						
						/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
						/*SAFETYMCUSW 114 S MR:12.6,13.2 <APPROVED> "Reason -  LDRA does not understand macro 
		                 FAPI_CHECK_FSM_READY_BUSY."*/
						/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason -  ( pFapi_FmcRegistersType ) ( 0xFFF87000U ) ) casting 
		                  is done in F021 library.*/ 		  
						if(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady)
						{
							/* Mark the Block header to indicate start of programming to the Block*/						
							TI_FeeInternal_StartProgramBlock(u8EEPIndex);						
							/* Make the block status write flag as FALSE to indicate status write complete.*/
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteStartProgram = FALSE;
							/* Make the partial block status write flag as TRUE to indicate partial block write needs to happen.*/
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWritePartialBlockHeader	= TRUE;	
						}
					}					
					/*SAFETYMCUSW 28 D <APPROVED> "Reason -  Fee_bWritePartialBlockHeader is made FALSE after writing */  
					while(TRUE == TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWritePartialBlockHeader)
					{
						/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
						/*SAFETYMCUSW 114 S MR:12.6,13.2 <APPROVED> "Reason -  LDRA does not understand macro 
		                  FAPI_CHECK_FSM_READY_BUSY."*/
						/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason -  ( pFapi_FmcRegistersType ) ( 0xFFF87000U ) ) casting 
		                  is done in F021 library.*/ 		    
						if(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady)
						{
							/* Write Block number, Block Size and Block counter into Block Header */
							TI_FeeInternal_WriteBlockHeader((boolean)FALSE,u8EEPIndex,
							              (uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSizeinBlockHeader,
							              (uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockNumberinBlockHeader);
							/* Initialize Write */
							TI_FeeInternal_WriteInitialize(TI_Fee_GlobalVariables[u8EEPIndex].Fee_oFlashNextAddress,
							                       TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8DataStart, u8EEPIndex);
							/* Make the partial block status write flag as FALSE to indicate status write complete.*/
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWritePartialBlockHeader	= FALSE;	
						}	
					}										
					/* Write the data of the Block */
					while((u8loopindex<TI_FEE_NUMBER_OF_EIGHTBYTEWRITES) && 
					      (TRUE == TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteData))
					{						
						/* Write job in progress */
						/* Write the next data to the Block */
						/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
						/*SAFETYMCUSW 114 S MR:12.6,13.2 <APPROVED> "Reason -  LDRA does not understand macro 
		                  FAPI_CHECK_FSM_READY_BUSY."*/
						/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason -  ( pFapi_FmcRegistersType ) ( 0xFFF87000U ) ) casting 
		                  is done in F021 library.*/ 		    
						if(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady)
						{
							/*SAFETYMCUSW 91 D MR:16.10 <APPROVED> "Reason - Return value is used in following code."*/
							u8WriteCount=TI_FeeInternal_WriteDataF021(FALSE,
							             (uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize, u8EEPIndex);
							/* To avoid MISRA warning */
							u8WriteCount=u8WriteCount;				
							if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize <= 0x08U)
							{
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize = 0x0U;
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteData=FALSE;
								break;
							}  
							else
							{
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize-=u8WriteCount;							
							}							
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataWriteCount+=u8WriteCount;
							u8loopindex++;
						}												
					}						
					/* After writing the block, mark the block as valid */
					while((TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize==0U)&&
					       (TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteData==FALSE))
					{
						/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
						/*SAFETYMCUSW 114 S MR:12.6,13.2 <APPROVED> "Reason -  LDRA does not understand macro 
		                  FAPI_CHECK_FSM_READY_BUSY."*/
						/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason -  ( pFapi_FmcRegistersType ) ( 0xFFF87000U ) ) casting 
		                  is done in F021 library.*/ 		    
						if(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady)
						{
							/* Mark Current Block Header as VALID */
							if(0U == TI_Fee_GlobalVariables[u8EEPIndex].Fee_u8WriteCount)
							{
								/* First update CRC and Address of previous block */
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_oWriteAddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oCurrentBlockHeader + 8U;
								/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
								/*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8Data=(uint8 *)&TI_Fee_GlobalVariables[u8EEPIndex].Fee_au32BlockHeader[2];
								TI_FeeInternal_WriteBlockHeader((boolean)TRUE,u8EEPIndex,
								     (uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSizeinBlockHeader,
								     (uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockNumberinBlockHeader);
							}
							else
							{
								/* Update the block status as Valid */
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_oWriteAddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oCurrentBlockHeader;
								/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
								/*SAFETYMCUSW 95 S MR:11.1,11.4 <APPROVED> "Reason -  Casting is required here."*/
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8Data=(uint8 *)&TI_Fee_GlobalVariables[u8EEPIndex].Fee_au32BlockHeader[0];
								TI_FeeInternal_WriteBlockHeader((boolean)TRUE,u8EEPIndex,
								        (uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSizeinBlockHeader,
								    	(uint16)TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockNumberinBlockHeader);
								break;
							}							 							
						}	
					}
					/* Mark the previous block as invalid */
					/*SAFETYMCUSW 28 D <APPROVED> "Reason -  Fee_bWriteBlockHeader is made FALSE after writing */  
					while(TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteBlockHeader==TRUE)
					{
						/*SAFETYMCUSW 184 S LDRA adding spaces causes this rule to fail."*/	
						/*SAFETYMCUSW 114 S MR:12.6,13.2 <APPROVED> "Reason -  LDRA does not understand macro 
		                  FAPI_CHECK_FSM_READY_BUSY."*/
						/*SAFETYMCUSW 440 S MR:11.3 <APPROVED> "Reason -  ( pFapi_FmcRegistersType ) ( 0xFFF87000U ) ) casting 
		                  is done in F021 library.*/ 		    
						if(FAPI_CHECK_FSM_READY_BUSY == Fapi_Status_FsmReady)
						{
							if(TI_Fee_GlobalVariables[u8EEPIndex].bWriteFirstTime!=TRUE)
							{
								/* Previous block shd be configured as notvalid */
								TI_FeeInternal_WritePreviousBlockHeader((boolean)TRUE, u8EEPIndex);						
							}
							else
							{
								TI_Fee_GlobalVariables[u8EEPIndex].bWriteFirstTime = FALSE;
								TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.WriteAsync = 0U;							
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_bWriteBlockHeader = FALSE;							
								/* If copy was initiated by this write job, do not return the job status as completed*/
								if(TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Copy == 1U)
								{
									TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=JOB_PENDING;
									TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState = BUSY_INTERNAL;
								}
								else
								{									
									TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=JOB_OK;
									TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState = IDLE;
									#if(STD_OFF == TI_FEE_POLLING_MODE)
									TI_FEE_NVM_JOB_END_NOTIFICATION();
									#endif
								}
							}
						}	
					}	
				}
				else if((TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.InvalidateBlock==1U) ||
				        (TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.EraseImmediate==1U))
				{					
					TI_Fee_GlobalVariables[u8EEPIndex].Fee_u8WriteCount = 0U;					
					TI_FeeInternal_WritePreviousBlockHeader(FALSE, u8EEPIndex);
					TI_Fee_GlobalVariables[u8EEPIndex].Fee_oCurrentBlockHeader = TI_Fee_GlobalVariables[u8EEPIndex].Fee_oCurrentStartAddress;
					TI_Fee_GlobalVariables[u8EEPIndex].bWriteFirstTime=FALSE;		
					TI_Fee_GlobalVariables[u8EEPIndex].Fee_au32BlockOffset[TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockIndex][TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex]= 0xABCD1234U;										
					TI_Fee_GlobalVariables[u8EEPIndex].Fee_au8BlockCopyStatus[TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockIndex][TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex]=2U;
				}
				else if (TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Read==1U)
				{					
					while(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize>0U)
					{						
						/*SAFETYMCUSW 45 D MR:21.1 <APPROVED> "Reason -  Null pointer check is done in ti_fee_read."*/
						*TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadDataBuffer=*TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress;								
						
						/*For every eight bytes of data, there is 1 byte of ECC. We need to check for errors only
                          during first byte read of eight bytes */
						if(8U==Fee_u8WriteCounter) 	
						{	
							Fee_u8WriteCounter=0U;	
						}	
						#if(TI_FEE_FLASH_ERROR_CORRECTION_HANDLING == TI_Fee_Fix)	
						/* If there is corectable error, continue reading the data, initiate write to new location */
						if((Fee_bSingleBitError == TRUE) && (0U==Fee_u8WriteCounter))						
						{
							Device_FlashDevice.Device_BankInfo[0].Device_ControlRegister->EeCorErrAdd.EE_COR_ERR_ADD_BITS.COR_ERR_ADD;
							TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.SingleBitError = 1U;
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_au8BlockCopyStatus[TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockIndex][TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex]=3U;								
							Fee_bSingleBitError = FALSE;
						}									
						if((Fee_bDoubleBitError == TRUE) && (0U==Fee_u8WriteCounter))
						{
							oBlockAddress = TI_FeeInternal_GetCurrentBlockAddress(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockIndex,
							                      TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex,u8EEPIndex);
							Device_FlashDevice.Device_BankInfo[0].Device_ControlRegister->EeUncErrAdd.EE_UNC_ERR_ADD_BITS.UNC_ERR_ADD;								
							/* If there is uncorectable error, read the data from previous block */	
							/* Address of previous block is present after block status.*/		
							/* If block header is 24 bytes(0-23), 8-11 bytes are previous block address */
							oBlockAddress += (((TI_FEE_BLOCK_OVERHEAD >> 2U)-4U) << 2U);	
							/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <APPROVED> "Reason -  Casting is required here."*/
							ppu32ReadHeader = (uint32 **)&oBlockAddress;
							u32BlockAddressTemp = **ppu32ReadHeader;
							if((u32BlockAddressTemp<TI_Fee_GlobalVariables[u8EEPIndex].Fee_oActiveVirtualSectorStartAddress) || 
							   (u32BlockAddressTemp>TI_Fee_GlobalVariables[u8EEPIndex].Fee_oActiveVirtualSectorEndAddress))
							{	
								/* Previous Block Address is not valid. Stop reading data */
								TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Read=0U;																
								/* Set the module state to IDLE */
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState=IDLE;
								#if(STD_OFF == TI_FEE_POLLING_MODE)
								TI_FEE_NVM_JOB_ERROR_NOTIFICATION();
								#endif
							}
							else 
							{								
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress = (uint8 *)u32BlockAddressTemp;										
								*TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadDataBuffer=*TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress;								
							}														
						}						
						#endif	
						
						Fee_u8WriteCounter++;
						
						/*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Reason -  Pointer Arithmatic is necessary here."*/
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadDataBuffer++;						
						#if(TI_FEE_CHECK_BANK7_ACCESS == STD_ON)
						if((TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress > (uint8 *)Device_FlashDevice.Device_BankInfo[0].Device_SectorInfo[0].Device_SectorStartAddress)
							&& (TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress <= (uint8 *) Device_FlashDevice.Device_BankInfo[0].Device_SectorInfo[DEVICE_BANK_MAX_NUMBER_OF_SECTORS-1U].Device_SectorStartAddress+
			                    Device_FlashDevice.Device_BankInfo[0].Device_SectorInfo[DEVICE_BANK_MAX_NUMBER_OF_SECTORS-1U].Device_SectorLength))
						{
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress++;						
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize--;	
						}
						else
						{
							/* Address is out of bank7 range. Reset block size so that no furthur read's happen */
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize = 0U;
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult = JOB_FAILED;
						}	
						#else
						/*SAFETYMCUSW 567 S MR:17.1,17.4 <APPROVED> "Reason -  Pointer Arithmatic is necessary here."*/
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress++;						
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize--;	
						#endif
					}
					if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize == 0U)
					{
						#if(TI_FEE_FLASH_ERROR_CORRECTION_HANDLING == TI_Fee_Fix)
						if((Fee_bDoubleBitError == TRUE))
						{
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=BLOCK_INCONSISTENT;
							Fee_bDoubleBitError = FALSE;	
						}
						/* Finished reading */
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=JOB_OK;	
						#else
						#ifndef _L2FMC
						#if (STD_ON == TI_FEE_FLASH_ERROR_CORRECTION_ENABLE)
						/* Check if there is multi bit error/uncorectable error, update job result*/
						if(1U == Device_FlashDevice.Device_BankInfo[0].Device_ControlRegister->EeStatus.EE_STATUS_BITS.EE_UNC_ERR)
						{
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=BLOCK_INCONSISTENT;
						}
						else
						#endif
						#endif
						{
							/* Finished reading correctly */
							if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult != JOB_FAILED)
							{
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=JOB_OK;
							}
						}	
						#endif							
						TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Read=0U;
						Fee_u8WriteCounter = 0U;
						/* Set the module state to IDLE since the Read command has been completed */
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState=IDLE;
						#if(STD_OFF == TI_FEE_POLLING_MODE)
						if(1U == Device_FlashDevice.Device_BankInfo[0].Device_ControlRegister->EeStatus.EE_STATUS_BITS.EE_UNC_ERR)
						{
							TI_FEE_NVM_JOB_ERROR_NOTIFICATION();
						}
						else
						{
							TI_FEE_NVM_JOB_END_NOTIFICATION();
						}	
						#endif						
					}
					TI_Fee_GlobalVariables[u8EEPIndex].bWriteFirstTime=FALSE;
				}
				else
				{					
					TI_Fee_GlobalVariables[u8EEPIndex].bWriteFirstTime=FALSE;					
					#if(STD_OFF == TI_FEE_POLLING_MODE)
					TI_FEE_NVM_JOB_END_NOTIFICATION();
					#endif
					if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult==JOB_PENDING)
					{
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=JOB_OK;
					}
					TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState=IDLE;
				}
			}			
		}		
Esempio n. 2
0
/*! \brief      This function performs the Read operation on the Block.It initializes the pointers. Complete read of the
 *				block will happen in TI_Fee_MainFunction.
 *  \param[in]  uint16 BlockNumber
 *  \param[in]	uint16 BlockOffset
 *  \param[in]	uint8* DataBufferPtr
 *  \param[in]	uint16 Length
 *  \param[out] none
 *  \return     E_OK
 *  \return     E_NOT_OK
 *  \context    Function could be called from task level
 *  \note       TI FEE API.
 **********************************************************************************************************************/
Std_ReturnType TI_Fee_Read(uint16 BlockNumber,uint16 BlockOffset,uint8* DataBufferPtr,uint16 Length)
{
	uint32 u32BlockSize = 0U,au32BlockAddress[2],au32BlockStatus[2];
	TI_Fee_AddressType oBlockAddress=0U;
	uint16 u16BlockIndex=0U;	
	uint32 **ppu32ReadHeader=0U;	
	/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
	Std_ReturnType oResult=E_OK;
	uint16 u16DataSetNumber=0U;
	uint8 u8EEPIndex=0U;
	uint16 u16BlockNumber=0U;		
	TI_FeeModuleStatusType ModuleState=IDLE;		
	
	TI_Fee_u8DeviceIndex = 0U;		

	/* Determine the Block number & Block index */
	/* From the block number, remove data selection bits */
	u16BlockNumber = TI_FeeInternal_GetBlockNumber(BlockNumber);
	/* Get the index of the block in Fee_BlockConfiguration array */
	u16BlockIndex = TI_FeeInternal_GetBlockIndex(u16BlockNumber);	
	/* If block index is not found, report an error */
	if(u16BlockIndex == 0xFFFFU)
	{
	  TI_Fee_GlobalVariables[u8EEPIndex].Fee_oStatus = TI_FEE_ERROR;
	  TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult = JOB_FAILED;
	  TI_Fee_GlobalVariables[u8EEPIndex].Fee_Error = Error_InvalidBlockIndex;
	}
	else
	{	
		/* Read the device index from the block configuration */
		u8EEPIndex = Fee_BlockConfiguration[u16BlockIndex].FeeEEPNumber;	
		ModuleState=TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState;
		if(UNINIT == ModuleState)
		{
			/* Module is Not Initialized */
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_oStatus=TI_FEE_ERROR;
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_Error=Error_FeeUninit;
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult=JOB_FAILED;
			/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
			oResult=E_NOT_OK;
		}
		else
		{
			TI_Fee_u8DeviceIndex = u8EEPIndex;
			/* Get the DataSet index after removing the Block number */
			/*SAFETYMCUSW 91 D MR:16.10 <REVIEWED> "Reason - Return value is used in following code."*/
			u16DataSetNumber = TI_FeeInternal_GetDataSetIndex(BlockNumber);
			/* Check for any non severe errors */		
			TI_FeeInternal_CheckForError(u8EEPIndex);
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_oStatus = TI_FEE_OK;		
		}
	}
	
	if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_Error == Error_Nil)
	{
		/* Store the module state */
		ModuleState = TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState;
		/* Read current state*/
		/* If the module state is BUSY_INTERNAL, change it to IDLE */
		oResult = TI_FeeInternal_CheckModuleState(u8EEPIndex);
		/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
		if((oResult == (uint8)E_OK) && (TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Read != 1U) && (TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult != JOB_PENDING))
		{		
			/* Initialize the DataSetIndex */
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex = 0U;			
			TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockIndex = u16BlockIndex;
			/* Report error if Block index cannot be found */
			if(u16BlockIndex == 0xFFFFU)
			{
				TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult = JOB_FAILED;
				/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
				oResult = E_NOT_OK;					
			}
			else
			{
				/* Determine the Block Size */
				u32BlockSize = Fee_BlockConfiguration[u16BlockIndex].FeeBlockSize;
				TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult = JOB_PENDING;
				TI_Fee_GlobalVariables[u8EEPIndex].Fee_ModuleState = BUSY;				
				/* Check if the parameters used for Fee_Read are proper or not */
				oResult = TI_FeeInternal_CheckReadParameters(u32BlockSize,BlockOffset,DataBufferPtr,Length,u8EEPIndex);
				/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
				if(oResult == (uint8)E_OK)
				{
					/* If using more than one DataSet, find out the DataSet Index. If Dataset Index is not found, report an error */
					if(Fee_BlockConfiguration[u16BlockIndex].FeeNumberOfDataSets > 1U)
					{
						TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex = u16DataSetNumber;
						if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16DataSetIndex > Fee_BlockConfiguration[u16BlockIndex].FeeNumberOfDataSets)
						{
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult = JOB_FAILED;
							/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
							oResult = E_NOT_OK;								
						}						
					}

					if(TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult != JOB_FAILED)
					{
						/* Get the Current Block Address for this Block */
						oBlockAddress = TI_FeeInternal_GetCurrentBlockAddress(u16BlockIndex,u16DataSetNumber,u8EEPIndex);
						if(oBlockAddress == 0x00000000U)
						{
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult = BLOCK_INVALID;
							/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
							oResult = E_OK;								
						}	
					}

					if((TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult != JOB_FAILED) && (TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16JobResult != BLOCK_INVALID))
					{
						/* Read the Block Header and check if it is valid */						
						/* If invalid, report an Error else continue reading the block */				
						au32BlockAddress[0] = oBlockAddress;						
						au32BlockAddress[1] = au32BlockAddress[0]+4U;
						/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <REVIEWED> "Reason -  Casting is required here."*/									 
						ppu32ReadHeader = (uint32 **)&au32BlockAddress[0];							
						au32BlockStatus[0] = **ppu32ReadHeader;
						/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <REVIEWED> "Reason -  Casting is required here."*/									 
						ppu32ReadHeader = (uint32 **)&au32BlockAddress[1];
						au32BlockStatus[1] = **ppu32ReadHeader;

						if((au32BlockStatus[0]==ValidBlockLo) && (au32BlockStatus[1] == ValidBlockHi))
						{	
							/* Read the Data */
							/* Determine the start address for the Read command */
							/* Start Address of data  = Current Address + Block Header Size + offset in the data */															
							/*SAFETYMCUSW 45 D MR:21.1 <REVIEWED> "Reason -  Null pointer check is done for oBlockAddress."*/
							/*SAFETYMCUSW 440 S MR:11.3 <REVIEWED> "Reason -  Casting is required here."*/
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress = (uint8 *)oBlockAddress ;								
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress = TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadAddress+(uint32)TI_FEE_BLOCK_OVERHEAD+(uint32)BlockOffset;								
							/* If the length of the block to read is 0xffff, then the length of the block is read from the block header */
							if(Length == 0xFFFFU)
							{								
								/* Length of the block is present in 2 bytes of last 4 bytes*/		
								/* If block header is 24 bytes(0-23), 20-21 bytes are block size */
								oBlockAddress += (((TI_FEE_BLOCK_OVERHEAD >> 2U)-1U) << 2U);
								/*SAFETYMCUSW 94 S MR:11.1,11.2,11.4 <REVIEWED> "Reason -  Casting is required here."*/									 
								ppu32ReadHeader = (uint32 **)&oBlockAddress;
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize = (uint16)(((**ppu32ReadHeader)&0xFFFF0000U)>>16U);
								oBlockAddress -= (((TI_FEE_BLOCK_OVERHEAD >> 2U)-1U) << 2U);
							} 
							else
							{
								TI_Fee_GlobalVariables[u8EEPIndex].Fee_u16BlockSize = Length;
							}	
							/* Update the pointer. Reading will happen in main function */									
							TI_Fee_GlobalVariables[u8EEPIndex].Fee_pu8ReadDataBuffer = DataBufferPtr;									
							TI_Fee_oStatusWord[u8EEPIndex].Fee_StatusWordType_ST.Read = 1U;
							/*SAFETYMCUSW 331 S MR:10.1 <REVIEWED> "Reason - Std_ReturnType is not part of FEE.This should be fixed outside of FEE."*/
							oResult = (uint8)E_OK;								
						}