/*********************************************************************************************************************
*
* Description:     BootM module implementation
* FileName:        FBL_BootM.c
* Company:         ETAS GmbH (www.etas.com)
* Generated        28/12/2018 at 11:22
*
**********************************************************************************************************************
*
* COPYRIGHT RESERVED, Copyright ETAS GmbH 2018. All rights reserved, also regarding any disposal,
* exploitation, reproduction, editing, distribution, as well as in the event of applications
* for industrial property rights.
*
**********************************************************************************************************************
* History:
**********************************************************************************************************************
* Author        Date            Comment
**********************************************************************************************************************
BGA1YOK         29/01/2018      First Version    
**********************************************************************************************************************/


/*********************************************************************************************************************
* Includes
*********************************************************************************************************************/
#include "FBL_BootM.h"
#include "FBL_BootMPrv.h"
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_OFF
#endif
#include "CanSM_ComM.h"
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_ON
#endif
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_OFF
#endif
#include "Dcm.h"
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_ON
#endif
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_OFF
#endif
#include "DcmAppl.h"
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_ON
#endif
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_OFF
#endif
#include "DcmCore_DslDsd_Prot.h"
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_ON
#endif
#include "FBL_DataM.h"
#include "FBL_Port.h"
#include "Fee.h"
#include "NvM.h"
#include "MemIf.h"
#include "MemIf_Cfg.h"

// Removing of compiler warnings and errors because of type re-declaration between hal_stdtypes.h and Std_Types.h
#define _BOOLEAN_DECLARED
#define _UINT8_DECLARED
#define _UINT16_DECLARED
#define _UINT32_DECLARED
#define _UINT64_DECLARED
#define _SINT8_DECLARED
#define _SINT16_DECLARED
#define _SINT32_DECLARED
#define _SINT64_DECLARED
#define _FLOAT32_DECLARED
#define _FLOAT64_DECLARED
#define _STD_RETURN_TYPE_DECLARED
#define _STDVERSION_DECLARED

#include "Ios_IntrTimerManagement.h"
#include "Ios_BoardLedMngt.h"
#include "Ios_Terminal.h"
#include "sys_core.h"
#include "Ios_Std.h"
#include "Ios_BoardExtWdgMngt.h"
//#include "ti_Fee.h"

/*********************************************************************************************************************
* Local Defines
*********************************************************************************************************************/
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 14] */
#define FBL_BOOTM_REPROGRAMMING_REQUEST_FLAG_STATE_ON  ((Fbl_BootM_ReprogrammingRequestFlagStateType) 0xAAFF55AAUL)
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 15] */
#define FBL_BOOTM_REPROGRAMMING_REQUEST_FLAG_STATE_OFF ((Fbl_BootM_ReprogrammingRequestFlagStateType) 0x55AAFF55UL)
/*********************************************************************************************************************
* Local Macros
*********************************************************************************************************************/

/*********************************************************************************************************************
* Local Types
*********************************************************************************************************************/
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 1] */
typedef enum
{
  FBL_BOOTM_CMPSTATE_NOT_INIT,
  FBL_BOOTM_CMPSTATE_INIT
}Fbl_BootM_CmpStateType;

/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 2] */
typedef enum
{
  FBL_BOOTM_SYSTEM_STATE_RUNNING, 
  FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING
} Fbl_BootM_SystemStateType;
/*********************************************************************************************************************
* Local Variables
*********************************************************************************************************************/
/* Component status */ 
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 6] */
static Fbl_BootM_CmpStateType Fbl_BootM_CmpState = FBL_BOOTM_CMPSTATE_NOT_INIT;
/* Main function state variables */
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 7] */
static Fbl_BootM_SystemStateType Fbl_BootM_CurrentSystemState = FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING;
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 8] */
static Fbl_BootM_SystemStateType Fbl_BootM_PreviousSystemState = FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING;

/*********************************************************************************************************************
* Local Functions Prototypes
*********************************************************************************************************************/

/*********************************************************************************************************************
* Local Functions Implementation
*********************************************************************************************************************/

/*********************************************************************************************************************
* Exported Variables Implementation
*********************************************************************************************************************/

/*********************************************************************************************************************
* Exported Functions Implementation
*********************************************************************************************************************/

