/* ======================================================================
*   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.
* ==================================================================== */
    
/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */
#include "string.h"
#include "Can_Priv.h"
#include "EcuM_Cbk.h"
#include "Can_Cfg.h"

#include "soc.h"
#include "mcan.h"
#define CAN_START_SEC_CODE
#include "Can_MemMap.h"
#include "hw_types.h"
#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"
#include "hw_mcanss.h"

/*******************************************************************************
 *  LOCAL DATA DEFINITIONS
 ******************************************************************************/

/* ========================================================================== */
/*                           Macros & Typedefs                                */
/* ========================================================================== */

/**
 *  \name Default Configuration params values
 *
 *  Defines for MCAN Controller default Configuration params
 *  @{
 */
/** \brief  Transmit pause enable */
#define MCAN_TRANSMIT_PAUSE_ENABLE          (MCAN_CCCR_TXP_DISABLE)
/** \brief  Edge Filtering during Bus Integration */
#define MCAN_EFBI                           (MCAN_CCCR_EFBI_DISABLE)
/** \brief  Protocol Exception Handling Enable */
#define MCAN_PROT_EXP_HANDLING_ENABLE       (MCAN_CCCR_PXHD_DISABLE)
/** \brief  Emulation Enable */
#define MCAN_EMU_ENABLE                     (MCAN_MCANSS_CTRL_EMUEN_DISABLE)
/** \brief  Emulation Fast Ack */
#define MCAN_EMU_FAST_ACK                   (MCAN_MCANSS_CTRL_EMUFACK_DISABLE)
/** \brief  Clock Stop Fast Ack */
#define MCAN_CLK_STOP_FAST_ACK              (MCAN_MCANSS_CTRL_CLKFACK_DISABLE)
/** \brief  Start value of the Message RAM Watchdog Counter */
#define MCAN_WDC_PRELOAD                    (MCAN_RWD_WDC_DISABLE)
/** \brief  Transmitter Delay Compensation Filter Window Length */
#define MCAN_TRCV_DELAY_COMP_WIN            (0U)
/** \brief  MCAN Extension ID mask*/
#define APP_MCAN_EXT_ID_AND_MASK                 (0x1FFFFFFFU)

/**
 *  \name Elements Size
 *
 *  Defines for MCAN Message RAM Elements Size in Words
 *  @{
 */
/** \brief  Standard ID Filter Element Size */
#define MCAN_MSG_RAM_STD_ELEM_SIZE          (1U)
/** \brief  Extended ID Filter Element Size */
#define MCAN_MSG_RAM_EXT_ELEM_SIZE          (2U)
/** \brief  Tx/Rx Mailbox Size */
#define MCAN_MSG_RAM_TX_RX_ELEM_SIZE        (18U)

#define XTD_MSGID_MASK          ((uint32)0x1fffffffU)
#define STD_MSGID_MASK          ((uint32)0x7ffU)
#define STD_MSGID_SHIFT         (18U)
#define CAN_ID_STD              (0x0U)
#define CAN_ID_XTD              (0x1U)
#define CAN_ID_MIXED            (0x2U)

#define CAN_MSG_ID_TYPE_STD     ((uint32)0x0U)
#define CAN_MSG_ID_TYPE_EXT     ((uint32)0x80000000U)
#define CAN_MSG_TYPE_MASK       ((uint32)0x40000000U)
#define CAN_MSG_TYPE_CLASSIC_CAN         ((uint32)0x0U)
#define CAN_MSG_TYPE_CAN_FD              ((uint32)0x40000000U)


/**
 *  \name Default Interrupt Enable Mask
 *
 *  Defines for MCAN Controller default Interrupt Mask
 *  NOTE: User can change this mask
 *  @{
 */

#define MCAN_INTR_MASK       ((uint32)MCAN_INTR_SRC_RX_FIFO1_NEW_MSG | \
                              (uint32) MCAN_INTR_SRC_TRANS_CANCEL_FINISH|  \
                              (uint32)MCAN_INTR_SRC_TIMEOUT | \
                              (uint32) MCAN_INTR_SRC_BUS_OFF_STATUS |\
                              (uint32)MCAN_INTR_SRC_PROTOCOL_ERR_ARB | \
                              (uint32)MCAN_INTR_SRC_PROTOCOL_ERR_DATA | \
                              (uint32)MCAN_INTR_SRC_RX_FIFO0_NEW_MSG | \
                              (uint32)MCAN_INTR_SRC_RX_FIFO0_MSG_LOST |  \
                              (uint32)MCAN_INTR_SRC_TRANS_COMPLETE |  \
                              (uint32)MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG |  \
                              (uint32)MCAN_INTR_SRC_BUS_OFF_STATUS)


/* ========================================================================== */
/*                         Structures and Enums                               */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                 Internal Function Declarations                             */
/* ========================================================================== */

void Can_mcanInit(MCAN_InitParams *initParams,
                  const Can_ControllerType *canControllerCfg);

void Can_mcanConfig(const Can_ControllerObjType *controllerObj,
                    const Can_ControllerType *canControllerCfg,
                    uint32 baseAddr);

void Can_mcanSetUpController(uint32 baseAddr);

void Can_mcanMsgRAMConfigInit(Can_FdMsgRAMConfigObjType *canFDMsgRamConfig);

void Can_mcanSetUpMSGRAM(Can_ControllerObjType *canController,
                         const Can_MailboxObjType *canMailbox,
                         uint32 maxMbCnt);

void Can_mcanSetUpTxMailbox(Can_FdMsgRAMConfigObjType *msgRamConfig,
                            const Can_MailboxType *mailboxCfg,
                            Can_ControllerType *canControllerCfg,
                            uint32 htrh,
                            uint32 baseAddr);

void Can_mcanSetUpRxMailbox(Can_FdMsgRAMConfigObjType *msgRamConfig,
                            const Can_MailboxType *mailboxCfg,
                            uint32 htrh);

void Can_mcanMsgRAMConfig(uint32 baseAddr,
                          Can_FdMsgRAMConfigObjType *canFDMsgRamConfig);


void Can_mcanInitInterrupt(uint32 baseAddr,uint32 InterruptMask);

static void Can_mcanCancelPendMsg(uint32 baseAddr);
static void Can_mcanConfigBaudRate(const Can_ControllerObjType *controllerObj,
                                   const Can_ControllerType *controllerCfg,
                                   uint32 baseAddr);

static void Can_mcanSetId(const Can_PduType *PduInfo,
                          const Can_MailboxType *mailboxCfg,
                          MCAN_TxBufElement *elem);

static inline uint32 Can_mcanGetID(const uint32 idType,
                                   const uint32 CanId);
static void Can_mcanRamInitDone(uint32 baseAddr);
/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */
#define CAN_START_SEC_VAR_INIT_8
#include "Can_MemMap.h"

static const uint8 gMcanDataSize[16] = {0U,  1U,  2U,  3U,
                                        4U, 5U,  6U, 7U,
                                        8U, 12U, 16U, 20U,
                                        24U, 32U, 48U, 64U};

#define CAN_STOP_SEC_VAR_INIT_8
#include "Can_MemMap.h"
extern VAR(Can_MbHTRHMapping_Type, CAN_VAR_NOINIT)
                    CanHtrhMbMapping[KMAX_MB_PER_CONTROLLER * KMAX_CONTROLLER];

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */

#define CAN_START_SEC_CODE
#include "Can_MemMap.h"

/*******************************************************************************
 * Can_mcanRamInitDone
 ******************************************************************************/
/*! \brief      Checks the initialization of Message RAM done or not.
 *
 *  \param[in]  uint32 baseAddr -  Base Address of controller
 *
 ******************************************************************************/
static void Can_mcanRamInitDone(uint32 baseAddr)
{
    
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
                /* timeout */
              (void)Dem_SetEventStatus(
                    CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while (MCAN_isMemInitDone(baseAddr) != (uint32) TRUE);
    }
}

void Can_mcanConfigController(Can_ControllerObjType *canController,
                              const Can_MailboxObjType *canMailbox,
                              uint32 maxMbCnt)
{
    uint32 baseAddr;
    const Can_ControllerType *canControllerCfg;
    MCAN_InitParams initParams;

    canControllerCfg = &canController->canControllerConfig;
    baseAddr =  canControllerCfg->CntrAddr;

    /* Checks the initialization of Message RAM */
    Can_mcanRamInitDone(baseAddr);

    Can_mcanSetUpController(baseAddr);
    /* Initialize Init params */
    Can_mcanInit(&initParams, canControllerCfg);

    /* Configure MCAN */
    Can_mcanConfig(canController, canControllerCfg, baseAddr);

    /* Perform the initialization of Message RAM and the mailboxes */
    Can_mcanSetUpMSGRAM(canController, canMailbox, maxMbCnt);

#if (STD_ON == CAN_ECC_ENABLE)
    /* Enable ECC Interrupt */
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_SEC, (uint32)TRUE);
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_DED, (uint32)TRUE);
#endif

    /* Interrupt is enabled only if either RX or TX is in Interrupt mode */
    if ((canControllerCfg->RxInterrupt == (boolean) TRUE) ||
        (canControllerCfg->TxInterrupt == (boolean) TRUE))
    {
        Can_mcanInitInterrupt(baseAddr, canControllerCfg->InterruptMask);
    }
}

