/* ======================================================================
*   Copyright (C) 2022 Texas Instruments Incorporated
*
*   All rights reserved. Property of Texas Instruments Incorporated.
*   Restricted rights to use, duplicate or disclose this code are
*   granted through contract.
*
*   The program may not be used without the written permission
*   of Texas Instruments Incorporated or against the terms and conditions
*   stipulated in the agreement under which this program has been
*   supplied.
* ==================================================================== */

/**
 *  \file     CanApp.c
 *
 *  \brief    This file contains the Can test example
 */

/*******************************************************************************
 *  INCLUDES
 ******************************************************************************/

/* Include Files */
#include "string.h"
#include "Std_Types.h"
#include "Det.h"
#include "Dem.h"
#include "Can.h"
#include "CanIf_Cbk.h"
#include "EcuM_Cbk.h"
#include "Mcu.h"
#include "Mcu_Cfg.h"
#include "Port.h"
#include "Port_Cfg.h"
#include "hw_types.h"
#include "esm.h"
#include "sys_vim.h"
#include "app_utils.h"
#include "trace.h"

uint8 MainFunc_Execution;

#define APP_NAME "CanApp"
#define CANEXAMPLE_ARRAYSIZE(x)  (sizeof ((x)) / sizeof (x[0U]))

extern const Can_ConfigType CanConfigSet;
#if (STD_OFF == MCU_NO_PLL)
extern CONST(Mcu_ConfigType, MCU_PBCFG) McuModuleConfiguration_0;
#endif
static volatile uint32 msgCounter1 = 0U, CanIf_TxConfirmationCount = 0U;
static volatile uint32 eccErrCnt = 0U;
Can_PduType                 Pdu, Pdu1, Pdu2, Pdu3;
Std_VersionInfoType         VersionInfo;
uint8                       CanRxData[64U], dlc;
Can_IdType                  CanIdVal;
uint32                      ExecutionTicks, eccErrType;
uint32                      gTestPassed = E_OK;
Can_PduType                 Pdunit;
boolean                     bCanBusOff;
uint8                       data[64U] =
{0xA1, 0x1A, 0xFF, 0xFF, 0xC1, 0x1C, 0xB1, 0x1B,
0xA2, 0x2A, 0xFF, 0xFF, 0xC2, 0x2C, 0xB2, 0x2B,
0xA3, 0x3A, 0xFF, 0xFF, 0xC3, 0x3C, 0xB3, 0x3B,
0xA4, 0x4A, 0xFF, 0xFF, 0xC4, 0x4C, 0xB4, 0x4B,
0xA5, 0x5A, 0xFF, 0xFF, 0xC5, 0x5C, 0xB5, 0x5B,
0xA6, 0x6A, 0xFF, 0xFF, 0xC6, 0x6C, 0xB6, 0x6B,
0xA7, 0x7A, 0xFF, 0xFF, 0xC7, 0x7C, 0xB7, 0x7B,
0xA8, 0x8A, 0xFF, 0xFF, 0xC8, 0x8C, 0xB8, 0x8B};

#define APP_LOOPBACK_MODE      STD_OFF

Mcu_RamSectionConfigType    Mcu_RamConfig[] =
{
    [0U] =
    {
    .Mcu_RamSectionBaseAddress = &CanRxData[0U],
    .Mcu_RamDefaultValue       = 0xFF,
    .Mcu_RamSectionBytes       = sizeof (CanRxData)
    },
    [1U] =
    {
    .Mcu_RamSectionBaseAddress = (uint8 *) &Pdu,
    .Mcu_RamDefaultValue       = 0x00,
    .Mcu_RamSectionBytes       = sizeof (Pdu)
    },
    [2U] =
    {
    .Mcu_RamSectionBaseAddress = (uint8 *) &Pdu1,
    .Mcu_RamDefaultValue       = 0x00,
    .Mcu_RamSectionBytes       = sizeof (Pdu1)
    },
	[3U] =
    {
    .Mcu_RamSectionBaseAddress = (uint8 *) &Pdu2,
    .Mcu_RamDefaultValue       = 0x00,
    .Mcu_RamSectionBytes       = sizeof (Pdu2)
    },
	[4U] =
    {
    .Mcu_RamSectionBaseAddress = (uint8 *) &Pdu3,
    .Mcu_RamDefaultValue       = 0x00,
    .Mcu_RamSectionBytes       = sizeof (Pdu3)
    },
    [5U] =
    {
    .Mcu_RamSectionBaseAddress = (uint8 *) &VersionInfo,
    .Mcu_RamDefaultValue       = 0x00,
    .Mcu_RamSectionBytes       = sizeof (VersionInfo)
    },
};