/*********************************************************************************************************************
* Local Functions Prototypes
*********************************************************************************************************************/
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 12] */
static void Fbl_BootM_DcmSessionMonitor (void);
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 13] */
static Std_ReturnType Fbl_BootM_ClearReprogrammingRequestFlag(void);
/*********************************************************************************************************************
* Local Functions Implementation
*********************************************************************************************************************/
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 12] */
/* Implement Bootloader Session transition in accordance with ISO14229 */
static void Fbl_BootM_DcmSessionMonitor(void)
{
    /* Repogramming request, flag */
    Fbl_BootM_ReprogrammingRequestFlagStateType reprogrammingRequestFlagState;
    (void)Fbl_BootM_ReadReprogrammingRequestFlag(&reprogrammingRequestFlagState);
    if (FBL_BOOTM_REPROGRAMMING_REQUEST_FLAG_STATE_ON == reprogrammingRequestFlagState)
    {
        (void)Fbl_BootM_ClearReprogrammingRequestFlag();
    }
}

/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 13] */
static Std_ReturnType Fbl_BootM_ClearReprogrammingRequestFlag(void)
{
  Std_ReturnType ret;
  const Fbl_BootM_ReprogrammingRequestFlagStateType flag = FBL_BOOTM_REPROGRAMMING_REQUEST_FLAG_STATE_OFF;
  /* PRQA S 0310 EOF */ /* Deviation: Rule 11.3 */ /* MISRA Deviation: Casting to different object pointer type is acceptable */
  ret =  Fbl_DataM_NvmReprogrammingRequestFlagWriteFunc((const uint8 *) &flag);
  return ret;
}
/*********************************************************************************************************************
* Exported Variables Implementation
*********************************************************************************************************************/

/*********************************************************************************************************************
* Exported Functions Implementation
*********************************************************************************************************************/

/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 19] */
void Fbl_BootM_Init (void)
{
  Fbl_BootM_CmpState = FBL_BOOTM_CMPSTATE_INIT;
  Fbl_BootM_CurrentSystemState  = FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING;
  Fbl_BootM_PreviousSystemState = FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING;
}
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 20] */
void Fbl_BootM_DeInit (void)
{
	Fbl_BootM_CmpState = FBL_BOOTM_CMPSTATE_NOT_INIT;
}

uint8 Fbl_IsReprogammingRequested(void)
{
    Fbl_BootM_ReprogrammingRequestFlagStateType reprogrammingRequestFlagState;
    (void)Fbl_BootM_ReadReprogrammingRequestFlag(&reprogrammingRequestFlagState);

    return ((uint8)(FBL_BOOTM_REPROGRAMMING_REQUEST_FLAG_STATE_ON == reprogrammingRequestFlagState));
}
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 21] */
void Fbl_BootM_MainFunction (void)
{
  ComM_ModeType commStatus;
  Std_ReturnType opResult;
  if (Fbl_BootM_CmpState == FBL_BOOTM_CMPSTATE_INIT)
  {
    switch(Fbl_BootM_CurrentSystemState)
    {
      case FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING:
      {
        Fbl_BootM_PreviousSystemState = FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING;
        opResult = CanSM_GetCurrentComMode(ComMConf_ComMChannel_ComMChannel_Can_Network_Channel,&commStatus);
        if ((E_OK == opResult) && (COMM_FULL_COMMUNICATION == commStatus))
        {
          Fbl_BootM_CurrentSystemState = FBL_BOOTM_SYSTEM_STATE_RUNNING;
        }
        break;
      }
      case FBL_BOOTM_SYSTEM_STATE_RUNNING:
      {
        Fbl_BootM_PreviousSystemState = FBL_BOOTM_SYSTEM_STATE_RUNNING;
        /* Call Dcm Session monitor service */
        Fbl_BootM_DcmSessionMonitor();
        break;
      }
      default:
      {
        /* Should never get here */
        Fbl_BootM_CurrentSystemState = FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING;
        Fbl_BootM_PreviousSystemState = FBL_BOOTM_SYSTEM_STATE_PRE_RUNNING;
        break;
      }
    }
  }
}