boolean Can_mcanStart(Can_ControllerObjType *controllerObj)
{
    
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;
    boolean status = (boolean) FALSE;
    MCAN_ProtocolStatus errStatus;
    uint32  baseAddr;

    baseAddr = controllerObj->canControllerConfig.CntrAddr;
    /* Put MCAN in operational mode */
    MCAN_setOpMode(baseAddr, (uint32_t)MCAN_OPERATION_MODE_NORMAL);
    (void) GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
                /* timeout */
              (void)Dem_SetEventStatus(
                    CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while (((uint32_t)(MCAN_OPERATION_MODE_NORMAL)) != 
                                                      MCAN_getOpMode(baseAddr));
    }

    controllerObj->canState = CAN_CS_STARTED;
    CanIf_ControllerModeIndication(
                            controllerObj->canControllerConfig.ControllerId,
                            CANIF_CS_STARTED);
    status = (boolean) TRUE;
    /* Check if there is a busoff */
    MCAN_getProtocolStatus(baseAddr, &errStatus);
    if ((uint32_t)MCAN_PSR_BO_BUS_OFF == errStatus.busOffStatus)
    {
        /* BusOff Recovery sequence has started */
        controllerObj->canBusOffRecoveryStatus = (boolean) TRUE;
    }

    return status;
}

static void Can_mcanCancelPendMsg(uint32 baseAddr)
{
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;
    
    uint32      txBufPendStatus, bitIndex;

    /* Cancel all pending messages */
    txBufPendStatus = MCAN_getTxBufReqPend(baseAddr);
    for (bitIndex = 0U; bitIndex < 32U; bitIndex++)
    {
        /* For each bit set call cancel request */
        uint32 bitPos = (uint32)1U << bitIndex;
        if (bitPos == (txBufPendStatus & bitPos))
        {
            /* Clear pending Tx request */
            (void) MCAN_txBufCancellationReq(baseAddr, bitIndex);
            (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
            
            {
                /* Below API can change start time, so use temp variable */
                tempCount = startCount;
                /* Wait for FSM to to come out of reset */
                do
                {
                    (void)GetElapsedValue(
                                 CAN_CFG_OS_COUNTER_ID,
                                 &tempCount,
                                 &elaspsedCount);
                    if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
                    {
                        /* timeout */
                      (void)Dem_SetEventStatus(
                            CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
                        break;
                    }
                }while ((MCAN_txBufCancellationStatus(baseAddr) & bitPos) !=
                        bitPos);
            }
        }
    }
}

boolean Can_mcanStop(Can_ControllerObjType * controllerObj)
{
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;
    
    boolean status = (boolean) FALSE;
    uint32 baseAddr;

    baseAddr = controllerObj->canControllerConfig.CntrAddr;
    /* Put MCAN in SW initialization mode */
    MCAN_setOpMode(baseAddr, (uint32_t)MCAN_OPERATION_MODE_SW_INIT);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
                /* timeout */
              (void)Dem_SetEventStatus(
                    CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while ( ( (uint32_t)MCAN_OPERATION_MODE_SW_INIT ) != 
                                                      MCAN_getOpMode(baseAddr));
    }

    /* cancel pending messages */
    Can_mcanCancelPendMsg(baseAddr);

    controllerObj->canState = CAN_CS_STOPPED;
    CanIf_ControllerModeIndication(
                            controllerObj->canControllerConfig.ControllerId,
                            CANIF_CS_STOPPED);
    status = (boolean) TRUE;
    controllerObj->canBusOffRecoveryStatus = (boolean) FALSE;

    return status;
}

boolean Can_mcanSleep(Can_ControllerObjType * controllerObj)
{
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;
    boolean     timeOut = (boolean)FALSE;    
    boolean status = (boolean) FALSE;
    uint32 baseAddr;

    baseAddr = controllerObj->canControllerConfig.CntrAddr;
    /* Local Power down */
    MCAN_addClockStopRequest(baseAddr, (uint32)TRUE);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
                /* timeout */
                timeOut = (boolean)TRUE;
                break;
            }
        } while ((uint32)MCAN_CCCR_CSA_ACK != MCAN_getClkStopAck(baseAddr));
    }
    if (timeOut == (boolean)TRUE)
    {
      (void)Dem_SetEventStatus(
            CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
    }
    controllerObj->canState = CAN_CS_SLEEP;
    CanIf_ControllerModeIndication(
                            controllerObj->canControllerConfig.ControllerId,
                            CANIF_CS_SLEEP);
    status = (boolean) TRUE;
    controllerObj->canBusOffRecoveryStatus =
        (boolean) FALSE;

    return status;
}


Std_ReturnType Can_mcanTestLoopBackModeEnable(uint32 baseAddr, uint8 mode)
{
    
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;    

    /* Put MCAN in SW initialization mode */
    MCAN_setOpMode(baseAddr,(uint32_t)MCAN_OPERATION_MODE_SW_INIT);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
              (void)Dem_SetEventStatus(CAN_E_HARDWARE_ERROR,
                                      DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while ( ( (uint32_t) MCAN_OPERATION_MODE_SW_INIT) != 
                                                      MCAN_getOpMode(baseAddr));
    }
    if (0U == mode)
    {
        /* Enable Digital Loopback */
        MCAN_lpbkModeEnable(baseAddr, (uint32_t)MCAN_LPBK_MODE_INTERNAL, 
                                                                (uint32_t)TRUE);    
    }
    else
    {
        /* Enable Analog Loopback */
        MCAN_lpbkModeEnable(baseAddr, (uint32_t)MCAN_LPBK_MODE_EXTERNAL, 
                                                                (uint32_t)TRUE);    
    }
    /* Put MCAN in normal mode of operation */
    MCAN_setOpMode(baseAddr, (uint32_t)MCAN_OPERATION_MODE_NORMAL);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
              (void)Dem_SetEventStatus(CAN_E_HARDWARE_ERROR,
                                      DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while (((uint32_t)MCAN_OPERATION_MODE_NORMAL) != 
                                                      MCAN_getOpMode(baseAddr));
    }
    return (Std_ReturnType)(E_OK);

}

Std_ReturnType Can_mcanTestLoopBackModeDisable(uint32 baseAddr, uint8 mode)
{
    
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;

    
    /* Put MCAN in SW initialization mode */
    MCAN_setOpMode(baseAddr, (uint32_t)MCAN_OPERATION_MODE_SW_INIT);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION )
            {
              (void)Dem_SetEventStatus(CAN_E_HARDWARE_ERROR,
                                      DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while ((uint32_t)MCAN_OPERATION_MODE_SW_INIT != 
                                                      MCAN_getOpMode(baseAddr));
    }
    if (0U == mode)
    {
        /* Enable Digital Loopback */
        MCAN_lpbkModeEnable(baseAddr, (uint32)MCAN_LPBK_MODE_INTERNAL, 
                                                                 (uint32)FALSE);
    }
    else
    {
        /* Enable Analog Loopback */
        MCAN_lpbkModeEnable(baseAddr, (uint32)MCAN_LPBK_MODE_EXTERNAL, 
                                                                 (uint32)FALSE); 
    }
    /* Put MCAN in normal mode of operation */
    MCAN_setOpMode(baseAddr, (uint32_t)MCAN_OPERATION_MODE_NORMAL);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
              (void)Dem_SetEventStatus(CAN_E_HARDWARE_ERROR,
                                      DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while (((uint32_t)(MCAN_OPERATION_MODE_NORMAL)) != 
                                                      MCAN_getOpMode(baseAddr));
    }
  return (Std_ReturnType)(E_OK);
}

Can_ReturnType Can_mcanWriteGetFreeMsgObj(const Can_MailboxType *mailboxCfg,
                                     const Can_ControllerObjType *canController,
                                     uint32 *msgObj,
                                     uint32 htrh)
{
    Can_ReturnType status = CAN_OK;
    uint32         messageBox, baseAddr, loopCnt;
    uint32         bitIndex;
    const Can_FdMsgRAMConfigObjType *canFDMsgRamConfig;
    uint8          canTxStatus;
    const Can_ControllerObjType *controllerObj;

    controllerObj = canController;
    canFDMsgRamConfig = &controllerObj->canFDMsgRamConfig;
    baseAddr = mailboxCfg->Controller->CntrAddr;
    if (mailboxCfg->CanHwObjectCount > 1U)
    {
        loopCnt = (uint32)(canFDMsgRamConfig->txBuffNum);
        for (;
            loopCnt < ((uint32)canFDMsgRamConfig->txFIFONum +
                       (uint32)canFDMsgRamConfig->txBuffNum)
            ; loopCnt++)
        {
            canTxStatus = canController->canTxStatus[loopCnt];
            bitIndex = (uint32)((uint32)1U << loopCnt);
            if (bitIndex == (MCAN_getTxBufReqPend(baseAddr) & bitIndex))
            {
                status = CAN_BUSY;
            }
            else if ((canTxStatus == 1U) &&
            (canController->canControllerConfig.DisableAutoRetransmission ==
             (boolean)FALSE))
            {
                status = CAN_BUSY;
            }
            else
            {
                *msgObj = loopCnt;
                status = CAN_OK;
                break;
            }
        }
    }
    else
    {
        for (messageBox = 0U ;
            messageBox < (uint32)(canFDMsgRamConfig->txBuffNum) ;
            messageBox++)
        {
            if (htrh == canFDMsgRamConfig->txMbMapping[0U][messageBox])
            {
                break;
            }
        }
        if (messageBox < (uint32)canFDMsgRamConfig->txBuffNum)
        {
            canTxStatus = canController->canTxStatus[messageBox];
            bitIndex = ((uint32)1U << messageBox);
            /*- Check for pending message:
             *     - pending message, return CAN_BUSY
             *     - no pending message, start new transmission
             */
            if (bitIndex == (MCAN_getTxBufReqPend(baseAddr) & bitIndex))
            {
                status = CAN_BUSY;
            }
            else if ((canTxStatus == 1U) &&
            (canController->canControllerConfig.DisableAutoRetransmission ==
             (boolean)FALSE))
            {
                status = CAN_BUSY;
            }
            else
            {
                *msgObj = messageBox;
                status = CAN_OK;
            }
        }
        else
        {
            status = CAN_OK;
        }
    }

    return status;
}