static Mcu_ClockConfigType      gCanAppMcuClockConfig[] =
{
    [0] =
    {
    .Mcu_InitCfg       = TRUE,
    .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_MCAN0,
    .Mcu_ClockSourceId = MCU_CLKSRC_4,
    .Mcu_ClockDiv      = 4U /* mcu clock div for 80 MhZ, with 400 MHz clock */
    },
    [1] =
    {
    .Mcu_InitCfg       = TRUE,
    .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_MCAN1,
    .Mcu_ClockSourceId = MCU_CLKSRC_4,
    .Mcu_ClockDiv      = 4U /* 80MHz */   
    },
	[2] =
    {
    .Mcu_InitCfg       = TRUE,
    .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_MCAN2,
    .Mcu_ClockSourceId = MCU_CLKSRC_4,
    .Mcu_ClockDiv      = 4U /* 80MHz */   
    },
	[3] =
    {
    .Mcu_InitCfg       = TRUE,
    .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_MCAN3,
    .Mcu_ClockSourceId = MCU_CLKSRC_4,
    .Mcu_ClockDiv      = 4U /* 80MHz */   
    },
    [4] =
    {
    .Mcu_ClockModuleId = MCU_CLKSRC_MODULE_ID_SCI0,
    .Mcu_ClockSourceId = MCU_CLKSRC_3,
    .Mcu_ClockDiv = 3,
    .Mcu_InitCfg  = TRUE,
    }
};

Mcu_ConfigType              Mcu_Config =
{
    .Mcu_ResetMode           = MCU_PERFORM_RESET_MODE_WARM,
    .Mcu_ConfigRamSection    = (Mcu_RamSectionConfigType *) Mcu_RamConfig,
    .Mcu_NumberOfRamSectors  = CANEXAMPLE_ARRAYSIZE(Mcu_RamConfig),
    .Mcu_ClockConfig         = (Mcu_ClockConfigPtrType) gCanAppMcuClockConfig,
    .Mcu_NumberOfClockConfig = CANEXAMPLE_ARRAYSIZE(gCanAppMcuClockConfig)
};

static void CanExample_PlatformInit()
{
    uint16 mss_uart_tx_pin, mss_uart_rx_pin;
    uint32 sys_clk_freq_vclk_const;
    
    #if (STD_OFF == MCU_NO_PLL)
    /* MCU PLL Config */
    Mcu_Config.Mcu_PllConfig = McuModuleConfiguration_0.Mcu_PllConfig;
    Mcu_Config.Mcu_PllSourceId = McuModuleConfiguration_0.Mcu_PllSourceId;
    #endif

    Mcu_Init(&Mcu_Config);
    Port_Init(PortConfigSet_0_pt);
    Mcu_InitRamSection(0);
    Mcu_InitRamSection(1);
    Mcu_InitRamSection(2);
    Mcu_InitRamSection(3);
	Mcu_InitRamSection(4);
	Mcu_InitRamSection(5);

    mss_uart_tx_pin = 13;
    mss_uart_rx_pin = 14;
    Port_SetPinMode(mss_uart_tx_pin, PORT_PIN_MODE_LIN0);
    /* Set up the pinmux for UART rx */
    Port_SetPinMode(mss_uart_rx_pin, PORT_PIN_MODE_LIN0);
	Port_SetPinDirection(mss_uart_rx_pin, PORT_PIN_IN);
   
    #if (STD_OFF == MCU_NO_PLL)
    if(McuModuleConfiguration_0.Mcu_PllSourceId == MCU_CLKSRC_DPLL)
    {
		

        sys_clk_freq_vclk_const = (McuModuleConfiguration_0.
		Mcu_PllConfig[MCU_CLKSRC_DPLL].Mcu_PllClk1.MCU_PLL_HSDIV2 / (2e6)) * 30;
    }
    else
    {
        sys_clk_freq_vclk_const = (McuModuleConfiguration_0.
		Mcu_PllConfig[MCU_CLKSRC_APLL].Mcu_PllClk1.MCU_PLL_HSDIV0 / (2e6)) * 30;
    }
    Enable_Uart();
    #else
    Enable_Uart();
    #endif
    
}