/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 22] */
void Fbl_BootM_CheckEcuState (void)
{

    NvM_Rb_StatusType status_NvM;
    MemIf_StatusType stMemIf_en;

    //NvM_Rb_StatusType NvM_WriteAllStatusflag;
    //TI_FeeModuleStatusType Status = IDLE;

    /* Repogramming request, flag */
    Fbl_BootM_ReprogrammingRequestFlagStateType reprogrammingRequestFlagState;
    boolean applicationIsValid = (boolean)FALSE;

    (void)Fbl_BootM_ReadReprogrammingRequestFlag(&reprogrammingRequestFlagState);

    if (FBL_BOOTM_REPROGRAMMING_REQUEST_FLAG_STATE_ON != reprogrammingRequestFlagState)
    {

        //applicationIsValid = FALSE; //Fbl_Port_ApplicationIsValid(); // Test to stay in boot
        //applicationIsValid = TRUE; //Fbl_Port_ApplicationIsValid(); // Test to to force jump to app
        applicationIsValid = Fbl_Port_ApplicationIsValid();

        if ((boolean)TRUE == applicationIsValid)
        {
            // Stop counters and save counter values in NVM
            rtiStopCounter(rtiCOUNTER_BLOCK0);
            rtiStopCounter(rtiCOUNTER_BLOCK1);
            fnIosSaveRTICountersToNVM();

            /* Internal Non-volatile memory write */
            //        do
            //        {
            //            /* Execute */
            //            Fbl_DataM_MainFunction();
            //            NvM_MainFunction();
            //            TI_Fee_MainFunction();
            //            //(void)MemIf_Rb_MainFunction();
            //            (void)NvM_Rb_GetStatus(&NvM_WriteAllStatusflag);
            //            Status = (TI_FeeModuleStatusType)MemIf_GetStatus(0);
            //        } while ((NvM_WriteAllStatusflag == NVM_RB_STATUS_BUSY)|| (Status != IDLE));

            NvM_WriteAll();

            do
            {
                Fbl_DataM_MainFunction();
                NvM_MainFunction();
                MemIf_Rb_MainFunction();

                NvM_Rb_GetStatus(&status_NvM);
                stMemIf_en = MemIf_Rb_GetStatus();
                dwdReset();

            } while ( (status_NvM == NVM_RB_STATUS_BUSY ) || (stMemIf_en == MEMIF_BUSY) || (Fbl_DataM_NvmAllBlocksArePersisted() == FALSE));

        wcu_printf("Jumping to App.\n");
        fnIosFlushTxQueue();

        //fnIosShutdownBoardLeds();
        fnIosTurnAllBoardLedsON(); // Turn all LED ON before jumping to give sign of life when jumping to App

        (void)_disable_interrupt_();
        fnIosForceExtrernalWdgKick();    // Refresh external watchdog one last time before jumping to App
        dwdReset();                     // Refresh internal watchdog one last time before jumping to App

        /* Jump to customer APP */
        (*Fbl_BootM_StartCustomerApp)(); // Jump to app start address
    }
    else
    {
      /* do nothing, stay in bootloader */
    }
  }
  else
  {
    /* do nothing, stay in bootloader */
  }
}

/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 29] */
Std_ReturnType Fbl_BootM_ReadReprogrammingRequestFlag(Fbl_BootM_ReprogrammingRequestFlagStateType * flag)
{
  Std_ReturnType ret;
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_OFF 310
#endif
/* MISRA DEVIATION: Cast necessary to be compatible with function prototype */
  ret = Fbl_DataM_NvmReprogrammingRequestFlagReadFunc((uint8 * ) flag);
#ifdef __PQRA_QAC__
#pragma PRQA_MESSAGES_ON
#endif
  return ret;
}

/************************************/
/* Callback implementations for DCM */
/************************************/
/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 23] */
FUNC(void,DCM_APPL_CODE) DcmAppl_Switch_DcmDiagnosticSessionControl(VAR(Dcm_SesCtrlType,AUTOMATIC) SessionMode)
{

}

/* [$Satisfies $RTA_FBL_SDK_DD_BOOTM 24] */
FUNC(Dcm_EcuStartModeType,DCM_APPL_CODE) Dcm_GetProgConditions (P2VAR(Dcm_ProgConditionsType,AUTOMATIC,DCM_INTERN_DATA) ProgConditions )
{
    Dcm_EcuStartModeType startMode = DCM_COLD_START;
    Dcm_ProgConditionsType progConditionsStored;
    /* restore information from NVM to send response */
    /* PRQA S 0310 2 */ /* Deviation: Rule 11.3 */ /* MISRA Deviation: Casting to different object pointer type is acceptable */
    (void)Fbl_DataM_NvmProgramConditionsReadFunc((uint8*)&progConditionsStored);
    /* response from previous reset is required */ 
    if ((boolean)TRUE == progConditionsStored.ResponseRequired)
    {
        /* copy the saved structure to Dcm */
        (*ProgConditions) = progConditionsStored;
        /* clear NvM value to send response only once */
        (void)rba_BswSrv_MemSet(&progConditionsStored, 0x00, sizeof(progConditionsStored));
        /* PRQA S 0310 2 */ /* Deviation: Rule 11.3 */ /* MISRA Deviation: Casting to different object pointer type is acceptable */
        (void)Fbl_DataM_NvmProgramConditionsWriteFunc((uint8*)&progConditionsStored);
        startMode = DCM_WARM_START;
    }
    else
    {
    /* do nothing and return startMode as DCM_COLD_START */
    }
    return startMode;
}