void Can_mcanWriteTxMailbox(const Can_MailboxType *mailboxCfg,
                            Can_ControllerObjType *controllerObj,
                            uint32   messageBox,
                            const Can_PduType *pduInfo,
                            uint32   hth)
{
    uint32         loopCnt, idx = 0U, baseAddr;
    uint32         memType;
    uint8         *deref_data = NULL;
    MCAN_TxBufElement elem;

    baseAddr = mailboxCfg->Controller->CntrAddr;
    /* Frame Tx message element */
    elem.rtr = 0U;
    elem.esi = 0U;
    if (CAN_MSG_TYPE_CLASSIC_CAN == (pduInfo->id & CAN_MSG_TYPE_MASK))
    {
        elem.brs = 0U;
        elem.fdf = 0U;
    }
    else
    {
        elem.brs = 1U;
        elem.fdf = 1U;
    }
    elem.efc = 0U;
    elem.mm = 0U;
    Can_mcanSetId(pduInfo, mailboxCfg, &elem);

    /* Copy payload into message element */
    deref_data = pduInfo->sdu;
    if (deref_data != NULL)
    {
        for (loopCnt = 0U ; loopCnt < pduInfo->length ; loopCnt++)
        {
            elem.data[loopCnt] = deref_data[loopCnt];
        }
        for (loopCnt = 0U ; loopCnt < 16U ; loopCnt++)
        {
            if (pduInfo->length <= gMcanDataSize[loopCnt])
            {
                idx = loopCnt;
                break;
            }
        }
        elem.data_length = idx;
        /* Add padding value to unused to data in payload */
        loopCnt = (uint32)pduInfo->length;
        for (; loopCnt < gMcanDataSize[idx] ; loopCnt++)
        {
            elem.data[loopCnt] = mailboxCfg->CanFdPaddingValue;
        }
    }
    if (mailboxCfg->CanHwObjectCount > 1U)
    {
        memType = (uint32)MCAN_MEM_TYPE_FIFO;
    }
    else
    {
        memType = (uint32)MCAN_MEM_TYPE_BUF;
    }
    controllerObj->canFDMsgRamConfig.hthToMbMapping[messageBox] = hth;
    MCAN_writeMsgRam(baseAddr, memType, messageBox, &elem);
    (void) MCAN_txBufAddReq(baseAddr, messageBox);
}


/*******************************************************************************
 * Can_mcanGetProtocolStatus
 ******************************************************************************/
 /*! \brief      This function will check the Protocol Status register to get 
                 the error status.
  *
  *  \param[in]  Can_ControllerObjType controller -  The controller for which 
  *              the error status is checked.  
  *
  *  \param[out] Returns the Can_ErrorStateType errorState 
  *  \context
  *****************************************************************************/
Can_ErrorStateType Can_mcanGetProtocolStatus(
  const Can_ControllerObjType *canController)
{
  uint32 baseAddr;
  MCAN_ProtocolStatus   errStatus;
  Can_ErrorStateType    errorState;
  baseAddr = canController->canControllerConfig.CntrAddr;
  /* Check Protocol Staus Register */
  MCAN_getProtocolStatus(baseAddr, &errStatus);
  if (1U == errStatus.busOffStatus)
  {
    errorState = CAN_ERRORSTATE_BUSOFF;
  }
  else if (1U == errStatus.errPassive)
  {
    errorState = CAN_ERRORSTATE_PASSIVE;
  }
  else
  {
    errorState = CAN_ERRORSTATE_ACTIVE;
  }

  return errorState;
}

/* ========================================================================== */
/*                 Internal Functions                                         */
/* ========================================================================== */

void Can_mcanInit(MCAN_InitParams *initParams,
                  const Can_ControllerType *canControllerCfg)
{
    uint32 timeQuanta, baseAddr;

    baseAddr =  canControllerCfg->CntrAddr;
    /* Initialize MCAN Init params */
    initParams->fdMode          = (uint32)MCAN_CCCR_FDOE_ENABLE;
    if ((boolean)TRUE == 
                      canControllerCfg->DefaultBaud->BaudFdRateConfig.BrsSwitch)
    {
        initParams->brsEnable       = (uint32)MCAN_CCCR_BRSE_ENABLE;
    }
    else
    {
        initParams->brsEnable       = (uint32)MCAN_CCCR_BRSE_DISABLE;
    }
    if ((boolean)TRUE == canControllerCfg->DisableAutoRetransmission)
    {
        initParams->darEnable       = (uint32)MCAN_CCCR_DAR_ENABLE;
    }
    else
    {
        initParams->darEnable       = (uint32)MCAN_CCCR_DAR_DISABLE;
    }
    if ((boolean)TRUE == canControllerCfg->CanBusWakeupSupport)
    {
        initParams->wkupReqEnable   =
                                (uint32)MCAN_MCANSS_CTRL_WAKEUPREQEN_ENABLE;
        initParams->autoWkupEnable  =
                                (uint32)MCAN_MCANSS_CTRL_AUTOWAKEUP_ENABLE;
    }
    else
    {
        initParams->wkupReqEnable   =
                                (uint32)MCAN_MCANSS_CTRL_WAKEUPREQEN_DISABLE;
        initParams->autoWkupEnable  =
                                (uint32)MCAN_MCANSS_CTRL_AUTOWAKEUP_DISABLE;
    }
    if (0U != canControllerCfg->DefaultBaud->BaudFdRateConfig.TrcvCompDelay)
    {
        timeQuanta = (uint32)canControllerCfg->DefaultBaud->BaudFdRateConfig.
                                                                  TrcvCompDelay;
        if(canControllerCfg->CanControllerType == CAN_CONTROLLER_INSTANCE_MCAN1)
        {
            timeQuanta = ((uint32)CLK_CAN_FD1_FREQ * timeQuanta) / 1000U;
        }
        else if(canControllerCfg->CanControllerType == 
												CAN_CONTROLLER_INSTANCE_MCAN2)
        {
            timeQuanta = ((uint32)CLK_CAN_FD2_FREQ * timeQuanta) / 1000U;
        }
        else if(canControllerCfg->CanControllerType == 
                                                CAN_CONTROLLER_INSTANCE_MCAN3)
        {
            timeQuanta = ((uint32)CLK_CAN_FD3_FREQ * timeQuanta) / 1000U;
        }
        else
        {
            timeQuanta = ((uint32)CLK_CAN_FD4_FREQ * timeQuanta) / 1000U;
        }
        initParams->tdcEnable       = (uint32)MCAN_DBTP_TDC_ENABLE;
        initParams->tdcConfig.tdco  = timeQuanta;
        initParams->tdcConfig.tdcf  = (uint32)MCAN_TRCV_DELAY_COMP_WIN;
    }
    else
    {
        initParams->tdcEnable       = (uint32)MCAN_DBTP_TDC_DISABLE;
        initParams->tdcConfig.tdco  = (uint32)canControllerCfg->
                                    DefaultBaud->BaudFdRateConfig.TrcvCompDelay;
        initParams->tdcConfig.tdcf  = (uint32)MCAN_TRCV_DELAY_COMP_WIN;
    }
    initParams->txpEnable       = (uint32)MCAN_TRANSMIT_PAUSE_ENABLE;
    initParams->efbi            = (uint32)MCAN_EFBI;
    initParams->pxhddisable = (uint32)0U;
    initParams->emulationEnable = (uint32)MCAN_EMU_ENABLE;
    initParams->emulationFAck   = (uint32)MCAN_EMU_FAST_ACK;
    initParams->clkStopFAck     = (uint32)MCAN_CLK_STOP_FAST_ACK;
    initParams->wdcPreload      = (uint32)MCAN_WDC_PRELOAD;
    (void) MCAN_init(baseAddr, initParams);
}

void Can_mcanConfig(const Can_ControllerObjType *controllerObj,
                    const Can_ControllerType *canControllerCfg,
                    uint32 baseAddr)
{
    MCAN_ConfigParams mConfParams;
    MCAN_ECCConfigParams eccConfigParams;
    MCAN_RxNewDataStatus newDataStatus;

    /* Initialize Configuration parameters */
    mConfParams.monEnable                      = 0U;
    mConfParams.asmEnable                      = 0U;
    mConfParams.tsPrescalar                    = 0U;
    mConfParams.tsSelect                       = 0U;
    mConfParams.timeoutSelect                  = 0U;
    mConfParams.timeoutPreload                 = 0U;
    mConfParams.timeoutCntEnable               = 0U;
    mConfParams.filterConfig.rrfe              = 0x1U;
    mConfParams.filterConfig.rrfs              = 0x1U;
    mConfParams.filterConfig.anfe              = 0x3U;
    mConfParams.filterConfig.anfs              = 0x3U;
    (void) MCAN_config(baseAddr, &mConfParams);
    /* Configure ECC */
#if (STD_ON == CAN_ECC_ENABLE)
    eccConfigParams.enable         =
                            (uint32)MCAN_ECC_AGGR_CONTROL_ECC_ENABLE_ENABLE;
    eccConfigParams.enableChk      =
                            (uint32)MCAN_ECC_AGGR_CONTROL_ECC_CHECK_ENABLE;
    eccConfigParams.enableRdModWr  =
                            (uint32)MCAN_ECC_AGGR_CONTROL_ENABLE_RMW_ENABLE;
    MCAN_eccConfig(baseAddr, &eccConfigParams);
#else
    eccConfigParams.enable         =
                            (uint32)MCAN_ECC_AGGR_CONTROL_ECC_ENABLE_DISABLE;
    eccConfigParams.enableChk      =
                            (uint32)MCAN_ECC_AGGR_CONTROL_ECC_CHECK_DISABLE;
    eccConfigParams.enableRdModWr  =
                            (uint32)MCAN_ECC_AGGR_CONTROL_ENABLE_RMW_DISABLE;
    MCAN_eccConfig(baseAddr, &eccConfigParams);
#endif
    /* Clear all pending error flags and status */
    MCAN_clearIntrStatus(baseAddr, MCAN_INTR_MASK);
    newDataStatus.statusLow  = MCAN_NDAT1_CLEAR;
    newDataStatus.statusHigh = MCAN_NDAT2_CLEAR;
    MCAN_clearNewDataStatus(baseAddr, &newDataStatus);
    /* Configure Baud rate */
    Can_mcanConfigBaudRate(controllerObj, canControllerCfg, baseAddr);
    
    /* Set Extended ID Mask */
    (void)MCAN_setExtIDAndMask(baseAddr, APP_MCAN_EXT_ID_AND_MASK);

}