#if defined (CAN_CONTROLLER_MCAN1) || defined (CAN_CONTROLLER_MCAN2) || defined (CAN_CONTROLLER_MCAN3) ||defined (CAN_CONTROLLER_MCAN4)
#if (STD_ON == CAN_ECC_ENABLE)
/* 51 MSS_MCANA_SERR Single Bit correctable error indication for MCANA Message Memory */
/* 50 MSS_MCANA_UERR Multi Bit uncorrectable error indication for MCANA Message Memory */
/* 48 MSS_MCANB_SERR Single Bit correctable error indication for MCANB Message Memory */
/* 47 MSS_MCANB_UERR Multi Bit uncorrectable error indication for MCANB Message Memory */
/* #define CANFD_ESM_MASK          (uint64)(0x4800000000000) */
#define CANFD_ESM_MASK          (uint64)(0xC000000000000)
/* #define CANFD2_ESM_MASK         (uint64)(0x000200200000) */
#define CANFD2_ESM_MASK         (uint64)(0x3000000000000)
void esm_low_priority_handler (void)
{
#if (STD_ON == CAN_ECC_ENABLE)
#if defined (CAN_CONTROLLER_MCAN1)
    uint64 esmStatus2 = esmGetStatus(esmREG, 0, CANFD1_ESM_MASK);
    if (esmStatus2)
    {
        Can_0_Int1ISR_Fun();
        esmClearStatus(esmREG, 0, CANFD2_ESM_MASK);
}
#endif
#if defined (CAN_CONTROLLER_MCAN2)
    uint64 esmStatus = esmGetStatus(esmREG, 0, CANFD2_ESM_MASK);
    if (esmStatus)
    {
      esmClearStatus(esmREG, 0, CANFD_ESM_MASK);
      Can_1_Int1ISR_Fun();
    }
#endif
#if defined (CAN_CONTROLLER_MCAN3)
    uint64 esmStatus = esmGetStatus(esmREG, 0, CANFD3_ESM_MASK);
    if (esmStatus)
    {
      esmClearStatus(esmREG, 0, CANFD_ESM_MASK);
      Can_2_Int1ISR_Fun();
    }
#endif
#if defined (CAN_CONTROLLER_MCAN4)
    uint64 esmStatus = esmGetStatus(esmREG, 0, CANFD4_ESM_MASK);
    if (esmStatus)
    {
      esmClearStatus(esmREG, 0, CANFD_ESM_MASK);
      Can_3_Int1ISR_Fun();
    }
#endif
#endif
}

#endif
#endif

static void CanExample_InterruptConfig(void)
{
    vimInit();
    Vim_IntCfg Can_IntCfg;
    Can_IntCfg.map = VIM_INTTYPE_IRQ;
    Can_IntCfg.type = VIM_INTTRIGTYPE_LEVEL;
    Can_IntCfg.intNum = MCAN0_MCAN_LVL_INT_0;

#if defined (CAN_CONTROLLER_MCAN1)
    Can_IntCfg.intNum = MCAN0_MCAN_LVL_INT_0;    
    Can_IntCfg.handler = Can_0_Int0ISR;
    Can_IntCfg.priority = VIM_PRIORITY_3;
    vimRegisterInterrupt(&Can_IntCfg);

#if (STD_ON == CAN_ECC_ENABLE)
    Can_IntCfg.intNum = MSS_ESM_LO;
    Can_IntCfg.handler = esm_low_priority_handler;
    Can_IntCfg.priority = VIM_PRIORITY_4;
    vimRegisterInterrupt(&Can_IntCfg);

    esmClearStatus(esmREG, 0, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 1, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 2, 0xFFFFFFFFFFFFFFFF);

    esmSetInterruptLevel(esmREG, CANFD1_ESM_MASK, 0U);
    esmEnableInterrupt(esmREG, CANFD1_ESM_MASK);
#endif
#endif

#if defined (CAN_CONTROLLER_MCAN2)
    Can_IntCfg.intNum = MCAN1_MCAN_LVL_INT_0;
    Can_IntCfg.handler = Can_1_Int0ISR;
    Can_IntCfg.priority = VIM_PRIORITY_5;
    vimRegisterInterrupt(&Can_IntCfg);

#if (STD_ON == CAN_ECC_ENABLE)
    Can_IntCfg.intNum = MSS_ESM_LO;
    Can_IntCfg.handler = esm_low_priority_handler;
    Can_IntCfg.priority = VIM_PRIORITY_4;
    vimRegisterInterrupt(&Can_IntCfg);

    esmClearStatus(esmREG, 0, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 1, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 2, 0xFFFFFFFFFFFFFFFF);

    esmSetInterruptLevel(esmREG, CANFD2_ESM_MASK, 0U);
    esmEnableInterrupt(esmREG, CANFD2_ESM_MASK);
#endif
#endif
#if defined (CAN_CONTROLLER_MCAN3)
    Can_IntCfg.intNum = MCAN2_MCAN_LVL_INT_0;
    Can_IntCfg.handler = Can_2_Int0ISR;
    Can_IntCfg.priority = VIM_PRIORITY_6;
    vimRegisterInterrupt(&Can_IntCfg);

#if (STD_ON == CAN_ECC_ENABLE)
    Can_IntCfg.intNum = MSS_ESM_LO;
    Can_IntCfg.handler = esm_low_priority_handler;
    Can_IntCfg.priority = VIM_PRIORITY_4;
    vimRegisterInterrupt(&Can_IntCfg);

    esmClearStatus(esmREG, 0, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 1, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 2, 0xFFFFFFFFFFFFFFFF);

    esmSetInterruptLevel(esmREG, CANFD3_ESM_MASK, 0U);
    esmEnableInterrupt(esmREG, CANFD3_ESM_MASK);
#endif
#endif
#if defined (CAN_CONTROLLER_MCAN4)
    Can_IntCfg.intNum = MCAN3_MCAN_LVL_INT_0;
    Can_IntCfg.handler = Can_3_Int0ISR;
    Can_IntCfg.priority = VIM_PRIORITY_7;
    vimRegisterInterrupt(&Can_IntCfg);

#if (STD_ON == CAN_ECC_ENABLE)
    Can_IntCfg.intNum = MSS_ESM_LO;
    Can_IntCfg.handler = esm_low_priority_handler;
    Can_IntCfg.priority = VIM_PRIORITY_4;
    vimRegisterInterrupt(&Can_IntCfg);

    esmClearStatus(esmREG, 0, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 1, 0xFFFFFFFFFFFFFFFF);
    esmClearStatus(esmREG, 2, 0xFFFFFFFFFFFFFFFF);

    esmSetInterruptLevel(esmREG, CANFD4_ESM_MASK, 0U);
    esmEnableInterrupt(esmREG, CANFD4_ESM_MASK);
#endif
#endif
}