void Can_mcanInitInterrupt(uint32 baseAddr,uint32 InterruptMask)
{
    if ((uint32)MCAN_INTR_LINE_NUM_0 ==
                            (InterruptMask & (uint32)MCAN_INTR_LINE_NUM_0))
    {

        MCAN_enableIntr(baseAddr, MCAN_INTR_MASK, (uint32)TRUE);
        MCAN_selectIntrLine(baseAddr,
                            MCAN_INTR_MASK,
                            (uint32)MCAN_INTR_LINE_NUM_0);
        MCAN_enableIntrLine(baseAddr,
                            (uint32)MCAN_INTR_LINE_NUM_0,
                            (uint32)TRUE);
    }
}


/*******************************************************************************
 * Can_mcanConfigBaudRate
 ******************************************************************************/
/*! \brief      This function will configure the baud rate.
 *
 *  \param[in]  uint8 controller -  The controller for which the state change
 *              needs to be performed/
 *              uint32 baseAddr- MCAN base address.
 *
 *
 *  \context
 ******************************************************************************/
static void Can_mcanConfigBaudRate(const Can_ControllerObjType *controllerObj,
                                   const Can_ControllerType *controllerCfg,
                                   uint32 baseAddr)
{
    MCAN_BitTimingParams configParams;
    uint8 tmpVal;
    sint32 status;

    if (controllerObj->canBaud != 0x000U)
    {
        configParams.nomRatePrescalar = ((uint32)controllerObj->canBaud);
    }
    else
    {
        configParams.nomRatePrescalar =
                                (uint32)controllerCfg->DefaultBaud->BrpValue;
    }
    configParams.nomRatePrescalar -= (uint32)1U;

    /* Setup bit timing */
    tmpVal = (controllerCfg->DefaultBaud->Pseg1 +
                    controllerCfg->DefaultBaud->PropSeg) - 1U;
    configParams.nomTimeSeg1 = (uint32)tmpVal;
    configParams.nomTimeSeg2 = (uint32)controllerCfg->DefaultBaud->Pseg2 - 1U;
    configParams.nomSynchJumpWidth =
                                (uint32)controllerCfg->DefaultBaud->Sjw - 1U;
    tmpVal = (controllerCfg->DefaultBaud->BaudFdRateConfig.Pseg1 +
                    controllerCfg->DefaultBaud->BaudFdRateConfig.PropSeg) - 1U;
    configParams.dataTimeSeg1 = (uint32)tmpVal;

    configParams.dataTimeSeg2 =
                (uint32)controllerCfg->DefaultBaud->BaudFdRateConfig.Pseg2 - 1U;
    configParams.dataSynchJumpWidth =
                (uint32)controllerCfg->DefaultBaud->BaudFdRateConfig.Sjw - 1U;
    configParams.dataRatePrescalar =
            (uint32)controllerCfg->DefaultBaud->BaudFdRateConfig.BrpValue - 1U;

    status = MCAN_setBitTime(baseAddr, &configParams);
    if (STW_SOK == status)
    {
        /* Bit timings config successful */
    }
    else
    {
#if (CAN_DEV_ERROR_DETECT == STD_ON)
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_INIT_ID,
                               (uint8) CAN_E_PARAM_BAUDRATE);
#endif
    }
}

void Can_mcanMsgRAMConfigInit(Can_FdMsgRAMConfigObjType *canFDMsgRamConfig)
{
    uint32 loopCnt = 0U;
    canFDMsgRamConfig->stdFilterNum      = (uint8)0U;
    canFDMsgRamConfig->extFilterNum      = (uint8)0U;

    /* Initialize Message RAM configuration parameters */
    canFDMsgRamConfig->configParams.flssa                  = 0U;
    canFDMsgRamConfig->configParams.lss                    = 0U;
    canFDMsgRamConfig->configParams.flesa                  = 0U;
    canFDMsgRamConfig->configParams.lse                    = 0U;
    canFDMsgRamConfig->configParams.txStartAddr            = 0U;
    canFDMsgRamConfig->configParams.txBufNum               = 0U;
    canFDMsgRamConfig->configParams.txFIFOSize             = 0U;
    canFDMsgRamConfig->configParams.txBufMode              = 1U;
    canFDMsgRamConfig->configParams.txBufElemSize          =
                                                (uint32)MCAN_ELEM_SIZE_64BYTES;
    canFDMsgRamConfig->configParams.txEventFIFOStartAddr   = 0U;
    canFDMsgRamConfig->configParams.txEventFIFOSize        = 0U;
    canFDMsgRamConfig->configParams.txEventFIFOWaterMark   = 0U;
    canFDMsgRamConfig->configParams.rxFIFO0startAddr       = 0U;
    canFDMsgRamConfig->configParams.rxFIFO0size            = 0U;
    canFDMsgRamConfig->configParams.rxFIFO0waterMark       = 0U;
    canFDMsgRamConfig->configParams.rxFIFO0OpMode          = 0U;
    canFDMsgRamConfig->configParams.rxFIFO1startAddr       = 0U;
    canFDMsgRamConfig->configParams.rxFIFO1size            = 0U;
    canFDMsgRamConfig->configParams.rxFIFO1waterMark       = 0U;
    canFDMsgRamConfig->configParams.rxFIFO1OpMode          = 0U;
    canFDMsgRamConfig->configParams.rxBufStartAddr         = 0U;
    canFDMsgRamConfig->configParams.rxBufElemSize          =
                                                (uint32)MCAN_ELEM_SIZE_64BYTES;
    canFDMsgRamConfig->configParams.rxFIFO0ElemSize        =
                                                (uint32)MCAN_ELEM_SIZE_64BYTES;
    canFDMsgRamConfig->configParams.rxFIFO1ElemSize        = 0U;

    canFDMsgRamConfig->txBuffNum                           = (uint16)0U;
    canFDMsgRamConfig->txFIFONum                           = (uint16)0U;
    canFDMsgRamConfig->rxBuffNum                           = (uint16)0U;
    canFDMsgRamConfig->rxFIFONum                           = (uint16)0U;

    for (loopCnt = 0U ; loopCnt < KMAX_MB_PER_CONTROLLER ; loopCnt++)
    {
        canFDMsgRamConfig->stdMsgIDFilterList[loopCnt].sfid1 = 0U;
        canFDMsgRamConfig->stdMsgIDFilterList[loopCnt].sfid2 = 0U;
        canFDMsgRamConfig->stdMsgIDFilterList[loopCnt].sfec  = 0U;
        canFDMsgRamConfig->stdMsgIDFilterList[loopCnt].sft   = 0x3U;
        canFDMsgRamConfig->extMsgIDFilterList[loopCnt].efid1 = 0U;
        canFDMsgRamConfig->extMsgIDFilterList[loopCnt].efid2 = 0U;
        canFDMsgRamConfig->extMsgIDFilterList[loopCnt].efec  = 0U;
        canFDMsgRamConfig->extMsgIDFilterList[loopCnt].eft   = 0x3U;
        canFDMsgRamConfig->txMbMapping[0U][loopCnt]           = 0xFFU;
        canFDMsgRamConfig->txMbMapping[1U][loopCnt]           = 0xFFU;
        canFDMsgRamConfig->rxMbMapping[0U][loopCnt]           = 0xFFU;
        canFDMsgRamConfig->rxMbMapping[1U][loopCnt]           = 0xFFU;
        canFDMsgRamConfig->hthToMbMapping[loopCnt]            = 0xFFU;
    }
}

void Can_mcanSetUpController(uint32 baseAddr)
{

    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;

    /* reset MCAN Module */
    MCAN_reset(baseAddr);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
                /* timeout */
              (void)Dem_SetEventStatus(
                    CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while ((uint32)TRUE == MCAN_isInReset(baseAddr));
    }

    /* Put MCAN in SW initialization mode */
    MCAN_setOpMode(baseAddr, (uint32_t)MCAN_OPERATION_MODE_SW_INIT);
    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);
    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for FSM to to come out of reset */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32)CAN_CFG_TIMEOUT_DURATION)
            {
                /* timeout */
              (void)Dem_SetEventStatus(
                    CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
                break;
            }
        } while ((uint32_t)MCAN_OPERATION_MODE_SW_INIT != 
                                                    MCAN_getOpMode(baseAddr));
    }
}

void Can_mcanSetUpMSGRAM(Can_ControllerObjType *canController,
                         const Can_MailboxObjType *canMailbox,
                         uint32 maxMbCnt)
{
    uint32 htrh, baseAddr;
    uint8 controller;
    Can_ControllerType *canControllerCfg;
    const Can_MailboxType *mailboxCfg;
    const Can_MailboxObjType *mailBoxCfgList;
    Can_FdMsgRAMConfigObjType *msgRamConfig;

    controller = canController->canControllerConfig.ControllerId;
    canControllerCfg = &canController->canControllerConfig;
    mailBoxCfgList = &canMailbox[0U];
    baseAddr = canControllerCfg->CntrAddr;
    msgRamConfig = &canController->canFDMsgRamConfig;
    Can_mcanMsgRAMConfigInit(msgRamConfig);
    /* Initialize Message RAM params according to configured mailboxes */
    for (htrh = 0U; htrh < maxMbCnt; htrh++)
    {
        mailboxCfg = &mailBoxCfgList[htrh].mailBoxConfig;
        if (mailboxCfg->Controller->ControllerId == controller)
        {
            if (CAN_MAILBOX_DIRECTION_RX == mailboxCfg->MBDir)
            {
                Can_mcanSetUpRxMailbox(msgRamConfig,
                                       mailboxCfg,
                                       htrh);
            }
            if (CAN_MAILBOX_DIRECTION_TX == mailboxCfg->MBDir)
            {
                Can_mcanSetUpTxMailbox(msgRamConfig,
                                       mailboxCfg,
                                       canControllerCfg,
                                       htrh,
                                       baseAddr);
                CanHtrhMbMapping[mailboxCfg->CanObjectId] = htrh;
            }
        }
    }
    msgRamConfig->configParams.lss = (uint32)msgRamConfig->stdFilterNum;
    msgRamConfig->configParams.lse = (uint32)msgRamConfig->extFilterNum;
    /* Configure Message RAM sections:
     * STD/EXT filters, Tx Buffers/FIFO and Rx Buffers/FIFO */
    Can_mcanMsgRAMConfig(baseAddr, msgRamConfig);
}

void Can_mcanSetUpTxMailbox(Can_FdMsgRAMConfigObjType *msgRamConfig,
                            const Can_MailboxType *mailboxCfg,
                            Can_ControllerType *canControllerCfg,
                            uint32 htrh,
                            uint32 baseAddr)
{
    uint32 intrCnt;
    if (mailboxCfg->CanHwObjectCount > 1U)
    {
        msgRamConfig->txMbMapping[1U][mailboxCfg->HwHandle] = htrh;
        msgRamConfig->txFIFONum += (uint16)mailboxCfg->CanHwObjectCount;
        msgRamConfig->configParams.txFIFOSize +=
                                        (uint32)mailboxCfg->CanHwObjectCount;
        /* Prepare Transmission Interrupt Enable Mask */
        for (intrCnt = 0U ;
            intrCnt < (uint32)mailboxCfg->CanHwObjectCount;
            intrCnt++)
        {
            if (canControllerCfg->TxInterrupt == (boolean) TRUE)
            {
                MCAN_txBufTransIntrEnable(baseAddr,
                                          (mailboxCfg->HwHandle + intrCnt));
            }
        }
    }
    else
    {
        msgRamConfig->txMbMapping[0U][mailboxCfg->HwHandle] = htrh;
        msgRamConfig->txBuffNum += (uint16)1U;
        msgRamConfig->configParams.txBufNum++;
        /* Prepare Transmission Interrupt Enable Mask */
        if (canControllerCfg->TxInterrupt == (boolean) TRUE)
        {
            MCAN_txBufTransIntrEnable(baseAddr, mailboxCfg->HwHandle);
        }
    }
}

void Can_mcanSetUpRxMailbox(Can_FdMsgRAMConfigObjType *msgRamConfig,
                            const Can_MailboxType *mailboxCfg,
                            uint32 htrh)
{
    uint8  idx = (uint8)0U;
    if (mailboxCfg->CanHwObjectCount > 1U)
    {
        /* Get Filter Mask for HRH - STD */
        if ((uint32)CAN_ID_STD == mailboxCfg->MBIdType)
        {
            idx = (uint8)msgRamConfig->stdFilterNum;
            msgRamConfig->stdMsgIDFilterList[idx].sfid1 =
                                (mailboxCfg->IDValue &  STD_MSGID_MASK);
            msgRamConfig->stdMsgIDFilterList[idx].sfid2 =
                                (mailboxCfg->Mask.MaskValue &  STD_MSGID_MASK);
            /* store the message in Rx FIFO 0 */
            msgRamConfig->stdMsgIDFilterList[idx].sfec = 0x1U;
            /* Classic Filter - Bit Mask */
            msgRamConfig->stdMsgIDFilterList[idx].sft = 0x2U;
            msgRamConfig->stdFilterNum++;
        }
        /* Get Filter Mask for HRH - EXT */
        else
        {
            idx = (uint8)msgRamConfig->extFilterNum;
            msgRamConfig->extMsgIDFilterList[idx].efid1 =
                                (mailboxCfg->IDValue & XTD_MSGID_MASK);
            msgRamConfig->extMsgIDFilterList[idx].efid2 =
                                (mailboxCfg->Mask.MaskValue & XTD_MSGID_MASK);
            /* store the message in Rx FIFO 0 */
            msgRamConfig->extMsgIDFilterList[idx].efec = 0x1U;
            /* Classic Filter - Bit mask */
            msgRamConfig->extMsgIDFilterList[idx].eft = 0x2U;
            msgRamConfig->extFilterNum++;
        }
        /* Set Mailbox entry */
        msgRamConfig->rxMbMapping[1U][msgRamConfig->rxFIFONum] = htrh;
        msgRamConfig->rxFIFONum += (uint16)1U;
        msgRamConfig->configParams.rxFIFO0size +=
                                        (uint32)mailboxCfg->CanHwObjectCount;
    }
    else
    {
        /* Get Filter Mask for HRH - STD */
        if ((uint32)CAN_ID_STD == mailboxCfg->MBIdType)
        {
            idx = (uint8)msgRamConfig->stdFilterNum;
            msgRamConfig->stdMsgIDFilterList[idx].sfid1 =
                                        (mailboxCfg->IDValue &  STD_MSGID_MASK);
            msgRamConfig->stdMsgIDFilterList[idx].sfid2 |=
                                            (uint32)msgRamConfig->rxBuffNum;
            msgRamConfig->stdMsgIDFilterList[idx].sfec = 0x7U;
            msgRamConfig->stdMsgIDFilterList[idx].sft = 0x0U;
            msgRamConfig->stdFilterNum++;
        }
        /* Get Filter Mask for HRH - EXT */
        else
        {
            idx = (uint8)msgRamConfig->extFilterNum;
            msgRamConfig->extMsgIDFilterList[idx].efid1 =
                                        (mailboxCfg->IDValue & XTD_MSGID_MASK);
            msgRamConfig->extMsgIDFilterList[idx].efid2 |=
                                        (uint32)msgRamConfig->rxBuffNum;
            msgRamConfig->extMsgIDFilterList[idx].efec = 0x7U;
            msgRamConfig->extMsgIDFilterList[idx].eft = 0x0U;
            msgRamConfig->extFilterNum++;
        }
        msgRamConfig->rxMbMapping[0U][msgRamConfig->rxBuffNum] = htrh;
        msgRamConfig->rxBuffNum += (uint16)1U;
    }
}

void Can_mcanMsgRAMConfig(uint32 baseAddr,
                          Can_FdMsgRAMConfigObjType *canFDMsgRamConfig)
{
    uint32 startAddr, loopCnt, txMbNum;

    txMbNum = ((uint32)canFDMsgRamConfig->txBuffNum +
                       (uint32)canFDMsgRamConfig->txFIFONum);
    if ((MCAN_TX_BUFFER_MAX_NUM >= txMbNum) &&
        (MCAN_RX_FIFO_0_MAX_NUM >= canFDMsgRamConfig->rxFIFONum) &&
        (MCAN_RX_BUFFER_MAX_NUM >= canFDMsgRamConfig->rxBuffNum))
    {
        /* Calculate start address for Message RAM sections */
        startAddr = 0U;
        canFDMsgRamConfig->configParams.flssa                  = 0U;
        startAddr += (uint32)(((uint32)canFDMsgRamConfig->stdFilterNum + 
                     (uint32)1U) * (uint32)MCAN_MSG_RAM_STD_ELEM_SIZE * 4U);
        canFDMsgRamConfig->configParams.flesa                  = startAddr;
        startAddr += (uint32)(((uint32)canFDMsgRamConfig->extFilterNum + 
                     (uint32)1U) * (uint32)MCAN_MSG_RAM_EXT_ELEM_SIZE * 4U);
        canFDMsgRamConfig->configParams.txStartAddr            = startAddr;
        startAddr += (uint32)(((uint32)canFDMsgRamConfig->configParams.txBufNum 
                     + (uint32)1U) * (uint32)MCAN_MSG_RAM_TX_RX_ELEM_SIZE * 4U);
        startAddr += (uint32)(((uint32)canFDMsgRamConfig->configParams.
                      txFIFOSize + (uint32)1U) * 
                      (uint32)MCAN_MSG_RAM_TX_RX_ELEM_SIZE * 4U);
        canFDMsgRamConfig->configParams.rxFIFO0startAddr       = startAddr;
        startAddr += (uint32)((canFDMsgRamConfig->configParams.rxFIFO0size + 1U)
                     * MCAN_MSG_RAM_TX_RX_ELEM_SIZE * 4U);
        canFDMsgRamConfig->configParams.rxBufStartAddr            = startAddr;

        /* Configure Message RAM */
        (void) MCAN_msgRAMConfig(baseAddr, &canFDMsgRamConfig->configParams);

        /* Configure Standard ID filters */
        for (loopCnt = 0U ; loopCnt < (uint32)canFDMsgRamConfig->stdFilterNum; 
             loopCnt++)
        {
            MCAN_addStdMsgIDFilter(
                            baseAddr,
                            loopCnt,
                            &canFDMsgRamConfig->stdMsgIDFilterList[loopCnt]);
        }
        /* Configure Extended ID filters */
        for (loopCnt = 0U ; loopCnt < (uint32)canFDMsgRamConfig->extFilterNum; 
             loopCnt++)
        {
            MCAN_addExtMsgIDFilter(
                            baseAddr,
                            loopCnt,
                            &canFDMsgRamConfig->extMsgIDFilterList[loopCnt]);
        }
    }
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    else
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8)CAN_INIT_ID,
                               (uint8) CAN_E_PARAM_HANDLE);
    }
#endif
}