#if (STD_ON == APP_LOOPBACK_MODE)
static void CanExample_LoopbackTest()
{
    uint32 cntr_cnt, mask = 0x00000000U;;
    const Can_ConfigType *Can_ConfigPtr;
    Can_PduType    *PduInfo;
    uint8 loopCnt = 0U, hth = 0U;
    Can_ReturnType        status;

    Can_ConfigPtr = &CanConfigSet;
    /* Message for CAN-FD(MCAN module) */
    PduInfo         = &Pdu;
    /* Setting Up CAN FD Frame*/
    Pdu.id          = 0xC1 | 0x40000000U;
    Pdu.length      = 64U;
    Pdu.swPduHandle = 1U;
    Pdu.sdu         = &data[0U];

    /* Message for CAN(DCAN module) */
    /* Setting Up CAN FD Frame*/
    Pdu1.id          = 0xC1;
    Pdu1.length      = 8U;
    Pdu1.swPduHandle = 1U;
    Pdu1.sdu         = &data[0U];
	
	Pdu2.id          = 0xC1;
    Pdu2.length      = 8U;
    Pdu2.swPduHandle = 2U;
    Pdu2.sdu         = &data[0U];
	
	Pdu3.id          = 0xC1;
    Pdu3.length      = 8U;
    Pdu3.swPduHandle = 2U;
    Pdu3.sdu         = &data[0U];


    AppUtils_printf(APP_NAME ": CAN Loopback test \n\r");
    /* Do Can Init */
    Can_Init(Can_ConfigPtr);    
    for (cntr_cnt = 0U ;    
         cntr_cnt < (Can_ConfigPtr->CanMaxControllerCount) ;
         cntr_cnt++)
    {
        /* Flush RxData */
        for (loopCnt = 0U; loopCnt < Pdu.length; loopCnt++)
        {
            CanRxData[loopCnt] = 0;
        }
        if (CAN_CONTROLLER_INSTANCE_MCAN1 ==
            Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
        {
            AppUtils_printf(APP_NAME ": Can Controller: MCAN1  (CAN_CONTROLLER_INSTANCE_MCAN1)\n\r");
            PduInfo         = &Pdu;
            hth = 0U;
            /* mask is need for checking id of received message with
             * sent message as 30th bit the of sent message will be set
             * for CAN FD frame */
            mask = 0x40000000U;
        }
        else if (CAN_CONTROLLER_INSTANCE_MCAN2 ==
                Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
        {
            AppUtils_printf(APP_NAME ": Can Controller: MCAN2  (CAN_CONTROLLER_INSTANCE_MCAN2)\n\r");
            PduInfo         = &Pdu1;
            hth = 2U;
            mask = 0x00000000U;
        }
        else if (CAN_CONTROLLER_INSTANCE_MCAN3 ==
                Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
        {
            AppUtils_printf(APP_NAME ": Can Controller: MCAN3  (CAN_CONTROLLER_INSTANCE_MCAN3)\n\r");
            PduInfo         = &Pdu2;
            hth = 4U;
            mask = 0x00000000U;
        }
        else if (CAN_CONTROLLER_INSTANCE_MCAN4 ==
                Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
        {
            AppUtils_printf(APP_NAME ": Can Controller: MCAN4  (CAN_CONTROLLER_INSTANCE_MCAN4)\n\r");
            PduInfo         = &Pdu3;
            hth = 6U;
            mask = 0x00000000U;
        }
        else
        {
        }
        /* Set Controller Mode for controller 0U */
        status = Can_SetControllerMode(Can_ConfigPtr->
                        CanControllerList[cntr_cnt]->ControllerId, CAN_CS_STARTED);
        if (status != CAN_OK)
        {
            gTestPassed = E_NOT_OK;
        }

#if (CAN_LOOPBACK_ENABLE == STD_ON)
        /* Enable loopback mode in CAN */
        Can_TestLoopBackModeEnable(Can_ConfigPtr->
                                   CanControllerList[cntr_cnt]->ControllerId,
                                   0U);
#endif

        /* Do Can Write to send the data on CAN bus */
        AppUtils_printf(APP_NAME "Calling Can_Write \n\r");
        status = Can_Write(hth, PduInfo);        
        if (status != CAN_OK)
        {
            AppUtils_printf(APP_NAME ": Error In Can_Write.\n\r");
            gTestPassed = E_NOT_OK;
        }
        AppUtils_printf(APP_NAME "Can_Write ok \n\r");

        /* Delay required else ISR will not be able to clear flag.
         * Delay should be enough for ISR execution */
//#ifdef CAN_APP_QT
        //AppUtils_delay(5U);        
//#else 
        AppUtils_delay(30U);
//#endif         
#if (CAN_TX_POLLING == STD_ON)
				Can_MainFunction_Write();
#endif

#if (CAN_RX_POLLING == STD_ON)
				Can_MainFunction_Read();
#endif
        
        if (E_OK == gTestPassed)
        {
            if (0U != eccErrCnt)
            {
                eccErrCnt= 0U;
                gTestPassed = E_NOT_OK;
                if ((uint32)CAN_ECC_ERROR_TYPE_PARITY == eccErrType)
                {
                    AppUtils_printf(APP_NAME ": Parity Error Detected.\n\r");
                }
                else if ((uint32)CAN_ECC_ERROR_TYPE_SEC == eccErrType)
                {
                    AppUtils_printf(APP_NAME ": SEC Error Detected.\n\r");
                }
                else if ((uint32)CAN_ECC_ERROR_TYPE_DED == eccErrType)
                {
                    AppUtils_printf(APP_NAME ": DED Error Detected.\n\r");
                }
                else
                {
                }
                break;
            }
            else if ((1U == CanIf_TxConfirmationCount) && (1U == msgCounter1))
            {
                CanIf_TxConfirmationCount = 0U;
                msgCounter1 = 0U;
            }
            else
            {
                gTestPassed = E_NOT_OK;
                break;
            }
            /* Set Controller Mode for controller 0U */
            status = Can_SetControllerMode(Can_ConfigPtr->
                            CanControllerList[cntr_cnt]->ControllerId, CAN_CS_STOPPED);
            if (status != CAN_OK)
            {
                gTestPassed = E_NOT_OK;
            }
#if (CAN_LOOPBACK_ENABLE == STD_ON)
            Can_TestLoopBackModeDisable(Can_ConfigPtr->
                                    CanControllerList[cntr_cnt]->ControllerId,
                                    0U);
#endif
            if ((PduInfo->length == dlc) && (PduInfo->id == (CanIdVal | mask)))
            {
                for (loopCnt = 0U; loopCnt < PduInfo->length; loopCnt++)
                {
                    if (CanRxData[loopCnt] != data[loopCnt])
                    {
                        gTestPassed = E_NOT_OK;
                        AppUtils_printf(APP_NAME ": Transmitted and Received data miss-matched.\n\r");
                    }
                }
            }
            else
            {
                gTestPassed = E_NOT_OK;
                break;
            }
        }
        if (gTestPassed == E_OK)
        {
            AppUtils_printf(APP_NAME ": Test Passed\n\r");
        }
    }
}

#else
static void CanExample_ExternalTest()
{
    char           option;
    boolean quit_opt = 0;
    uint32 cntr_cnt;//,mask = 0x00000000U;
    const Can_ConfigType *Can_ConfigPtr;
    Can_PduType    *PduInfo;
    uint8 loopCnt = 0U, hth = 0U;
    Can_ReturnType        status;
    uint8 operationMode = 1;
	Can_ControllerStateType Controller_Satus;

    Can_ConfigPtr = &CanConfigSet;
    /* Message for CAN-FD(MCAN module) */
    PduInfo         = &Pdu;
    /* Setting Up CAN FD Frame*/
    Pdu.id          = 0xC1 | 0x40000000U;
    Pdu.length      = 64U;
    Pdu.swPduHandle = 1U;
    Pdu.sdu         = &data[0U];

      /* Do Can Init */
      Can_Init(Can_ConfigPtr);
      
	  AppUtils_printf(APP_NAME ": Select one of the controller\n\r");
      AppUtils_printf(APP_NAME ": d - for using MCAN controller 0 \n\r");
      AppUtils_printf(APP_NAME ": m - for using MCAN controller 1 \n\r");
      AppUtils_printf(APP_NAME ": n - for using MCAN controller 2 \n\r");
      AppUtils_printf(APP_NAME ": s - for using MCAN controller 3 \n\r");
      option = AppUtils_getChar();
      if (option == 'd')
      {
        cntr_cnt = 0;
        AppUtils_printf(APP_NAME ":MCAN Selected - CAN_CONTROLLER_INSTANCE_MCAN1 (cntr_cnt=0) \n\r");
      }
      else if (option == 'm')
      {
        cntr_cnt = 1;
        AppUtils_printf(APP_NAME ":MCAN Selected - CAN_CONTROLLER_INSTANCE_MCAN2 (cntr_cnt=1) \n\r");
      }
      else if (option == 'n')
      {
        cntr_cnt = 2;
        AppUtils_printf(APP_NAME ":MCAN Selected - CAN_CONTROLLER_INSTANCE_MCAN3 (cntr_cnt=2) \n\r");
      }
      else
      {
        AppUtils_printf(APP_NAME ":MCAN Selected - - CAN_CONTROLLER_INSTANCE_MCAN4 (cntr_cnt=3)\n\r");
        cntr_cnt = 3;
      }
        /* Disable interrupts for selected controller */
	  AppUtils_printf(APP_NAME ": Select one of the Mode\n\r");
      AppUtils_printf(APP_NAME ": i - for interrupt mode\n\r");
      AppUtils_printf(APP_NAME ": p - for polling mode\n\r");
      option = AppUtils_getChar();
	  
	  if (option == 'i')
      {

        AppUtils_printf(APP_NAME ":Interrupt mode selected\n\r");
        operationMode = 0;
      }
      else
      {
        AppUtils_printf(APP_NAME ":polling Mode selected\n\r");

        /* Disable interrupts for selected controller */
        Can_DisableControllerInterrupts(cntr_cnt);
        operationMode = 1;
      }
      /* Flush RxData */
      for (loopCnt = 0U; loopCnt < Pdu.length; loopCnt++)
      {
        CanRxData[loopCnt] = 0;
      }
	if (CAN_CONTROLLER_INSTANCE_MCAN1 ==
        Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
      {
        AppUtils_printf(APP_NAME ": Can Controller: MCAN1 (cntr_cnt=0)\n\r");
		Pdu.sdu         = &data[0U];
        PduInfo = &Pdu;   //this CAN controller will be CAN FD
      }
      else if (CAN_CONTROLLER_INSTANCE_MCAN2 ==
        Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
      {
        AppUtils_printf(APP_NAME ": Can Controller:MCAN2 (cntr_cnt=1)  \n\r");
		Pdu.sdu         = &data[7U];
        PduInfo = &Pdu;
      }
      else if (CAN_CONTROLLER_INSTANCE_MCAN3 ==
        Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
      {
        AppUtils_printf(APP_NAME ": Can Controller:MCAN3 (cntr_cnt=2)  \n\r");
		Pdu.sdu         = &data[5U];
        PduInfo = &Pdu;
      }
      else if (CAN_CONTROLLER_INSTANCE_MCAN4 ==
        Can_ConfigPtr->CanControllerList[cntr_cnt]->CanControllerInst)
      {
        AppUtils_printf(APP_NAME ": Can Controller:MCAN4 (cntr_cnt=3)  \n\r");
		Pdu.sdu         = &data[2U];
        PduInfo = &Pdu;
      }
      else
      {
        AppUtils_printf(APP_NAME "please check the configuration\n\r");
      }
      /* Set Controller Mode for selected controller */
      status = Can_SetControllerMode(Can_ConfigPtr->
        CanControllerList[cntr_cnt]->ControllerId, CAN_CS_STARTED);
		Can_GetControllerMode(Can_ConfigPtr->
        CanControllerList[cntr_cnt]->ControllerId, &Controller_Satus);
		AppUtils_printf(APP_NAME ": Status: %d\n",Controller_Satus);
      if (status != CAN_OK)
      {
        gTestPassed = E_NOT_OK;
      }

      while (1) 
      {
        AppUtils_printf(APP_NAME ": Enter one of the following\n\r");
        AppUtils_printf(APP_NAME ": t - to transmit data\n\r");
        AppUtils_printf(APP_NAME ": r - to receive data\n\r");
        AppUtils_printf(APP_NAME ": q - to quit the application\n\r\n\r");
        
        /* Decide whether to wait to receive CAN message or to send the data on CAN bus */
        option = AppUtils_getChar();

        switch (option)
        {
        case 't':
          AppUtils_printf(APP_NAME ": e - for extended format\n\r");
          AppUtils_printf(APP_NAME ": s - for standard format\n\r");
          option = AppUtils_getChar();          
		  
		  if (cntr_cnt == 0)
          {
			  
            if (option == 'e')
            {
              AppUtils_printf("sending message with extended ID\n\r");
              hth = 1U;

            }
            else
            {
              AppUtils_printf("sending message with standard ID\n\r");
              hth = 0U;
            }
          }
		  else if (cntr_cnt == 1)
          {
            if (option == 'e')
            {
              AppUtils_printf("sending message with extended ID\n\r");
              hth = 3U;

            }
            else
            {
              AppUtils_printf("sending message with standard ID\n\r");
              hth = 2U;
            }
          }
		  else if (cntr_cnt == 2)
          {
            if (option == 'e')
            {
              AppUtils_printf("sending message with extended ID\n\r");
              hth = 5U;

            }
            else
            {
              AppUtils_printf("sending message with standard ID\n\r");
              hth = 4U;
            }
          }
		  else 
          {
            if (option == 'e')
            {
              AppUtils_printf("sending message with extended ID\n\r");
              hth = 7U;

            }
            else
            {
              AppUtils_printf("sending message with standard ID\n\r");
              hth = 6U;
            }
          }
          status = Can_Write(hth, PduInfo);
		  
		  
          if (status != CAN_OK)
          {
            AppUtils_printf(APP_NAME ": Error In Can_Write.\n\r");
            gTestPassed = E_NOT_OK;
          }
          else
          {
            if (operationMode == 0)
            {
              while ((0 == CanIf_TxConfirmationCount));
			  
            }
            else
            {
              while (CanIf_TxConfirmationCount == 0)
              {
                /*poll Can_MainFunction_Write for TX confirmation*/
                Can_MainFunction_Write();
                AppUtils_delay(100U);
              }
              AppUtils_printf(APP_NAME ": Data transmitted.\n\r");
              CanIf_TxConfirmationCount = 0;
            }
          }
          break;

        case 'r':
          AppUtils_printf(APP_NAME ": waiting to receive data\n\r");
          if (operationMode == 1)
          {
            while ((0U == msgCounter1))
            {
              Can_MainFunction_Read();
              AppUtils_delay(100U);
            };

            msgCounter1 = 0U;
            for (loopCnt = 0U; loopCnt < dlc; loopCnt++)
            {
              if ((loopCnt % 8) == 7)
              {
                /*Klockworks fix :  ABV.GENERAL*/
                if (loopCnt < 64U)
                  AppUtils_printf("0x%x\n\r", CanRxData[loopCnt]);
              }
              else
              {
                /*Klockworks fix :  ABV.GENERAL*/
                if (loopCnt < 64U)
                  AppUtils_printf("0x%x\t", CanRxData[loopCnt]);
              }

            }
          }
          else
          {
            while ((0U == msgCounter1))
            {
              AppUtils_delay(100U);
            };
            msgCounter1 = 0U;
            AppUtils_printf(APP_NAME ": Received Data \n\r");
            for (loopCnt = 0U; loopCnt < dlc; loopCnt++)
            {
              if ((loopCnt % 8) == 7)
              {
                AppUtils_printf("0x%x\n\r", CanRxData[loopCnt]);
              }
              else
              {
                AppUtils_printf("0x%x\t", CanRxData[loopCnt]);
              }

            }
          }


          break;

        case 'q':
          quit_opt = 1;
          break;

        default:
          AppUtils_printf(APP_NAME ": Invalid Input\n\r");
          continue;
        }


        if (E_OK != gTestPassed)
        {
          AppUtils_printf(APP_NAME ": Exiting the application\n\r");
          break;
        }

        if (0U != eccErrCnt)
        {
          eccErrCnt = 0U;
          gTestPassed = E_NOT_OK;
          if ((uint32)CAN_ECC_ERROR_TYPE_PARITY == eccErrType)
          {
            AppUtils_printf(APP_NAME ": Parity Error Detected.\n\r");
          }
          else if ((uint32)CAN_ECC_ERROR_TYPE_SEC == eccErrType)
          {
            AppUtils_printf(APP_NAME ": SEC Error Detected.\n\r");
          }
          else if ((uint32)CAN_ECC_ERROR_TYPE_DED == eccErrType)
          {
            AppUtils_printf(APP_NAME ": DED Error Detected.\n\r");
          }
          else
          {
          }
          break;
        }

        if (quit_opt == 1)
        {
          break;
        }

      }//end of while (1) 

      if (gTestPassed == E_OK)
      {
        AppUtils_printf(APP_NAME ": Test Passed\n\r");
      }

    }

#endif
typedef void (*CanExampleFxn_t)(void);

CanExampleFxn_t CanExampleFxnTbl[] =
{
#if (STD_ON == APP_LOOPBACK_MODE)
    CanExample_LoopbackTest,
#else
    CanExample_ExternalTest
#endif
};

int32_t main(void)
{
    uint8_least i;

    gTestPassed = E_OK;

    AppUtils_defaultInit();
#if defined (CAN_CONTROLLER_MCAN1) || defined (CAN_CONTROLLER_MCAN2)
#if (STD_ON == CAN_ECC_ENABLE)
    /* ESM module needs to be enabled to generate interrupt for ECC errors */
    esmInit();
#endif
#endif
    CanExample_PlatformInit();
    CanExample_InterruptConfig();
    AppUtils_printf(APP_NAME ": Sample Application - STARTS !!!\n\r");
    AppUtils_printf(APP_NAME "gCanAppMcuClockConfig[0].Mcu_ClockSourceId = %d gCanAppMcuClockConfig[0].Mcu_ClockDiv = %d  \n\r",
    gCanAppMcuClockConfig[0].Mcu_ClockSourceId, gCanAppMcuClockConfig[0].Mcu_ClockDiv);

    for (i = 0U; i < CANEXAMPLE_ARRAYSIZE(CanExampleFxnTbl); i++)
    {
        CanExampleFxnTbl[i]();
    }

    GT_1trace(McalAppTrace, GT_INFO,
              " CAN Stack Usage: %d bytes\n\r", AppUtils_getStackUsage());
    /* if (AppUtils_checkStackAndSectionCorruption() != E_OK)
    {
        gTestPassed = E_NOT_OK;
        GT_0trace(McalAppTrace, GT_ERR, " CAN Stack/section corruption!!!\n\r");
    } */

    if (E_OK == gTestPassed)
    {
        GT_0trace(McalAppTrace, GT_INFO, " CAN Test Passed!!!\n\r");
    }
    else
    {
        GT_0trace(McalAppTrace, GT_ERR, " CAN Test Failed!!!\n\r");
    }
    return (gTestPassed);
}

void CanIf_ControllerBusOff(uint8 Controller)
{
    MainFunc_Execution = 3U;
}


void CanIf_RxIndication(const Can_HwType* Mailbox,
    const PduInfoType* PduInfoPtr)
{
    volatile uint8 Hrh1;
    uint8          i;
    Hrh1 = Mailbox->Hoh;
    msgCounter1++;
    MainFunc_Execution = 5U;

    if (PduInfoPtr->SduLength > 64U)
    {
        return;
    }
    /* Copy data */
    CanIdVal = Mailbox->CanId;
    dlc = PduInfoPtr->SduLength;
    for (i = 0U; i < PduInfoPtr->SduLength; i++)
    {
        CanRxData[i] = PduInfoPtr->SduDataPtr[i];
    }
}

void CanIf_TxConfirmation(PduIdType CanTxPduId)
{
    CanIf_TxConfirmationCount++;
    MainFunc_Execution = 4U;
}

void CanIf_ControllerModeIndication(uint8                    ControllerId,
                                    CanIf_ControllerModeType ControllerMode)
{
    static volatile uint8 controller;

    volatile CanIf_ControllerModeType ControllerMode1;
    controller         = ControllerId;
    ControllerMode1    = ControllerMode;
    MainFunc_Execution = 2U;
}

void CanApp_ErrorNotification(uint32 errStatus)
{
    MainFunc_Execution = 6U;
    eccErrCnt++;
    eccErrType = errStatus;
}

void EcuM_CheckWakeup(EcuM_WakeupSourceType wakeupSource)
{
    MainFunc_Execution = 1U;
}

uint8 Intc_status;

#ifdef __cplusplus
extern "C" {
#endif

void SchM_Enter_Port(sint32 cookie);
void SchM_Exit_Port(sint32 cookie);

#if defined CLANG
void  SchM_Enter_Mcu_MCU_EXCLUSIVE_AREA_0()
{
    AppUtils_SchM_Enter_EXCLUSIVE_AREA_0();
}

void   SchM_Exit_Mcu_MCU_EXCLUSIVE_AREA_0()
{
     AppUtils_SchM_Exit_EXCLUSIVE_AREA_0();
}
#endif

void  SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0()
{
    AppUtils_SchM_Enter_EXCLUSIVE_AREA_0();
}

void   SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0()
{
    AppUtils_SchM_Exit_EXCLUSIVE_AREA_0();
}

void  SchM_Enter_Port_PORT_EXCLUSIVE_AREA_0()
{
    AppUtils_SchM_Enter_EXCLUSIVE_AREA_0();

}

void   SchM_Exit_Port_PORT_EXCLUSIVE_AREA_0()
{

  AppUtils_SchM_Exit_EXCLUSIVE_AREA_0();

}

void Dem_ReportErrorStatus(Dem_EventIdType     eventId,
                           Dem_EventStatusType eventStatus)
{
    if (DEM_EVENT_STATUS_FAILED == eventStatus)
    {
        gTestPassed = E_NOT_OK;
        GT_assert(McalAppTrace, FALSE);
    }

    return;
}

Std_ReturnType Det_ReportError(uint16 ModuleId,
                               uint8  InstanceId,
                               uint8  ApiId,
                               uint8  ErrorId)
{
    AppUtils_printf(APP_NAME "Module ID: %d \t Instance ID: %d\t ApiID: %d\t ErrorID: %d \n",ModuleId,InstanceId,ApiId,ErrorId);
    return (E_OK);
	
}

#ifdef __cplusplus
}
#endif