static void Can_mcanSetId(const Can_PduType *PduInfo,
                          const Can_MailboxType *mailboxCfg,
                          MCAN_TxBufElement *elem)
{
    uint32 id;
    uint32 idType = CAN_ID_STD;
    uint32 status = (uint32) E_OK;

    switch (mailboxCfg->MBIdType)
    {
        case CAN_ID_STD:
        {
            idType = CAN_ID_STD;
            break;
        }

        case CAN_ID_XTD:
        {
            idType = CAN_ID_XTD;
            break;
        }

        case CAN_ID_MIXED:
        {
            /*Mixed ID */
            if ((PduInfo->id & CAN_MSG_ID_TYPE_EXT) == (CAN_MSG_ID_TYPE_EXT))
            {
                idType = CAN_ID_XTD;
            }
            else
            {
                idType = CAN_ID_STD;
            }
            break;
        }

        default:
        {
#if (CAN_DEV_ERROR_DETECT == STD_ON)
            (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                   (uint8) CAN_INSTANCE_ID,
                                   (uint8) CAN_WRITE_ID,
                                   (uint8) CAN_E_PARAM_CONTROLLER);
#endif
            status = (uint32) E_NOT_OK;
            break;
        }
    }

    if (((uint32) E_OK) == status)
    {
        id = Can_mcanGetID(idType, PduInfo->id);
        elem->xtd            = idType;
        elem->id             = id;
    }
}

static inline uint32 Can_mcanGetID(const uint32 idType,
                                   const uint32 CanId)
{
    uint32 id;

    if (idType == CAN_ID_STD)
    {
        /* Standard ID*/
        id = (CanId & STD_MSGID_MASK) << STD_MSGID_SHIFT;
    }
    else
    {
        /* Extended ID*/
        id = CanId & XTD_MSGID_MASK;
    }
    return id;
}

void Can_mcanChangeBaudrate(uint32 baseAddr, uint32 brp)
{
    MCAN_BitTimingParams configParams;
    sint32 status;

    MCAN_getBitTime(baseAddr, &configParams);
    configParams.nomRatePrescalar =  brp;
    configParams.nomRatePrescalar -= 1U;

    /* Not checking for return error as it is already check in configurator */
    status = MCAN_setBitTime(baseAddr, &configParams);
    if (STW_SOK == status)
    {
        /* Bit timings config successful */
    }
    else
    {
#if (CAN_DEV_ERROR_DETECT == STD_ON)
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CHNGBAUDRATE_ID,
                               (uint8) CAN_E_PARAM_BAUDRATE);
#endif
    }
}

void Can_mcanSetBaudrate(uint32 baseAddr, const Can_BaudConfigType *setBaud)
{
    MCAN_BitTimingParams configParams;
    uint8 tmpVal;
    sint32 status;

    configParams.nomRatePrescalar = ((uint32)setBaud->BrpValue);
    configParams.nomRatePrescalar -= 1U;

    /* Setup bit timing */
    tmpVal = (setBaud->Pseg1 + setBaud->PropSeg) - 1U;
    configParams.nomTimeSeg1 = (uint32)tmpVal;
    configParams.nomTimeSeg2 = (uint32)((uint32)setBaud->Pseg2 - 1U);
    configParams.nomSynchJumpWidth = (uint32)((uint32)setBaud->Sjw - 1U);
    tmpVal =       (setBaud->BaudFdRateConfig.Pseg1 +
                    setBaud->BaudFdRateConfig.PropSeg) - 1U;
    configParams.dataTimeSeg1 = (uint32)tmpVal;

    configParams.dataTimeSeg2 =
                        (uint32)setBaud->BaudFdRateConfig.Pseg2 - 1U;
    configParams.dataSynchJumpWidth =
                        (uint32)setBaud->BaudFdRateConfig.Sjw - 1U;
    configParams.dataRatePrescalar =
                        (uint32)setBaud->BaudFdRateConfig.BrpValue - 1U;
    status = MCAN_setBitTime(baseAddr, &configParams);
    if (STW_SOK == status)
    {
        /* Bit timings config successful */
    }
    else
    {
#if (CAN_DEV_ERROR_DETECT == STD_ON)
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_SETBAUDRATE_ID,
                               (uint8) CAN_E_PARAM_BAUDRATE);
#endif
    }
}

void Can_mcanDisableInterrupts(Can_ControllerObjType *controllerObj)
{
    uint8 InterruptCounter;
    uint32 baseAddr;

    InterruptCounter = controllerObj->canInterruptCounter;
    baseAddr = controllerObj->canControllerConfig.CntrAddr;
#if (STD_ON == CAN_ECC_ENABLE)
    /* Disable ECC Interrupt */
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_SEC, (uint32)FALSE);
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_DED, (uint32)FALSE);
#endif
    if ((uint32)MCAN_INTR_LINE_NUM_0 ==
        (controllerObj->canControllerConfig.InterruptMask &
                                                (uint32)MCAN_INTR_LINE_NUM_0))
    {
        /* Disable Interrupt Sources as well as Interrupt Line */
        MCAN_enableIntr(baseAddr, MCAN_INTR_MASK, (uint32)FALSE);
        MCAN_enableIntrLine(baseAddr,
                            (uint32)MCAN_INTR_LINE_NUM_0,
                            (uint32)FALSE);
    }
    controllerObj->canInterruptCounter = InterruptCounter + 1U;
}

void Can_mcanEnableInterrupts(Can_ControllerObjType *canController)
{
    uint8 InterruptCounter;
    uint32 baseAddr;

    InterruptCounter = canController->canInterruptCounter;
    baseAddr = canController->canControllerConfig.CntrAddr;
#if (STD_ON == CAN_ECC_ENABLE)
    /* Enable ECC Interrupt */
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_SEC, (uint32)TRUE);
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_DED, (uint32)TRUE);
#endif

    if (InterruptCounter != 0U)
    {
        canController->canInterruptCounter = InterruptCounter - 1U;
        InterruptCounter = canController->canInterruptCounter;
        if (InterruptCounter == 0U)
        {
            if ((uint32)MCAN_INTR_LINE_NUM_0 ==
                (canController->canControllerConfig.InterruptMask &
                                                (uint32)MCAN_INTR_LINE_NUM_0))
            {
                /* Enable Interrupt Sources as well as Interrupt Line */
                MCAN_enableIntr(baseAddr, MCAN_INTR_MASK, (uint32)TRUE);
                MCAN_enableIntrLine(baseAddr,
                                    (uint32)MCAN_INTR_LINE_NUM_0,
                                    (uint32)TRUE);
            }
        }     /*End of if (InterruptCounter == 0U)*/
    }
}

Can_ReturnType Can_mcanCheckWakeup(uint32 baseAddr)
{
    Can_ReturnType status = CAN_NOT_OK;
    uint32 initStatus, csa;

    initStatus = MCAN_getOpMode(baseAddr);
    csa = MCAN_getClkStopAck(baseAddr);
    if (((uint32)MCAN_CCCR_INIT_MODE_INIT == initStatus) &&
        ((uint32)MCAN_CCCR_CSA_ACK == (csa & (uint32)MCAN_CCCR_CSA_ACK)))
    {
        /*Sleeping*/
        status = CAN_NOT_OK;
    }
    else
    {
        /* Wakeup*/
        status = CAN_OK;
    }
    return status;
}

void Can_mcanTxDonePolling(Can_ControllerObjType *canController,
                           const Can_MailboxObjType *canMailbox,
                           uint8 htrh)
{
    uint32 messageBox = 0U, tranStatus, baseAddr, loopCnt, mbNum, bitPos;
    uint16 tmpBuffNum;

    baseAddr = canController->canControllerConfig.CntrAddr;

    if (canMailbox->mailBoxConfig.CanHwObjectCount > 1U)
    {
        loopCnt = (uint32)(canController->canFDMsgRamConfig.txBuffNum);
        tmpBuffNum = (canController->canFDMsgRamConfig.txBuffNum +
                 canController->canFDMsgRamConfig.txFIFONum);
        mbNum = (uint32) tmpBuffNum;
        for (; loopCnt < mbNum; loopCnt++)
        {
            if (htrh == canController->canFDMsgRamConfig.
                                                        hthToMbMapping[loopCnt])
            {

                messageBox = loopCnt;
                bitPos = ((uint32)1U << messageBox);
                tranStatus = MCAN_getTxBufTransmissionStatus(baseAddr);
                if ((canController->canTxStatus[messageBox] == 1U) &&
                    ((tranStatus & bitPos) == bitPos))
                {
                    /* Call TX confirmation */
                    CanIf_TxConfirmation(canMailbox->canTxRxPduId[messageBox]);
                    /* Clear the status as data is already sent */
                    canController->canTxStatus[messageBox] = 0U;
                }
            }
        }
    }
    else
    {
        messageBox = canMailbox->mailBoxConfig.HwHandle;
        bitPos = ((uint32)1U << messageBox);
        tranStatus = MCAN_getTxBufTransmissionStatus(baseAddr);
        if ((canController->canTxStatus[messageBox] == 1U) &&
            ((tranStatus & bitPos) == bitPos))
        {
            /* Clear the status as data is already sent */
            canController->canTxStatus[messageBox] = 0U;
            /* Call TX confirmation */
            CanIf_TxConfirmation(canMailbox->canTxRxPduId[messageBox]);
        }
    }
}

#if  (CAN_WAKEUP_POLLING == STD_ON)
void Can_mcan_WakeupProcess(Can_ControllerObjType *canController)
{
    uint32 initStatus, csa, baseAddr;

     baseAddr = canController->canControllerConfig.CntrAddr;
    initStatus = MCAN_getOpMode(baseAddr);

    csa = MCAN_getClkStopAck(baseAddr);
    /* If the controller is not activated just skip its checking */
    if (canController->canControllerConfig.CntrActive  == (boolean) TRUE)
    {
        if (((uint32)MCAN_CCCR_INIT_MODE_INIT == initStatus) &&
            ((uint32)MCAN_CCCR_CSA_ACK == (csa & (uint32)MCAN_CCCR_CSA_ACK)))
        {
            /*  Still Sleeping so indicate sleep */
            /* CanIf_ControllerModeIndication( controller_cntr,
             * CANIF_CS_SLEEP )*/
        }
        else
        {
            /* Call the Wakeup indication function */
            /*CanIf_ControllerModeIndication( controller_cntr,
             *CANIF_CS_STOPPED  )*/
            if (CAN_CS_SLEEP ==  canController->canState)
            {
                if (canController->canControllerConfig.ControllerId == 0U)
                {
#ifdef WAKEUP_SOURCE_REF_0
                    /* check */
                    EcuM_CheckWakeup(
                        (EcuM_WakeupSourceType) WAKEUP_SOURCE_REF_0);
#endif
                }
                else if (canController->canControllerConfig.ControllerId == 1U)
                {
#ifdef WAKEUP_SOURCE_REF_1
                    /* check */
                    EcuM_CheckWakeup(
                        (EcuM_WakeupSourceType) WAKEUP_SOURCE_REF_1);
#endif
                }
                else
                {
                    /* For MISRA-C Compliance */
                }
                canController->canState = CAN_CS_STOPPED;
            }
        }
    }
}
#endif

void Can_mcan_BusOffProcess(Can_ControllerObjType *canController)
{
    uint32 initStatus, baseAddr;
    MCAN_ProtocolStatus protStatus;

    baseAddr = canController->canControllerConfig.CntrAddr;
    initStatus = MCAN_getOpMode(baseAddr);
    MCAN_getProtocolStatus(baseAddr, &protStatus);
    if ((MCAN_PSR_BO_BUS_OFF == protStatus.busOffStatus) &&
        (MCAN_CCCR_INIT_MODE_INIT == initStatus))
    {
        /* Check if recovery has already started */
        if (canController->canBusOffRecoveryStatus != (boolean) TRUE)
        {
            Can_mcanCancelPendMsg(baseAddr);
            /* BusOff Recovery sequence has not started */
            canController->canState = CAN_CS_STOPPED;
            /*Call the bus off indication function*/
            CanIf_ControllerBusOff(canController->canControllerConfig.
                                                                  ControllerId);
        }
    }
}

void Can_mcan_ModeProcess(Can_ControllerObjType *canController)
{
    MCAN_ProtocolStatus protStatus;
    uint32 baseAddr;
    Can_ControllerStateType   controller_state;

    controller_state = canController->canState;
    baseAddr = canController->canControllerConfig.CntrAddr;
    switch (controller_state)
    {
        case CAN_CS_STARTED:
        {
            /* If BusOff recovery sequence has started, check if CAN
             * controller is started. If Not
             * restart CAN controller */
            if (canController->canBusOffRecoveryStatus == (boolean) TRUE)
            {
                if (canController->canControllerConfig.CntrActive ==
                                                            (boolean) TRUE)
                {
                    /* Restart CAN controller */
                    MCAN_setOpMode(baseAddr, 
                                   (uint32_t)MCAN_OPERATION_MODE_NORMAL);
                    MCAN_getProtocolStatus(baseAddr, &protStatus);
                    if (MCAN_PSR_BO_BUS_OFF == protStatus.busOffStatus)
                    {
                        /* Busoff recovery has completed */
                        canController->canBusOffRecoveryStatus =
                                                            (boolean) FALSE;
                    }
                }
            }
            CanIf_ControllerModeIndication(
                        (uint8)canController->canControllerConfig.ControllerId,
                        (CanIf_ControllerModeType)CANIF_CS_STARTED);
            break;
        }

        case CAN_CS_STOPPED:
        {
            if ((uint32_t)MCAN_OPERATION_MODE_SW_INIT == 
                                                       MCAN_getOpMode(baseAddr))
            {
                CanIf_ControllerModeIndication(
                            canController->canControllerConfig.ControllerId,
                            CANIF_CS_STOPPED);
            }
            break;
        }

        case CAN_CS_SLEEP:
        {
            if (MCAN_CCCR_CSA_ACK == (MCAN_getClkStopAck(baseAddr) &
                                                     (uint32)MCAN_CCCR_CSA_ACK))
            {
                CanIf_ControllerModeIndication(
                            canController->canControllerConfig.ControllerId,
                            CANIF_CS_SLEEP);
            }
            break;
        }

        default:
        {
            break;
        }
    } /*End of Switch*/
}

#if (CAN_RX_POLLING == STD_ON)
void Can_mcan_ReadProcess(Can_ControllerObjType *controllerObj,
                          const Can_MailboxObjType *canMailbox,
                          uint32 maxMbCnt)
{
    Can_FdMsgRAMConfigObjType ramConfig;

    ramConfig = controllerObj->canFDMsgRamConfig;
    /* Read Messages stored in  buffers */
    Can_mcanReadRxBuff(controllerObj,
                       canMailbox,
                       &ramConfig,
                       maxMbCnt);

    /* Empty FIFO messages */
    Can_mcanReadRxFIFO(controllerObj,
                       canMailbox,
                       maxMbCnt);
    }
#endif

void Can_mcanReadRxBuff(Can_ControllerObjType *controllerObj,
                        const Can_MailboxObjType *canMailbox,
                        const Can_FdMsgRAMConfigObjType *ramConfig,
                        uint32 maxMbCnt)
{
    uint32 canIdentifier = 0U, byteCnt, bitPos, buffNum, status, htrh, baseAddr;
    uint16       Hrh = 0U;
    uint8  CanDataLength;
    MCAN_RxNewDataStatus newDataStatus;
    MCAN_RxBufElement elem;

    baseAddr = controllerObj->canControllerConfig.CntrAddr;
    MCAN_getNewDataStatus(baseAddr, &newDataStatus);
    /* Clear NewData status to accept new messages */
    MCAN_clearNewDataStatus(baseAddr, &newDataStatus);
    /* Scan newData Register (32 bits x 2 Registers) and
     * read appropriate mailbox if any message is received */
    for (buffNum = 0U ; buffNum < 64U ; buffNum++)
    {
        if (buffNum < 32U)
        {
            status = newDataStatus.statusLow;
            bitPos = (uint32)(1U) << buffNum;
        }
        else
        {
            status = newDataStatus.statusHigh;
            bitPos = (uint32)1U << (buffNum - 32U);
        }

        if (bitPos == (status & bitPos))
        {
            if (buffNum < (uint32)ramConfig->rxBuffNum)
            {
                MCAN_readMsgRam(baseAddr,
                                (uint32_t)MCAN_MEM_TYPE_BUF,
                                buffNum,
                                &elem);
                CanDataLength = gMcanDataSize[elem.data_length];
                if (1U == elem.xtd)
                {
                    /* Received frame with Extended ID - set MSB to '1' */
                    canIdentifier = (uint32)(elem.id | CAN_MSG_ID_TYPE_EXT);
                }
                else
                {
                    /* Received frame with Standard ID */
                    canIdentifier = (uint32)((elem.id >> 18U) & STD_MSGID_MASK);
                }

                /* Set CAN-FD bit (30th bit) to '1' if CAN-FD frame is 
                   received */
                canIdentifier = (uint32)(canIdentifier | (elem.fdf << 30U));

                for (htrh = 0U ; htrh < maxMbCnt ; htrh++)
                {
                    /* Check for Controller type and Active state as well
                     * as MailBox Direction */
                    if ((CAN_MAILBOX_DIRECTION_RX ==
                                        canMailbox[htrh].mailBoxConfig.MBDir)
                        && ((boolean) TRUE ==
                        controllerObj->canControllerConfig.CntrActive) &&
                       (canMailbox[htrh].mailBoxConfig.Controller->ControllerId
                        == controllerObj->canControllerConfig.ControllerId) &&
                        (elem.xtd == canMailbox[htrh].mailBoxConfig.MBIdType) &&
                        /* ANDing with XTD_MSGID_MASK as that is maximum range 
                         * for both standard and extended type of identifier */
                       ((canIdentifier & XTD_MSGID_MASK) ==
                       (canMailbox[htrh].mailBoxConfig.IDValue & 
                       XTD_MSGID_MASK)))
                    {
                        break;
                    }
                }
                if (htrh < maxMbCnt)
                {
                    Hrh = canMailbox[htrh].mailBoxConfig.CanObjectId;
                }
                /* Copying payload into sdu */
                for (byteCnt = 0U ; byteCnt < CanDataLength; byteCnt++)
                {
                    controllerObj->canSduPtr[byteCnt] =
                                                    (uint8)elem.data[byteCnt];
                }
                 /* Copy CanId, HOH and ControllerId */
                controllerObj->mailboxCfg.Hoh = (uint8)Hrh;
                controllerObj->mailboxCfg.CanId = canIdentifier;
                controllerObj->mailboxCfg.ControllerId =
                    controllerObj->canControllerConfig.ControllerId;

                /* Copy SDU data */
                controllerObj->pduInfo.SduDataPtr = controllerObj->canSduPtr;
                controllerObj->pduInfo.SduLength  = (uint16)CanDataLength;

                /* Call Receive indication */
                CanIf_RxIndication(&controllerObj->mailboxCfg,
                    &controllerObj->pduInfo);
                /* Call the RX confirmation */
            }
        }
    }
}

void Can_mcanReadRxFIFO(Can_ControllerObjType *controllerObj,
                        const Can_MailboxObjType *canMailbox,
                        uint32 maxMbCnt)
{
    uint32 loopCnt, fillLvl, canIdentifier = 0U, byteCnt, htrh, baseAddr;
    uint8        CanDataLength;
    uint16       Hrh = 0U;
    MCAN_RxFIFOStatus fifoStatus;
    MCAN_RxBufElement elem;
    uint32 mask;

    Hrh = 0U;
    baseAddr = controllerObj->canControllerConfig.CntrAddr;
    fifoStatus.num = (uint32)MCAN_RX_FIFO_NUM_0;
    MCAN_getRxFIFOStatus(baseAddr, &fifoStatus);
    fillLvl = fifoStatus.fillLvl;
    for (loopCnt = 0U ; loopCnt < fillLvl ; loopCnt++)
    {
        MCAN_getRxFIFOStatus(baseAddr, &fifoStatus);
        MCAN_readMsgRam(baseAddr,
                        (uint32_t)MCAN_MEM_TYPE_FIFO,
                        fifoStatus.getIdx,
                        &elem);
        (void) MCAN_writeRxFIFOAck(baseAddr,fifoStatus.getIdx);
        CanDataLength = gMcanDataSize[elem.data_length];
        if (1U == elem.xtd)
        {
            /* Received frame with Extended ID - set MSB to '1' */
            canIdentifier = (uint32)(elem.id | CAN_MSG_ID_TYPE_EXT);
            mask = XTD_MSGID_MASK;

        }
        else
        {
            /* Received frame with Standard ID */
            canIdentifier = (uint32)((elem.id >> 18U) & STD_MSGID_MASK);
            mask = STD_MSGID_MASK;
        }

        /* Set CAN-FD bit (30th bit) to '1' if CAN-FD frame is received */
        canIdentifier = (uint32)(canIdentifier | (elem.fdf << 30U));

        for (htrh = 0U; htrh < maxMbCnt; htrh++)
        {
            /* Check for Controller type and Active state as well
             * as MailBox Direction */
            if ((CAN_MAILBOX_DIRECTION_RX ==
                    canMailbox[htrh].mailBoxConfig.MBDir) &&
               ((boolean)TRUE == controllerObj->canControllerConfig.CntrActive) 
                && (canMailbox[htrh].mailBoxConfig.Controller->ControllerId ==
                        controllerObj->canControllerConfig.ControllerId) &&
                (elem.xtd == canMailbox[htrh].mailBoxConfig.MBIdType))
            {
                /* get the exact mask value */
                mask = mask & canMailbox[htrh].mailBoxConfig.Mask.MaskValue;
                /* ANDing with mask for comparison */
                if ((canIdentifier & mask) ==
                    (canMailbox[htrh].mailBoxConfig.IDValue & mask))
                {
                    break;
                }
            }
        }
        if (htrh < maxMbCnt)
        {
            Hrh = canMailbox[htrh].mailBoxConfig.CanObjectId;
        }
        /* Copying payload into sdu */
        for (byteCnt = 0U ; byteCnt < CanDataLength; byteCnt++)
        {
            controllerObj->canSduPtr[byteCnt] = (uint8)elem.data[byteCnt];
        }
        /* Copy CanId, HOH and ControllerId */
        controllerObj->mailboxCfg.Hoh = (uint8)Hrh;
        controllerObj->mailboxCfg.CanId = canIdentifier;
        controllerObj->mailboxCfg.ControllerId =
            controllerObj->canControllerConfig.ControllerId;

        /* Copy SDU data */
        controllerObj->pduInfo.SduDataPtr = controllerObj->canSduPtr;
        controllerObj->pduInfo.SduLength  = (uint16)CanDataLength;

        /* Call Receive indication */
        CanIf_RxIndication(&controllerObj->mailboxCfg,
            &controllerObj->pduInfo);
    }
}

/*Requirements: SWS_Can_00273 */
void Can_mcanProcessISR(Can_ControllerObjType *canController,
                        const Can_MailboxObjType *canMailbox,
                        uint32 maxMbCnt)
{
    uint32 intrStatus, baseAddr;
    uint8 ControllerId;

    ControllerId = canController->canControllerConfig.ControllerId;
    baseAddr = canController->canControllerConfig.CntrAddr;
    intrStatus = MCAN_getIntrStatus(baseAddr);
    MCAN_clearIntrStatus(baseAddr, intrStatus);
    /* Process Error Interrupts */
    if ((uint32)MCAN_INTR_SRC_BUS_OFF_STATUS ==
       (intrStatus & (uint32)MCAN_INTR_SRC_BUS_OFF_STATUS))
    {
        Can_mcanCancelPendMsg(baseAddr);
        canController->canState =  CAN_CS_STOPPED;
        /* in BUS OFF state call the notification function */
        CanIf_ControllerBusOff(ControllerId);
    }
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if ((uint32)MCAN_INTR_SRC_RX_FIFO0_MSG_LOST ==
       (intrStatus & (uint32)MCAN_INTR_SRC_RX_FIFO0_MSG_LOST))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                       (uint8) ControllerId,
                                       (uint8) CAN_RXPROCESS_ID,
                                       (uint8) CAN_E_DATALOST);
    }
#endif
    if ((uint32)MCAN_INTR_SRC_TRANS_COMPLETE ==
       (intrStatus & (uint32)MCAN_INTR_SRC_TRANS_COMPLETE))
    {
        Can_mcanProcessISRTx(canController, canMailbox);
    }
    if (((uint32)MCAN_INTR_SRC_RX_FIFO0_NEW_MSG ==
       (intrStatus & (uint32)MCAN_INTR_SRC_RX_FIFO0_NEW_MSG)) ||
       ((uint32)MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG ==
       (intrStatus & (uint32)MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG)))
    {
        Can_mcanProcessISRRx(canController, canMailbox, maxMbCnt);
    }
}

void Can_mcanProcessISRTx(Can_ControllerObjType *canController,
                          const Can_MailboxObjType *canMailbox)
{
    uint32 txStatus, bitPos, hth, baseAddr;
    uint8 loopCnt;
    const Can_MailboxObjType *mailboxObj;
    const Can_MailboxType *mailboxCfg;

    baseAddr = canController->canControllerConfig.CntrAddr;

    txStatus = MCAN_getTxBufTransmissionStatus(baseAddr);
    /* Only 32 Tx Mailboxes are supported by hw */
    for (loopCnt = 0U ; loopCnt < MCAN_TX_MB_MAX_NUM ; loopCnt++)
    {
        bitPos = ((uint32)1U << loopCnt);
        if (bitPos == (txStatus & bitPos))
        {
            hth = canController->canFDMsgRamConfig.hthToMbMapping[loopCnt];
            mailboxObj = &canMailbox[hth];
            mailboxCfg = &canMailbox[hth].mailBoxConfig;
            if ((CAN_MAILBOX_DIRECTION_TX == mailboxCfg->MBDir) &&
               (canController->canTxStatus[loopCnt] == 1U))
            {
                canController->canTxStatus[loopCnt] = 0U;
                /* clear for next transmission. */
                CanIf_TxConfirmation(mailboxObj->canTxRxPduId[loopCnt]);
            }
        }
    }
}

void Can_mcanProcessISRRx(Can_ControllerObjType *controllerObj,
                          const Can_MailboxObjType *canMailbox,
                          uint32 maxMbCnt)
{
    Can_FdMsgRAMConfigObjType ramConfig;

    ramConfig = controllerObj->canFDMsgRamConfig;
    /* Read Messages stored in  buffers */
    Can_mcanReadRxBuff(controllerObj,
                       canMailbox,
                       &ramConfig,
                       maxMbCnt);

    /* Empty FIFO messages */
    Can_mcanReadRxFIFO(controllerObj,
                       canMailbox,
                       maxMbCnt);
}

#if (STD_ON == CAN_ECC_ENABLE)
void Can_mcanProcessECCISR(const Can_ControllerObjType *controllerObj)
{
    Can_ErrNotifyType errorNotification = NULL;
    MCAN_ECCErrStatus mcanECCErr;
    uint32 baseAddr;
    uint32 errType = (uint32)CAN_ECC_ERROR_TYPE_SEC;

    baseAddr = controllerObj->canControllerConfig.CntrAddr;
    MCAN_eccGetErrorStatus(baseAddr, &mcanECCErr);
    if (1U == mcanECCErr.secErr)
    {
        MCAN_eccClearErrorStatus(baseAddr, MCAN_ECC_ERR_TYPE_SEC);
        errType = (uint32)CAN_ECC_ERROR_TYPE_SEC;
    }
    if (1U == mcanECCErr.dedErr)
    {
        MCAN_eccClearErrorStatus(baseAddr, MCAN_ECC_ERR_TYPE_DED);
        errType = (uint32)CAN_ECC_ERROR_TYPE_DED;
    }
    errorNotification = controllerObj->canControllerConfig.
                                                    Can_ErrorNotification;

    if (errorNotification != NULL_PTR)
    {
        errorNotification(errType);
    }
    MCAN_eccWriteEOI(baseAddr, MCAN_ECC_ERR_TYPE_SEC);
    MCAN_eccWriteEOI(baseAddr, MCAN_ECC_ERR_TYPE_DED);
}
#endif

#if (CAN_CFG_DEINIT_API == STD_ON)
void Can_mcanHwDeInit(const Can_ControllerObjType *canController)
{
    uint32 baseAddr;

    baseAddr = canController->canControllerConfig.CntrAddr;
#if (STD_ON == CAN_ECC_ENABLE)
    /* Disable ECC Interrupt */
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_SEC, (uint32)FALSE);
    MCAN_eccEnableIntr(baseAddr, MCAN_ECC_ERR_TYPE_DED, (uint32)FALSE);
    /* Clear Interrupt status */
    MCAN_eccClearErrorStatus(baseAddr, MCAN_ECC_ERR_TYPE_SEC);
    MCAN_eccClearErrorStatus(baseAddr, MCAN_ECC_ERR_TYPE_DED);
#endif
    if ((uint32)MCAN_INTR_LINE_NUM_0 ==
        (canController->canControllerConfig.InterruptMask &
                                                (uint32)MCAN_INTR_LINE_NUM_0))
    {
        /* Disable Interrupt Sources as well as Interrupt Line */
        MCAN_enableIntr(baseAddr, MCAN_INTR_MASK, (uint32)FALSE);
        MCAN_enableIntrLine(baseAddr,
                            (uint32)MCAN_INTR_LINE_NUM_0,
                            (uint32)FALSE);
    }
    /* Clear Interrupt status */
    MCAN_clearIntrStatus(baseAddr, (uint32)MCAN_INTR_MASK_ALL);
}
#endif

#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"
