/* ======================================================================
*   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 DESCRIPTION
 *  -------------------------------------------------------------------------------------------------------------------
 *         File:  Can.c
 *      Project:  AM263x MCAL driver
 *       Module:  CAN Driver
 *
 *  Description:    The CAN driver provides services for CAN communication

 *---------------------------------------------------------------------------------------------------------------------
 *********************************************************************************************************************/

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */
#include "string.h"
#include "Can.h"
#include "CanIf_Cbk.h"
#include "EcuM_Cbk.h"
/* #include "Os.h" */
#include "SchM_Can.h"

#if (CAN_DEV_ERROR_DETECT == STD_ON)
#include "Det.h"
#endif


#include "soc.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_dcan.h"
#include "Can_Priv.h"

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

/* AUTOSAR version information check has to match definition in header file */
#if ((CAN_AR_RELEASE_MAJOR_VERSION != (4U))   \
    || (CAN_AR_RELEASE_MINOR_VERSION != (3U)) \
    || (CAN_AR_RELEASE_REVISION_VERSION != (1U)))
#error "CAN: AUTOSAR Version Numbers of CAN are different"
#endif

#if ((CAN_SW_MAJOR_VERSION != (0U)) || (CAN_SW_MINOR_VERSION != (9U)))
#error "Vendor specific version numbers of Can.c and Can.h are inconsistent"
#endif

#if ((CAN_CFG_MAJOR_VERSION != (0U)) || (CAN_CFG_MINOR_VERSION != (9U)))
#error "Version numbers of Can.c and Can_Cfg.h are inconsistent!"
#endif

/* FMEA requirement */
#if (STD_OFF == CAN_ECC_ENABLE)
/* TODO #warn "CAN parity check is not enabled " */
#endif

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

/* ========================================================================== */
/*                          Function Declarations                             */
/* ========================================================================== */
#if (CAN_DEV_ERROR_DETECT == STD_ON)
static boolean Can_CheckInitDet(const Can_ConfigType *ConfigPtr);
static boolean Can_CheckControllerConfig(const Can_ConfigType *ConfigPtr);
static boolean Can_CheckMbConfig(const Can_ConfigType *ConfigPtr);
static boolean Can_CheckWriteDet(const uint32 Hth,
                                 const Can_PduType *PduInfo,
                                 const Can_DriverObjType *canDrvObj);
static boolean Can_CheckEnableDet(uint8 Controller,
                                  const Can_DriverObjType * canDrvObj);
static boolean Can_CheckDisableDet(uint8 Controller,
                                   const Can_DriverObjType * canDrvObj);
static boolean Can_CheckSetControllerModeDet(uint8 Controller,
                                   const Can_DriverObjType * canDrvObj);
static boolean Can_CheckWakeupDet(uint8 Controller,
                                  const Can_DriverObjType * canDrvObj);
static boolean Can_SetBaudrateDet(uint8 Controller,
                                  const Can_DriverObjType * canDrvObj);
#if (CAN_CHANGE_BAUDRATE_API == STD_ON)
static boolean Can_ChangeBaudrateDet(uint8 Controller,
                                     const Can_DriverObjType * canDrvObj);
static boolean Can_CheckBaudrateDet(uint8 Controller);
#endif
#endif
static void Can_resetDrvObj(Can_DriverObjType *drvObj);
static void Can_initDrvObj(Can_DriverObjType *drvObj,
                           const Can_ConfigType *ConfigPtr);
LOCAL_INLINE Can_ReturnType Can_SetControllerModeProcess(
                                        Can_ControllerObjType * controllerObj,
                                        Can_ControllerStateType Transition);

/*******************************************************************************
 *  CONSTANT MACRO DEFINITION
 ******************************************************************************/

/* Interrupt source */
#define INT_IE0                  (0x1U)
#define INT_IE1                  (0x2U)

/**
 *  \brief CAN INVALID BASE ADDRESS
 */
#define CAN_INVALID_BASE_ADDR           (0x00000000U)

#define CAN_ID_CAN_CONTROLLER_TYPE_MASK         (0x40000000U)
#define CAN_ID_CAN_ID_TYPE_MASK                 (0x80000000U)

/*******************************************************************************
 * MACRO DEFINITIONS
 ******************************************************************************/

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

#define CAN_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Can_MemMap.h"

static Can_DriverObjType gCan_DriverObj;

#define CAN_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Can_MemMap.h"

#define CAN_START_SEC_VAR_INIT_UNSPECIFIED
#include "Can_MemMap.h"

static VAR(boolean, CAN_VAR_INIT) gCanInitDone = (boolean)FALSE;

#define CAN_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Can_MemMap.h"

#define CAN_START_SEC_VAR_NO_INIT_32
#include "Can_MemMap.h"

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

#define CAN_START_SEC_CODE
#include "Can_MemMap.h"

/*Requirements :SWS_Can_00079 , SWS_Can_00077, SWS_Can_00284, SWS_Can_00385,
 * SWS_Can_00386, SWS_Can_00427, SWS_Can_00401, SWS_Can_00402, SWS_Can_00403,
 * SWS_Can_00060,
 * SWS_Can_00202, SWS_Can_00110, SWS_Can_00234,
 * SWS_Can_00022,
 * SWS_Can_00024, SWS_Can_00221
 * SWS_Can_00490, SWS_Can_00440, SWS_Can_00242, SWS_Can_00398, SWS_Can_00397,
 * SWS_Can_00390  */

/* Optional Requirements which not implemented */
/* SWS_Can_00235, SWS_Can_00236, SWS_Can_00235, SWS_Can_00504, SWS_Can_00503 */

/* Not Applicable */
/* SWS_Can_00391, SWS_Can_00300, SWS_Can_00299, SWS_Can_00281 */

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */
/*******************************************************************************
 * Can_resetDrvObj
 ******************************************************************************/
/*! \brief      This function will reset default  Config structure.
 *
 *  \param[in]  Can_DriverObjType drvObj Pointer to Driver Config structure.
 *
 *  \context
 ******************************************************************************/
static void Can_resetDrvObj(Can_DriverObjType *drvObj)
{
    uint32 controllerIndx, mbIndx, loopIndx;

    for (controllerIndx = 0U; controllerIndx < (uint32)KMAX_CONTROLLER;
         controllerIndx++)
    {
        if (gCanInitDone == (boolean)FALSE)
        {
            drvObj->canController[controllerIndx].canState = CAN_CS_UNINIT;
        }
        drvObj->canController[controllerIndx].canBaud = 0U;
        drvObj->canController[controllerIndx].canBusOffRecoveryStatus =
                                                            (boolean) FALSE;
        drvObj->canController[controllerIndx].canInterruptCounter = (uint8)0U;
        for (mbIndx = 0U; mbIndx < (uint32)KMAX_MB_PER_CONTROLLER; mbIndx++)
        {
            drvObj->canController[controllerIndx].canTxStatus[mbIndx] =
                                                                  (uint8)0U;
        }
        for (mbIndx = 0U; mbIndx < (uint32)CAN_FD_PAYLOAD_MAX_BYTES; mbIndx++)
        {
            drvObj->canController[controllerIndx].canSduPtr[mbIndx] = (uint8)0U;
        }
        for (mbIndx = 0U; mbIndx < (uint32)KMAX_MAILBOXES; mbIndx++)
        {
            for (loopIndx = 0U ;
                 loopIndx < (uint32)KMAX_MB_PER_CONTROLLER ;
                 loopIndx++)
            {
                drvObj->canMailbox[mbIndx].canTxRxPduId[loopIndx] =
                                                                (PduIdType)0U;
            }
        }
    }
    return;
}

/*******************************************************************************
 * Can_initDrvObj
 ******************************************************************************/
/*! \brief      This function will initialize Driver Config structure.
 *
 *  \param[in]  Can_DriverObjType drvObj Pointer to Driver Config structure.
 *  \param[in]  Can_ConfigType ConfigPtr Pointer to Can controllers
 *              Config structure.
 *
 *  \context
 ******************************************************************************/
static void Can_initDrvObj(Can_DriverObjType *drvObj,
                           const Can_ConfigType *ConfigPtr)
{
    uint32 controllerIndx, mbIndx;

    for (controllerIndx = 0U ; controllerIndx < (uint32)KMAX_CONTROLLER ;
         controllerIndx++)
    {
        (void) memcpy(
            &drvObj->canController[controllerIndx].canControllerConfig,
            ConfigPtr->CanControllerList[controllerIndx],
            sizeof(Can_ControllerType));
        drvObj->canController[controllerIndx].MaxBaudConfigID =
                                ConfigPtr->MaxBaudConfigID[controllerIndx];
        drvObj->controllerIDMap[ConfigPtr->CanControllerList[controllerIndx]
                                ->CanControllerInst] = controllerIndx;

    }
    for (mbIndx = 0U ; mbIndx < (uint32)KMAX_MAILBOXES ; mbIndx++)
    {
        (void) memcpy(
            &drvObj->canMailbox[mbIndx].mailBoxConfig,
            ConfigPtr->MailBoxList[mbIndx],
            sizeof(Can_MailboxType));

    }
    drvObj->canMaxControllerCount = ConfigPtr->CanMaxControllerCount;
    drvObj->maxMbCnt              = ConfigPtr->MaxMbCnt;
}

LOCAL_INLINE Can_ReturnType Can_SetControllerModeProcess(
                                        Can_ControllerObjType * controllerObj,
                                        Can_ControllerStateType Transition)
{
    Can_ReturnType status;
    boolean retVal = (boolean) FALSE;

    switch (Transition)
    {
        case CAN_CS_STARTED:
        {
            retVal = Can_hwUnitStart(controllerObj);
            break;
        }

        case CAN_CS_STOPPED:
        {
            retVal = Can_hwUnitStop(controllerObj);
            break;
        }

        case CAN_CS_SLEEP:
        {
            retVal = Can_hwUnitSleep(controllerObj);
            break;
        }

        default:
        {
#if (CAN_DEV_ERROR_DETECT == STD_ON)
            retVal = (boolean) FALSE;
            (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                   (uint8) CAN_INSTANCE_ID,
                                   (uint8) CAN_SETCTR_ID,
                                   (uint8) CAN_E_TRANSITION);
#endif
        break;
        }
    }
    if (retVal == (boolean) TRUE)
    {
        status = CAN_OK;
    }
    else
    {
        status = CAN_NOT_OK;
    }
    return status;
}

/*******************************************************************************
 * Can_SetControllerMode
 ******************************************************************************/
/*! \brief      This function will transition the controller to different
 * states, Its AUTOSAR defined states.
 *
 *  \param[in]  uint8 Controller -  The controller for which the state change
 *              needs to be performed/
 *              Can_ControllerStateType Transition - the state to which
 *              controller needs to move in.
 *
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00261, SWS_Can_00262, SWS_Can_00257, SWS_Can_00265 ,
 * SWS_Can_00267, SWS_Can_00230
 * SWS_Can_00017, SWS_Can_00384, SWS_Can_00196, SWS_Can_00425, SWS_Can_00197,
 * SWS_Can_00426, SWS_Can_00198,
 * SWS_Can_00199, SWS_Can_00200, SWS_Can_00039*/
/* Design : CAN_DesignId_009 */
FUNC(Can_ReturnType, CAN_CODE) Can_SetControllerMode(
    uint8 Controller, Can_ControllerStateType Transition)
{
    Can_ReturnType status = CAN_NOT_OK;

    /*check for the validity of the controller parameter if det is enabled*/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_CheckSetControllerModeDet(Controller,
                                      &gCan_DriverObj) == (boolean) FALSE)
    {
        /* Det Error is already reported */
    }
    else
#endif
    {
        status = Can_SetControllerModeProcess(
                                &gCan_DriverObj.canController[Controller],
                                Transition);
    }

    return status;
}

/*******************************************************************************
 * Can_CheckInitDet
 ******************************************************************************/
/*! \brief      This function will check for NULL pointers for Config structure.
 *
 *  \param[in]  Can_ConfigType ConfigPtr Pointer to Driver Config structure.
 *
 *  \context
 ******************************************************************************/
/* Design :CAN_DesignId_006*/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
static boolean Can_CheckInitDet(const Can_ConfigType *ConfigPtr)
{
    boolean returnstatus = (boolean) TRUE;

    returnstatus = Can_CheckControllerConfig(ConfigPtr);
    if ((boolean) TRUE == returnstatus)
    {
        returnstatus = Can_CheckMbConfig(ConfigPtr);
    }

    return returnstatus;
}

static boolean Can_CheckControllerConfig(const Can_ConfigType *ConfigPtr)
{
    boolean returnstatus = (boolean) TRUE;
    uint32 loopCnt, cnt;

    for (loopCnt = 0U ; loopCnt < KMAX_CONTROLLER ; loopCnt++)
    {
        if (NULL_PTR == ConfigPtr->CanControllerList[loopCnt])
        {
            returnstatus = (boolean) FALSE;
        }
        else if (NULL_PTR == ConfigPtr->CanControllerList[loopCnt]->DefaultBaud)
        {
            returnstatus = (boolean) FALSE;
        }
        else if (CAN_INVALID_BASE_ADDR == 
                                ConfigPtr->CanControllerList[loopCnt]->CntrAddr)
        {
            returnstatus = (boolean) FALSE;
        }
        else
        {
            for (cnt = 0U ; cnt <= ConfigPtr->MaxBaudConfigID[loopCnt]; cnt++)
            {
                if (NULL_PTR ==
                ConfigPtr->CanControllerList[loopCnt]->BaudRateConfigList[cnt])
                {
                    returnstatus = (boolean) FALSE;
                }
            }
        }

        if ( returnstatus == (boolean)FALSE)
        {
            break;
        }
    }

    return returnstatus;
}

static boolean Can_CheckMbConfig(const Can_ConfigType *ConfigPtr)
{
    boolean returnstatus = (boolean) TRUE;
    uint32 loopCnt;

    for (loopCnt = 0U ; loopCnt < KMAX_MAILBOXES ; loopCnt++)
    {
        if (NULL_PTR == ConfigPtr->MailBoxList[loopCnt])
        {
            returnstatus = (boolean) FALSE;
        }
        else if (NULL_PTR == ConfigPtr->MailBoxList[loopCnt]->Controller)
        {
            returnstatus = (boolean) FALSE;
        }
        else
        {
            /*Do Nothing*/
        }

        if ( returnstatus == (boolean)FALSE)
        {
            break;
        }
    }
    return returnstatus;
}
#endif

/*******************************************************************************
 * Can_CheckSetControllerModeDet
 ******************************************************************************/
/*! \brief      This function will check DET for SetControllerMode API.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
/* Design :CAN_DesignId_006*/
static boolean Can_CheckSetControllerModeDet(uint8 Controller,
                                   const Can_DriverObjType * canDrvObj)
{
    boolean returnstatus;
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_SETCTR_ID, (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else if (Controller >= (canDrvObj->canMaxControllerCount))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_SETCTR_ID,
                               (uint8) CAN_E_PARAM_CONTROLLER);
        returnstatus = (boolean) FALSE;
    }
    else if (canDrvObj->canController[Controller].
                        canControllerConfig.CntrActive == (boolean) FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_SETCTR_ID, (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        /* MISRA C Compliance */
        returnstatus = (boolean) TRUE;
    }
    return returnstatus;
}

#endif

/*******************************************************************************
 * Can_CheckDisableDet
 ******************************************************************************/
/*! \brief      This function will check DET for Disable API.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
/* Design :CAN_DesignId_006*/
static boolean Can_CheckDisableDet(uint8 Controller,
                                   const Can_DriverObjType * canDrvObj)
{
    boolean returnstatus;
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_DIINT_ID, (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else if (Controller >= (canDrvObj->canMaxControllerCount))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_DIINT_ID,
                               (uint8) CAN_E_PARAM_CONTROLLER);
        returnstatus = (boolean) FALSE;
    }
    else if (canDrvObj->canController[Controller].
                        canControllerConfig.CntrActive == (boolean) FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_DIINT_ID, (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        returnstatus = (boolean) TRUE;
        /* MISRA C Compliance */
    }
    return returnstatus;
}

#endif

/*******************************************************************************
 * Can_CheckEnableDet
 ******************************************************************************/
/*! \brief      This function will check DET for Enable API.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
/* Design :CAN_DesignId_006*/
static boolean Can_CheckEnableDet(uint8 Controller,
                                  const Can_DriverObjType * canDrvObj)
{
    boolean returnstatus;
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_ENINT_ID, (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else if (Controller >= (canDrvObj->canMaxControllerCount))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_ENINT_ID,
                               (uint8) CAN_E_PARAM_CONTROLLER);
        returnstatus = (boolean) FALSE;
    }
    else if (canDrvObj->canController[Controller].
                        canControllerConfig.CntrActive == (boolean) FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_ENINT_ID, (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        returnstatus = (boolean) TRUE;
        /* MISRA C Compliance */
    }
    return returnstatus;
}

#endif

/*******************************************************************************
 * Can_CheckWakeupDet
 ******************************************************************************/
/*! \brief      This function will check DET for Can_CheckWakeup API.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
/* Design :CAN_DesignId_006*/
static boolean Can_CheckWakeupDet(uint8 Controller,
                                  const Can_DriverObjType * canDrvObj)
{
    boolean returnstatus;
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CKWAKEUP_ID,
                               (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else if (Controller >= (canDrvObj->canMaxControllerCount))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CKWAKEUP_ID,
                               (uint8) CAN_E_PARAM_CONTROLLER);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        returnstatus = (boolean) TRUE;
        /* MISRA C Compliance */
    }
    return returnstatus;
}

#endif

/*******************************************************************************
 *  API DEFINITIONS
 ******************************************************************************/

/*******************************************************************************
 * Can_Init
 ******************************************************************************/
/*! \brief     This function initilises the CAN controller
 *
 *              All the required initilisation for the CAN driver and hardware
 *              is performed in this function.
 *
 *  \param[in]  gCan_ConfigPtr  Pointer to post-build configuration data.
 *
 *  \context    App
 ******************************************************************************/
/*Requirements: SWS_Can_00291, SWS_Can_00021, SWS_Can_00250, SWS_Can_00053,
 * SWS_Can_00259, SWS_Can_00174, SWS_Can_00408, SWS_Can_00245,
 * SWS_Can_00407, SWS_Can_00104, SWS_Can_00026, SWS_Can_00056, SWS_Can_00255,
 *  SWS_Can_00246, SWS_Can_00238, SWS_Can_00220
 * SWS_Can_00239, SWS_Can_00240, SWS_Can_00244, SWS_Can_00419, SWS_Can_00091,
 * SWS_Can_00089, SWS_Can_00223, SWS_Can_00174, SWS_Can_00408, SWS_Can_00103,
 */
/* Design : CAN_DesignId_008 */
 FUNC(void, CAN_CODE) Can_Init(P2CONST(Can_ConfigType, AUTOMATIC,
                                    CAN_PBCFG) CfgPtr)
{
    uint8 controller_cntr;
    const Can_ConfigType *ConfigPtr = CfgPtr;
#if (STD_ON == CAN_CFG_PRE_COMPILE_VARIANT)
    if (NULL_PTR == ConfigPtr)
    {
        ConfigPtr = &CanConfigSet_0;
    }
#endif  /* (STD_ON == CAN_CFG_PRE_COMPILE_VARIANT) */
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (NULL_PTR == ConfigPtr)
    {
        /* Can config pointer is NOT valid */
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_INIT_ID,
                               (uint8) CAN_E_PARAM_POINTER);
    }
    else if (Can_CheckInitDet(ConfigPtr) == (boolean) FALSE)
    {
        /* Reporting Det Error */
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_INIT_ID,
                               (uint8) CAN_E_PARAM_POINTER);
    }
    else
#endif  /* (CAN_DEV_ERROR_DETECT == STD_ON) */
    {
        Can_resetDrvObj(&gCan_DriverObj);
        Can_initDrvObj(&gCan_DriverObj, ConfigPtr);
        for (controller_cntr = 0U;
             controller_cntr < gCan_DriverObj.canMaxControllerCount;
             controller_cntr++)
        {
#if (CAN_DEV_ERROR_DETECT == STD_ON)
            if (gCan_DriverObj.canController[controller_cntr].canState
                                                            != CAN_CS_UNINIT)
            {
                /* Can controller is in not in UNINT state */
                (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                       (uint8) CAN_INSTANCE_ID,
                                       (uint8) CAN_INIT_ID,
                                       (uint8) CAN_E_TRANSITION);
            }
            else
#endif
            {
                /* If Controller is active then only do initialization */
                if (gCan_DriverObj.canController[controller_cntr].
                            canControllerConfig.CntrActive ==
                                                            (boolean) TRUE)
                {
                    /* Init individual controller (may be moved to
                     * SetControllerMode(start state)) */
                    Can_hwUnitConfig(&gCan_DriverObj.
                                     canController[controller_cntr],
                                     &gCan_DriverObj.canMailbox[0U],
                                     gCan_DriverObj.maxMbCnt);
                    /* initialize the interrupt counter to zero */
                    gCan_DriverObj.canController[controller_cntr].
                    canInterruptCounter = 0U;
                    /* change the state to stopped from the UNINIT state */
                    gCan_DriverObj.canController[controller_cntr].canState =
                                                                CAN_CS_STOPPED;
                    /* Update BusOff Recovery status */
                    gCan_DriverObj.canController[controller_cntr].
                                canBusOffRecoveryStatus = (boolean) FALSE;
                }
            }
        }
        gCanInitDone = (boolean) TRUE;
    }
}

#if (CAN_VERSION_INFO_API == STD_ON)
/*******************************************************************************
 * Can_GetVersionInfo
 ******************************************************************************/
/*! \brief      This function will return the version for this module
 *
 *  \param[in]  None
 *
 *  \param[out]    Std_VersionInfoType VersionInfo - the structure that will
 *                  contain version info after fxn call.
 *
 *  \context    App
 ******************************************************************************/
/*Requirements: SWS_Can_00224, SWS_Can_00177 */
/* Design : CAN_DesignId_018 */
 FUNC(void,
     CAN_CODE)  Can_GetVersionInfo(P2VAR(Std_VersionInfoType, AUTOMATIC,
                                         CAN_APPL_DATA) Can_VersionInfo)
{
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_VersionInfo == NULL_PTR)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_VERSION_ID,
                               (uint8) CAN_E_PARAM_POINTER);
    }
    else
#endif
    {
        Can_VersionInfo->vendorID         = (uint16) CAN_VENDOR_ID;
        Can_VersionInfo->moduleID         = (uint16) CAN_MODULE_ID;
        Can_VersionInfo->sw_major_version = (uint8) CAN_SW_MAJOR_VERSION;
        Can_VersionInfo->sw_minor_version = (uint8) CAN_SW_MINOR_VERSION;
        Can_VersionInfo->sw_patch_version = (uint8) CAN_SW_PATCH_VERSION;
    }
}
#endif

/*******************************************************************************
 * Can_CheckWriteDet
 ******************************************************************************/
/*! \brief      This function will check DET for WriteAPI.
 *
 *  \param[in]  uint8 Hth - Hardware Handle
 *              const Can_PduType *PduInfo - pointer to pdu.
 *
 *  \context
 ******************************************************************************/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
/* Design :CAN_DesignId_006*/
static boolean Can_CheckWriteDet(const uint32 Hth,
                                 const Can_PduType *PduInfo,
                                 const Can_DriverObjType *canDrvObj)
{
    boolean returnstatus = (boolean) FALSE;
    uint8          MsgCntrlr = 0U;
    uint32         Hth1;

    if ((gCanInitDone == (boolean)FALSE) ||
            (canDrvObj->maxMbCnt <= Hth) ||
                   (PduInfo == NULL_PTR) )
    {
        /* Can config pointer is not valid */
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_WRITE_ID,
                               (uint8) CAN_E_PARAM_POINTER);
        returnstatus = (boolean) FALSE;
    }
    else if (PduInfo->sdu == NULL_PTR)
    {
        /* Can config pointer is not valid */
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_WRITE_ID,
                               (uint8) CAN_E_PARAM_POINTER);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        Hth1      = CanHtrhMbMapping[Hth];
        MsgCntrlr = canDrvObj->canMailbox[Hth1].
                                    mailBoxConfig.Controller->ControllerId;
        returnstatus = (boolean) TRUE;
    }
    if (returnstatus == (boolean) TRUE)
    {
        
        if (canDrvObj->canController[MsgCntrlr].
                    canControllerConfig.CntrActive == (boolean) FALSE)
        {
            /* Can controller is not valid */
            (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                   (uint8) CAN_INSTANCE_ID,
                                   (uint8) CAN_WRITE_ID,
                                   (uint8) CAN_E_UNINIT);
            returnstatus = (boolean) FALSE;
        }
        else
        {
            /* MISRA C Compliance */
            returnstatus = (boolean) TRUE;
        }

        if (((uint32)(CAN_CONTROLLER_TYPE_INFO_MCAN)==
            canDrvObj->canController[MsgCntrlr].
                                    canControllerConfig.CanControllerType)
            && (returnstatus == (boolean) TRUE))
        {
            if (PduInfo->length > 64U)
            {
                (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                       (uint8) CAN_INSTANCE_ID,
                                       (uint8) CAN_WRITE_ID,
                                       (uint8)CAN_E_PARAM_DATA_LENGTH);
                returnstatus = (boolean) FALSE;
            }
            else if ((PduInfo->length > 8U) &&
                    (CAN_ID_CAN_CONTROLLER_TYPE_MASK !=
                            (CAN_ID_CAN_CONTROLLER_TYPE_MASK & PduInfo->id)))
            {
                (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                       (uint8) CAN_INSTANCE_ID,
                                       (uint8) CAN_WRITE_ID,
                                       (uint8)CAN_E_PARAM_DATA_LENGTH);
                returnstatus = (boolean) FALSE;
            }
            else
            {
                returnstatus = (boolean) TRUE;
            }
        }
    }
    return returnstatus;
}

#endif

/*******************************************************************************
 * Can_Write
 ******************************************************************************/
/*! \brief      This function will write the data into Can mail boxes.
 *
 *  \param[in]  uint8 Hth -  This is the Msg box number its a unique number.
 *              const Can_PduType *PduInfo - the CAN message to be transmitted.
 *
 *
 *  \context    App
 ******************************************************************************/
/*Requirements: SWS_Can_00233, SWS_Can_00059, SWS_Can_00276, SWS_Can_00011,
 * SWS_Can_00212, SWS_Can_00213, SWS_Can_00501
 * SWS_Can_00214, SWS_Can_00275, SWS_Can_00216, SWS_Can_00217, SWS_Can_00218,
 * SWS_Can_00219, SWS_Can_00505, SWS_Can_00506, SWS_Can_00486, SWS_Can_00502
 * */
/* Design : CAN_DesignId_010 */
FUNC(Can_ReturnType, CAN_CODE) Can_Write(Can_HwHandleType Hth, 
                                         const Can_PduType *PduInfo)
{
    Can_ReturnType status = CAN_OK;
    uint32         messageBox, controller;
    uint8          MsgCntrlr;
    uint32         Hth1, msgObjIndx;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_CheckWriteDet((uint32) Hth, PduInfo, &gCan_DriverObj) ==
        (boolean) FALSE)
    {
        status = CAN_NOT_OK;
    }
    else
#endif
    {
        Hth1      = CanHtrhMbMapping[Hth];
        MsgCntrlr = gCan_DriverObj.canMailbox[Hth1].
                                mailBoxConfig.Controller->ControllerId;
        /* only for the Tx Mailbox */
        if (gCan_DriverObj.canMailbox[Hth1].mailBoxConfig.MBDir ==
                                                CAN_MAILBOX_DIRECTION_TX)
        {
            /* CanSM has triggered a new write after L1 timeout. Stop the BusOff
             * recovery.
             * CanSM will trigger a new bus off recovery sequence. */
            gCan_DriverObj.canController[MsgCntrlr].canBusOffRecoveryStatus =
                                                               (boolean) FALSE;
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();
            for (controller = 0U ; controller < KMAX_CONTROLLER; controller++)
            {
                if (MsgCntrlr == gCan_DriverObj.canController[controller].
                                            canControllerConfig.ControllerId)
                {
                    break;
                }
            }

            if (controller < KMAX_CONTROLLER)
            {               
                {
                    messageBox = (uint32)gCan_DriverObj.canMailbox[Hth1].
                                                        mailBoxConfig.HwHandle;
                }
                status = Can_writeGetFreeMsgObj(
                                &gCan_DriverObj.canMailbox[Hth1].mailBoxConfig,
                                &gCan_DriverObj.canController[MsgCntrlr],
                                &messageBox,
                                Hth1);
                if (status == CAN_OK)
                {
                    Can_writeTxMailbox(
                                &gCan_DriverObj.canMailbox[Hth1].mailBoxConfig,
                                &gCan_DriverObj.canController[MsgCntrlr],
                                Hth1,
                                messageBox,
                                PduInfo);
                    {
                        msgObjIndx = messageBox;
                    }
                    /* Store the transmitted Pdu SWPdu Handle for Tx
                     * confirmation */
                    gCan_DriverObj.canMailbox[Hth1].canTxRxPduId[msgObjIndx] =
                                                           PduInfo->swPduHandle;
                    /* set that this object is transmitted. */
                    gCan_DriverObj.canController[MsgCntrlr].
                                                canTxStatus[msgObjIndx] = 1U;
                }
            }
            else
            {
                status = CAN_NOT_OK;
            }
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
        }
        else
        {
#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_HANDLE);
#endif
            status = CAN_NOT_OK;
        }
    }
    return status;
}

/*******************************************************************************
 * Can_DisableControllerInterrupts
 ******************************************************************************/
/*! \brief      This function will Disable the interrupts for the Controller
 * desired.
 *              Basically it will Disable the CAN interrupts(reset bit 1 in CTL
 * reg(IE0=0)).
 *
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00231, SWS_Can_00049, SWS_Can_00205, SWS_Can_00206,
 *SWS_Can_00204*/
/* Design : CAN_DesignId_012 */
 FUNC(void, CAN_CODE)  Can_DisableControllerInterrupts(uint8 Controller)
{

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_CheckDisableDet(Controller, &gCan_DriverObj) == (boolean) FALSE)
    {
        /* Det Error is already reported */
    }
    else
#endif
    {
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();
#if (CAN_DEV_ERROR_DETECT == STD_ON)

        if ((gCan_DriverObj.canController[Controller].canControllerConfig.
                                                RxInterrupt == (boolean) FALSE)
            && (gCan_DriverObj.canController[Controller].canControllerConfig.
                                                TxInterrupt == (boolean) FALSE))
        {
            (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                   (uint8) CAN_INSTANCE_ID,
                                   (uint8) CAN_DIINT_ID,
                                   (uint8) CAN_E_PARAM_CONTROLLER);
        }
        else
#endif
        {
            Can_hwUnitDisableInterrupts(
                                &gCan_DriverObj.canController[Controller]);
        }
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
    }
}

/*******************************************************************************
 * Can_EnableControllerInterrupts
 ******************************************************************************/
/*! \brief      This function will Enable the interrupts for the Controller
 *              desired. It will restore the interrupts
 *              that were defined in the configuration. Basically it will enable
 *              the CAN interrupts.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00232, SWS_Can_00050, SWS_Can_00208, SWS_Can_00209,
 *SWS_Can_00210, SWS_Can_00033 */
/* Design : CAN_DesignId_013 */
FUNC(void, CAN_CODE)  Can_EnableControllerInterrupts(uint8 Controller)
{
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_CheckEnableDet(Controller, &gCan_DriverObj) == (boolean) FALSE)
    {
        /* Det Error is already reported */
    }
    else
#endif
    {
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();
        Can_hwUnitEnableInterrupts(&gCan_DriverObj.canController[Controller]);
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
    }
}

/*******************************************************************************
 * Can_MainFunction_Write
 ******************************************************************************/
/*! \brief      This function performs the polling of TX confirmation and TX
 * cancellation confirmation
 *              when CAN_TX_PROCESSING is set to POLLING.
 *
 *  \param[in]  void
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00058, SWS_Can_00016, SWS_Can_00225, SWS_Can_00031,
 *SWS_Can_00178,SWS_Can_00179,SWS_Can_00441 */
/* Design : CAN_DesignId_014 */
FUNC(void, CAN_CODE)  Can_MainFunction_Write(void)
{
#if  (CAN_TX_POLLING == STD_ON)
    uint8  htrh;
    uint8  Controller2;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_MAINFCT_WRITE_ID,
                               (uint8) CAN_E_UNINIT);
    }
    else
#endif
    {
        for (htrh = 0U ;
             htrh < (uint8) gCan_DriverObj.maxMbCnt;
             htrh++)
        {
            /* only for the Tx Mailbox */
            if (gCan_DriverObj.canMailbox[htrh].mailBoxConfig.MBDir ==
                CAN_MAILBOX_DIRECTION_TX)
            {
                Controller2 = gCan_DriverObj.canMailbox[htrh].
                                        mailBoxConfig.Controller->ControllerId;
                /* If the controller is not active then skip rest of processing
                **/
                if (gCan_DriverObj.canController[Controller2].
                            canControllerConfig.CntrActive == (boolean) TRUE)
                {
                    Can_hwUnitTxDonePolling(
                        &gCan_DriverObj.canController[Controller2],
                        &gCan_DriverObj.canMailbox[htrh],
                        htrh);
                }
            }
        }
    }
#endif
}

/*******************************************************************************
 * Can_CheckWakeup
 ******************************************************************************/
/*! \brief      This function will check the wakeup status for that controller.
 *
 *  \param[in]  uint8 Controller -  The controller for which the wake status
 * need to be checked
 *
 *  \return      Can_ReturnType  CAN_OK      - if wakeup is detected.
 *                               CAN_NOT_OK  - if Wakeup is not detected
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00360, SWS_Can_00361, SWS_Can_00362, SWS_Can_00363,
 *SWS_Can_00485 */
/* Design : CAN_DesignId_011 */
#if (CAN_WAKEUP_FUNCTIONALITY_API == STD_ON)
FUNC(Can_ReturnType, CAN_CODE) Can_CheckWakeup(uint8 Controller)
{
    uint32         baseAddr;
    Can_ReturnType status = CAN_NOT_OK;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_CheckWakeupDet(Controller, &gCan_DriverObj) == (boolean) FALSE)
    {
        /* Det Error is already reported */
    }
    else
#endif
    {
        baseAddr = gCan_DriverObj.canController[Controller].
                                            canControllerConfig.CntrAddr;
        status = Can_hwUnitCheckWakeup(
                            baseAddr);
    }
    return status;
}
#endif
#if (CAN_CHANGE_BAUDRATE_API == STD_ON)
/*******************************************************************************
 * Can_CheckBaudrate
 ******************************************************************************/
/*! \brief      This service shall check, if a certain CAN controller supports a
 *              requested baudrate
 *
 *  \param[in]  uint8 Controller -  The controller for which the Baud is to be
 *              checked
 *              const uint16 Baudrate - Baudrate in kbps
 *
 *  \return     Std_ReturnType -  E_OK      - Baud supported by Can
 *              Controller.
 *              E_NOT_OK  - Baud is not supported by Can
 *              Controller
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00454, SWS_Can_00455, SWS_Can_00459, SWS_Can_00460 */
/* Design : CAN_DesignId_021 */
FUNC(Std_ReturnType, CAN_CODE) Can_CheckBaudrate(uint8 Controller,
                                                 const uint16 Baudrate)
{
    uint32         brp;
    Std_ReturnType status = (Std_ReturnType)E_NOT_OK;
    uint32         brpMaxVal = 0x1FFU;
    uint32         clockFreq;
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_CheckBaudrateDet(Controller) == (boolean) FALSE)
    {
        /* Det Error is already reported */
    }
    else
#endif
    {
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();

        if (CAN_CONTROLLER_INSTANCE_MCAN1 == gCan_DriverObj.
           canController[Controller].canControllerConfig.CanControllerInst)
        {
            clockFreq = (uint32) CLK_CAN_FD1_FREQ;
        }
        else if (CAN_CONTROLLER_INSTANCE_MCAN2 == gCan_DriverObj.
           canController[Controller].canControllerConfig.CanControllerInst)
        {
            clockFreq = (uint32) CLK_CAN_FD2_FREQ;
        }
        else if (CAN_CONTROLLER_INSTANCE_MCAN3 == gCan_DriverObj.
           canController[Controller].canControllerConfig.CanControllerInst)
        {
            clockFreq = (uint32) CLK_CAN_FD3_FREQ;
        }
        else
        {
            clockFreq = (uint32) CLK_CAN_FD4_FREQ;
        }
        /* Validate the baud rate by calculating the BRPE */
        /* brp is brp*10 needed for rounding*/
        brp = (((uint32)10000U * (clockFreq))
               / ((uint32) Baudrate *
                  ((uint32)1U +
                   (uint32)(gCan_DriverObj.canController[Controller].
                             canControllerConfig.DefaultBaud->TimingValues))));
        /*Rounding the BRP value to nearest Integer */
        brp += 5U;
        brp /= 10U;
        /*Validate brp to be within permissible range for the controller type*/
        if (brp > brpMaxVal)
        {
#if (CAN_DEV_ERROR_DETECT == STD_ON)
            (void) Det_ReportError((uint16) CAN_MODULE_ID,
                                   (uint8) CAN_INSTANCE_ID,
                                   (uint8) CAN_CHKBAUDRATE_ID,
                                   (uint8) CAN_E_PARAM_BAUDRATE);
#endif
        }
        else
        {
            status = (Std_ReturnType) E_OK;
        }

        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
    }
    return status;
}
#endif

/*******************************************************************************
 * Can_CheckBaudrateDet
 ******************************************************************************/
/*! \brief      This function will check DET for Can_CheckBaudrate API.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
/*Requirements:  SWS_Can_00456, SWS_Can_00457, SWS_Can_00458 */
/* Design :CAN_DesignId_006*/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
static boolean Can_CheckBaudrateDet(uint8 Controller)
{
    boolean returnstatus = (boolean) TRUE;
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CHKBAUDRATE_ID,
                               (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else if (Controller >= (gCan_DriverObj.canMaxControllerCount))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CHKBAUDRATE_ID,
                               (uint8) CAN_E_PARAM_CONTROLLER);
        returnstatus = (boolean) FALSE;
    }
    else if (gCan_DriverObj.canController[Controller].canState !=
                                                                CAN_CS_STOPPED)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CHKBAUDRATE_ID,
                               (uint8) CAN_E_TRANSITION);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        /* MISRA C Compliance */
    }
    return returnstatus;
}

#endif
#if (CAN_CHANGE_BAUDRATE_API == STD_ON)
/*******************************************************************************
 * Can_ChangeBaudrate
 ******************************************************************************/
/*! \brief      This service shall change the baudrate of the CAN controller.
 *
 *  \param[in]  uint8 Controller -  The controller for which the Baud is to be
 *              changed
 *              const uint16 Baudrate - Baudrate in KB
 *
 *  \return     Std_ReturnType -  E_OK      - Baud accepted and change
 *              applied
 *                                E_NOT_OK  - Baud is not accepted by
 *              controller and no change done.
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00450, SWS_Can_00451, SWS_Can_00452, SWS_Can_00453,
 *SWS_Can_00500, SWS_Can_00493*/
/* Design : CAN_DesignId_020 */
FUNC(Std_ReturnType, CAN_CODE) Can_ChangeBaudrate(uint8 Controller,
                                                  const uint16 Baudrate)
{
    uint32                baseAddr;
    uint32                brp;
    Std_ReturnType        status = (Std_ReturnType)E_NOT_OK;
    Can_BaudConfigType   *defBaud;
    uint32         brpMaxVal = 0x1FFU;
    uint32         clockFreq;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_ChangeBaudrateDet(Controller, &gCan_DriverObj) == (boolean) FALSE)
    {
        /* Det Error is already reported */
    }
    else
#endif
    {
        if (CAN_CONTROLLER_INSTANCE_MCAN1 == gCan_DriverObj.
           canController[Controller].canControllerConfig.CanControllerInst)
        {
            clockFreq = (uint32) CLK_CAN_FD1_FREQ;
        }
        else if (CAN_CONTROLLER_INSTANCE_MCAN2 == gCan_DriverObj.
           canController[Controller].canControllerConfig.CanControllerInst)
        {
            clockFreq = (uint32) CLK_CAN_FD2_FREQ;
        }
        else if (CAN_CONTROLLER_INSTANCE_MCAN3 == gCan_DriverObj.
           canController[Controller].canControllerConfig.CanControllerInst)
        {
            clockFreq = (uint32) CLK_CAN_FD3_FREQ;
        }
        else
        {
            clockFreq = (uint32) CLK_CAN_FD4_FREQ;
        }
        baseAddr = gCan_DriverObj.canController[Controller].
                                            canControllerConfig.CntrAddr;
        Can_hwUnitConfig(&gCan_DriverObj.canController[Controller],
                         &gCan_DriverObj.canMailbox[0U],
                         gCan_DriverObj.maxMbCnt);
        defBaud = gCan_DriverObj.canController[Controller].
                                            canControllerConfig.DefaultBaud;
        /* Validate the baud rate by calculating the BRPE */
        /* brp is brp*10 needed for rounding */
        brp = (((uint32)10000U * (clockFreq)) / 
                ((uint32) Baudrate * ((uint32)1U +
                (uint32) (defBaud->TimingValues))));
        /*Rounding the BRP value to nearest Integer */
        brp += 5U;
        brp /= 10U;
        /* brp=brp-1 as we need to write one less into the register*/
        brp = brp - 1U;
        /*Validate brp to be within permissible range for the controller type*/
        if (brp > brpMaxVal)
        {
#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
        }
        else
        {
            Can_hwUnitChangeBaudrate(baseAddr,
                                     brp);
            /* Store the valid BRP for next time */
            gCan_DriverObj.canController[Controller].canBaud = (uint16) brp;
            status = (Std_ReturnType) E_OK;
        }
    }
    return status;
}
#endif
/*******************************************************************************
 * Can_ChangeBaudrateDet
 ******************************************************************************/
/*! \brief      This function will check DET for Can_ChangeBaudrate API.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00449, SWS_Can_00494, SWS_Can_00492, SWS_Can_00450 */
/* Design :CAN_DesignId_006*/
#if (CAN_DEV_ERROR_DETECT == STD_ON)
static boolean Can_ChangeBaudrateDet(uint8 Controller,
                                   const Can_DriverObjType * canDrvObj)
{
    boolean returnstatus = (boolean) TRUE;
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CHNGBAUDRATE_ID,
                               (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else if (Controller >= (canDrvObj->canMaxControllerCount))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CHNGBAUDRATE_ID,
                               (uint8) CAN_E_PARAM_CONTROLLER);
        returnstatus = (boolean) FALSE;
    }
    else if (canDrvObj->canController[Controller].canState !=
                                                            CAN_CS_STOPPED)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_CHNGBAUDRATE_ID,
                               (uint8) CAN_E_TRANSITION);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        /* MISRA C Compliance */
    }
    return returnstatus;
}

#endif

/*******************************************************************************
 * Can_SetBaudrateDet
 ******************************************************************************/
/*! \brief      This function will check DET for Can_ChangeBaudrate API.
 *
 *  \param[in]  uint8 Controller Controller Number in the can hardware its 0-3
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_CAN_00492, SWS_CAN_00494 */
#if (CAN_DEV_ERROR_DETECT == STD_ON)
static boolean Can_SetBaudrateDet(uint8 Controller,
                                   const Can_DriverObjType * canDrvObj)
{
    boolean returnstatus = (boolean) TRUE;
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_SETBAUDRATE_ID,
                               (uint8) CAN_E_UNINIT);
        returnstatus = (boolean) FALSE;
    }
    else if (Controller >= (canDrvObj->canMaxControllerCount))
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_SETBAUDRATE_ID,
                               (uint8) CAN_E_PARAM_CONTROLLER);
        returnstatus = (boolean) FALSE;
    }
    else if (canDrvObj->canController[Controller].canState !=
                                                CAN_CS_STOPPED)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_SETBAUDRATE_ID,
                               (uint8) CAN_E_TRANSITION);
        returnstatus = (boolean) FALSE;
    }
    else
    {
        /* MISRA C Compliance */
    }
    return returnstatus;
}

#endif

/*******************************************************************************
 * Can_SetBaudrate
 ******************************************************************************/
/*! \brief      This service shall set the baudrate of the CAN controller.
 *
 *  \param[in]  uint8 Controller -  The controller for which the Baud is to be
 *              changed
 *              BaudRateConfigID -  references a baud rate configuration by ID
 *
 *  \return     Std_ReturnType -  E_OK  - Service request accepted, setting
 *                                           of (new) baud rate started
 *
 *                                E_NOT_OK  - Service request not accepted
 *
 *  \context
 ******************************************************************************/
/* Design : CAN_DesignId_033 */
/*Requirements: SWS_Can_00493,SWS_Can_00500, SWS_Can_00256,
 *SWS_Can_00062, SWS_Can_00260 , SWS_Can_00422*/
FUNC(Std_ReturnType, CAN_CODE) Can_SetBaudrate(uint8 Controller,
                                               uint16 BaudRateConfigID)
{
    uint32                baseAddr;

    Std_ReturnType        status = E_NOT_OK;
    Can_BaudConfigType   *setBaud;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (Can_SetBaudrateDet(Controller, &gCan_DriverObj) == (boolean) FALSE)
    {
        /* Det Error is already reported */
    }
    else
#endif
    {
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();
        baseAddr = gCan_DriverObj.canController[Controller].
                                                canControllerConfig.CntrAddr;
        setBaud = gCan_DriverObj.canController[Controller].
                    canControllerConfig.BaudRateConfigList[BaudRateConfigID];

        if ((uint32)BaudRateConfigID >
            (gCan_DriverObj.canController[Controller].MaxBaudConfigID))
        {
#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
        }
        else
        {
            Can_hwUnitSetBaudrate(baseAddr,
                                setBaud);

            status = (Std_ReturnType) E_OK;
        }

        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
    }
    return status;
}

/*******************************************************************************
 * Can_MainFunction_Wakeup
 ******************************************************************************/
/*! \brief      This function performs the polling of wake-up events that are
 * configured statically as 'to be polled'.
 *
 *  \param[in]  void
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00270, SWS_Can_00271, SWS_Can_00269, SWS_Can_00228,
 *SWS_Can_00112, SWS_Can_00185, SWS_Can_00186*/
/* Design : CAN_DesignId_017 */
FUNC(void, CAN_CODE)  Can_MainFunction_Wakeup(void)
{
#if  (CAN_WAKEUP_POLLING == STD_ON)
    uint8  controller_cntr;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_MAINFCT_WU_ID,
                               (uint8) CAN_E_UNINIT);
    }
    else
#endif
    {
        for (controller_cntr = 0U;
             controller_cntr < gCan_DriverObj.canMaxControllerCount;
             controller_cntr++)
        {
            Can_MainFunction_WakeupProcess(
                                &gCan_DriverObj.canController[controller_cntr]);
        }
    }
#endif /* #if (CAN_WAKEUP_POLLING == STD_ON)  */
}
/*******************************************************************************
 * Can_MainFunction_BusOff
 ******************************************************************************/
/*! \brief      This function performs the polling of bus-off events that are
 * configured statically as 'to be polled'.
 *
 *  \param[in]  void
 *
 *  \context
 ******************************************************************************/
/*Requirements:SWS_Can_00280, SWS_Can_00007, SWS_Can_00227, SWS_Can_00109,
 *SWS_Can_00183, SWS_Can_00184 */
/* Design : CAN_DesignId_015 */
FUNC(void, CAN_CODE)  Can_MainFunction_BusOff(void)
{
#if (CAN_BUSOFF_POLLING == STD_ON)
    uint8  controller_cntr;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_MAINFCT_BO_ID,
                               (uint8) CAN_E_UNINIT);
    }
    else
#endif
    {
        for (controller_cntr = 0U;
             controller_cntr < gCan_DriverObj.canMaxControllerCount;
             controller_cntr++)
        {
            /* If the controller is not activated just skip its checking */
            if (gCan_DriverObj.canController[controller_cntr].
                        canControllerConfig.CntrActive == (boolean) TRUE)
            {
                Can_MainFunction_BusOffProcess(&gCan_DriverObj.
                                               canController[controller_cntr]);
            }
        }
    }
#endif /* #if (CAN_BUSOFF_POLLING == STD_ON) */
}

/*******************************************************************************
 * Can_MainFunction_Mode
 ******************************************************************************/
/*! \brief      This function performs the polling of CAN controller mode
 * transitions
 *              This will indicate only the CanController SW state and cannot
 *              indicate any HW state as there is not
 *              HW state exposed from the Can Controller.
 *
 *  \param[in]  void
 *
 *  \context
 ******************************************************************************/
/*Requirements:SWS_Can_00370, SWS_Can_00373, SWS_Can_00368, SWS_Can_00369,
 * SWS_Can_00379, SWS_Can_00372 */
/* Design : CAN_DesignId_019 */
FUNC(void, CAN_CODE)  Can_MainFunction_Mode(void)
{
    uint8  controller_cntr;

#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_MAINFCT_MODE_ID,
                               (uint8) CAN_E_UNINIT);
    }
    else
#endif
    {
        for (controller_cntr = 0U;
             controller_cntr < gCan_DriverObj.canMaxControllerCount;
             controller_cntr++)
        {
            Can_MainFunction_ModeProcess(
                &gCan_DriverObj.canController[controller_cntr]);
        }
    }
}

/*******************************************************************************
 * Can_MainFunction_Read
 ******************************************************************************/
/*! \brief      This function performs the polling of CAN controller mode
 * transitions
 *
 *  \param[in]  void
 *
 *  \context
 ******************************************************************************/
/*Requirements: SWS_Can_00396, SWS_Can_00395, SWS_Can_00007, SWS_Can_00226,
 * SWS_Can_00108, SWS_Can_00180, SWS_Can_00181
 * SWS_Can_00442 , SWS_Can_00423 */
/* Design : CAN_DesignId_016 */
FUNC(void, CAN_CODE)  Can_MainFunction_Read(void)
{
#if (CAN_RX_POLLING == STD_ON)
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (gCanInitDone == (boolean)FALSE)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID,
                               (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_MAINFCT_READ_ID,
                               (uint8) CAN_E_UNINIT);
    }
    else
#endif
    {
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_0();
        Can_MainFunction_ReadProcess(&gCan_DriverObj);
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_0();
    }
#endif /* #if (CAN_RX_POLLING == STD_ON) */
}

#if (CAN_LOOPBACK_ENABLE == STD_ON)
/*******************************************************************************
 * Can_TestLoopBackModeEnable
 ******************************************************************************/
/*! \brief      This function enables the Loopback
 *
 *  \param[in]  uint8 controller for which loopback needs to be enabled
 *              uint8 mode 0 - Enable Digital mode. 1 - Enable Analog mode.
 *
 *  \context
 ******************************************************************************/
/* Design : CAN_DesignId_022 */
FUNC(Std_ReturnType, CAN_CODE) Can_TestLoopBackModeEnable(uint8 controller,
                                                          uint8 mode)
{
    uint32 baseAddr;
    VAR(Std_ReturnType, AUTOMATIC) retVal;

    retVal = (Std_ReturnType) E_NOT_OK;
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (gCanInitDone == (boolean)TRUE)
#endif
    {
        if ((controller < (gCan_DriverObj.canMaxControllerCount)) &&
            (mode < 2U))
        {
            baseAddr = gCan_DriverObj.canController[controller].
                                                canControllerConfig.CntrAddr;
            retVal = Can_hwUnitTestLoopBackModeEnable(baseAddr,
                                    mode);
        }
    }
    return (retVal);
}

/*******************************************************************************
 * Can_TestLoopBackModeDisable
 ******************************************************************************/
/*! \brief      This function Disable the Loopback
 *
 *  \param[in]  uint8 controller for which loopback needs to be Disabled
 *              uint8 mode 0 - Disable Digital mode. 1 - Disable Analog mode.
 *
 *  \context
 ******************************************************************************/
/* Design : CAN_DesignId_023 */
FUNC(Std_ReturnType, CAN_CODE) Can_TestLoopBackModeDisable(uint8 controller,
                                                           uint8 mode)
{
    uint32 baseAddr;
    VAR(Std_ReturnType, AUTOMATIC) retVal;

    retVal = (Std_ReturnType) E_NOT_OK;
#if (CAN_DEV_ERROR_DETECT == STD_ON)
    if (gCanInitDone == (boolean)TRUE)
#endif
    {
        if ((controller < (gCan_DriverObj.canMaxControllerCount)) &&
            (mode < 2U))
        {
            baseAddr = gCan_DriverObj.canController[controller].
                                            canControllerConfig.CntrAddr;
            retVal = Can_hwUnitTestLoopBackModeDisable(baseAddr,
                                    mode);
        }
    }
    return (retVal);
}
#endif

/* Design : CAN_DesignId_034 */
/**
 * \brief API used only by UT.Not to be used by application
 */
#if (CAN_CFG_DEINIT_API == STD_ON)
/* [SWS_Can_91002],[SWS_Can_ 91009],[SWS_Can_91010],[SWS_Can_91011] */
FUNC(void, CAN_CODE) Can_DeInit(void)
{
    uint8 controllerIdx;

#if (STD_ON == CAN_DEV_ERROR_DETECT)
    if (((uint32) FALSE) == gCanInitDone)
    {
        (void) Det_ReportError((uint16) CAN_MODULE_ID, (uint8) CAN_INSTANCE_ID,
                               (uint8) CAN_DEINIT_ID, (uint8)CAN_E_TRANSITION);
    }
    else
#endif  /* #if (STD_ON == CAN_DEV_ERROR_DETECT) */
    {
        for (controllerIdx = 0U;
             controllerIdx < gCan_DriverObj.canMaxControllerCount;
             controllerIdx++)
        {
            gCan_DriverObj.canController[controllerIdx].canState = 
                                                                 CAN_CS_UNINIT;
            Can_hwDeInit(&gCan_DriverObj.canController[controllerIdx]);
        }
        Can_resetDrvObj(&gCan_DriverObj);
        gCanInitDone = (boolean)FALSE;
    }
}
#endif /* (CAN_CFG_DEINIT_API == STD_ON) */

 #define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"
/*******************************************************************************
 * INTERRUPT SERVICE ROUTINES
 ******************************************************************************/

#define CAN_START_SEC_ISR_CODE
#include "Can_MemMap.h"
#if  defined(CAN_CONTROLLER_MCAN1)
/*******************************************************************************
 * Can_0_Int0ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 1. All the
 * 				Interrupts are hooked to MCAN1INT.
 *              This ISR sends the TX confirmation for the successful tx msg.
 *              This ISR will call the RX processing function for the received
 *              message.
 *              This ISR will call the Error processing function in case of any
 *              error interrupts.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_0_Int0ISR_Fun(void)
{
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN1];

    Can_mcanProcessISR(&gCan_DriverObj.canController[ctrlId],
                       &gCan_DriverObj.canMailbox[0],
                       gCan_DriverObj.maxMbCnt);
}

/*******************************************************************************
 * Can_0_Int1ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 1 ECC Error.
 *              This ISR will clear and report the ECC Error through call back
 *              function.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
/*Requirements : SWS_Can_00033*/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_0_Int1ISR_Fun(void)
{
#if (STD_ON == CAN_ECC_ENABLE)
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN1];
        Can_mcanProcessECCISR(&gCan_DriverObj.canController[ctrlId]);
#endif

}
#endif

#if defined (CAN_CONTROLLER_MCAN2)
/*******************************************************************************
 * Can_1_Int0ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 2. All the
 * Interrupts are hooked to MCAN2INT.
 *              This ISR sends the TX confirmation for the successful tx msg.
 *              This ISR will call the RX processing function for the received
 *              message.
 *              This ISR will call the Error processing function in case of any
 *              error interrupts.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_1_Int0ISR_Fun(void)
{
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN2];
    Can_mcanProcessISR(&gCan_DriverObj.canController[ctrlId],
                           &gCan_DriverObj.canMailbox[0],
                           gCan_DriverObj.maxMbCnt);
}


/*******************************************************************************
 * Can_1_Int1ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 2 ECC Error.
 *              This ISR will clear and report the ECC Error through call back
 *              function.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
 /*Requirements : SWS_Can_00033*/
 /*Requirements : SWS_Can_00033*/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_1_Int1ISR_Fun(void)
{
#if (STD_ON == CAN_ECC_ENABLE)
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN2];
        Can_mcanProcessECCISR(&gCan_DriverObj.canController[ctrlId]);
#endif
}
#endif

#if  defined(CAN_CONTROLLER_MCAN3)
/*******************************************************************************
 * Can_2_Int0ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 3. All the
 * Interrupts are hooked to MCAN3INT.
 *              This ISR sends the TX confirmation for the successful tx msg.
 *              This ISR will call the RX processing function for the received
 *              message.
 *              This ISR will call the Error processing function in case of any
 *              error interrupts.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_2_Int0ISR_Fun(void)
{
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN3];

    Can_mcanProcessISR(&gCan_DriverObj.canController[ctrlId],
                       &gCan_DriverObj.canMailbox[0],
                       gCan_DriverObj.maxMbCnt);
}

/*******************************************************************************
 * Can_2_Int1ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 3 ECC Error.
 *              This ISR will clear and report the ECC Error through call back
 *              function.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
/*Requirements : SWS_Can_00033*/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_2_Int1ISR_Fun(void)
{
#if (STD_ON == CAN_ECC_ENABLE)
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN3];
        Can_mcanProcessECCISR(&gCan_DriverObj.canController[ctrlId]);
#endif

}
#endif

#if  defined(CAN_CONTROLLER_MCAN4)
/*******************************************************************************
 * Can_3_Int0ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 4. All the
 * Interrupts are hooked to MCAN4NT.
 *              This ISR sends the TX confirmation for the successful tx msg.
 *              This ISR will call the RX processing function for the received
 *              message.
 *              This ISR will call the Error processing function in case of any
 *              error interrupts.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_3_Int0ISR_Fun(void)
{
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN4];

    Can_mcanProcessISR(&gCan_DriverObj.canController[ctrlId],
                       &gCan_DriverObj.canMailbox[0],
                       gCan_DriverObj.maxMbCnt);
}

/*******************************************************************************
 * Can_3_Int1ISR_Fun
 ******************************************************************************/
/*! \brief      This is the ISR function for the MCAN controller 4 ECC Error.
 *              This ISR will clear and report the ECC Error through call back
 *              function.
 *
 *  \param[in]  void
 *
 *  \context    ISR
 ******************************************************************************/
/*Requirements : SWS_Can_00033*/
/* Design : CAN_DesignId_026 */
FUNC(void, CAN_CODE) Can_3_Int1ISR_Fun(void)
{
#if (STD_ON == CAN_ECC_ENABLE)
    uint32 ctrlId =
            gCan_DriverObj.controllerIDMap[CAN_CONTROLLER_INSTANCE_MCAN4];
        Can_mcanProcessECCISR(&gCan_DriverObj.canController[ctrlId]);
#endif

}
#endif

/* [SWS_Can_91004], [SWS_Can_91005], [SWS_Can_91006], [SWS_Can_91007],
   [SWS_Can_91008] */
/*******************************************************************************
 * Can_GetControllerErrorState
 ******************************************************************************/
 /**
 * \brief This function updates the error state of the controller.
 *
 * \verbatim
 * Service name: Can_GetControllerErrorState
 * Syntax      : Std_ReturnType Can_GetControllerErrorState( uint8 ControllerId,
 *               Can_ErrorStateType* ErrorStatePtr )
 * Service ID[hex]:0x11
 * Sync/Async     :Synchronous
 * Reentrancy     :Non Reentrant
 * Parameters (in):ControllerId
 *                 - ID of the CAN controller whose error state is requested.
 * Parameters (inout):None
 * Parameters (out)  :ErrorStatePtr
 *                    - Pointer where the error state is updated.
 * Return value:Std_ReturnType
 *              - E_OK: Error state request accepted
 *              - E_NOT_OK: Error state request not accepted
 * Description:This function updates the error state of the controller.
 * \endverbatim 
  *****************************************************************************/
FUNC(Std_ReturnType, CAN_CODE) Can_GetControllerErrorState(uint8 ControllerId,
  Can_ErrorStateType* ErrorStatePtr)
{
  Std_ReturnType          retVal = (Std_ReturnType)E_NOT_OK;
  Can_ErrorStateType    errorState;
#if (CAN_DEV_ERROR_DETECT == STD_ON)
  if (gCanInitDone == (boolean)FALSE)
  {
    (void)Det_ReportError((uint16)CAN_MODULE_ID,
      (uint8)CAN_INSTANCE_ID,
      (uint8)CAN_GETCTRERRST_ID,
      (uint8)CAN_E_UNINIT);
  }
  else if (ControllerId >= (gCan_DriverObj.canMaxControllerCount))
  {
    (void)Det_ReportError((uint16)CAN_MODULE_ID,
      (uint8)CAN_INSTANCE_ID,
      (uint8)CAN_GETCTRERRST_ID,
      (uint8)CAN_E_PARAM_CONTROLLER);
  }
  else if (ErrorStatePtr == NULL_PTR)
  {
    (void)Det_ReportError((uint16)CAN_MODULE_ID,
      (uint8)CAN_INSTANCE_ID,
      (uint8)CAN_GETCTRERRST_ID,
      (uint8)CAN_E_PARAM_POINTER);
  }
  else
#endif
  {
    retVal = (Std_ReturnType)E_OK;
    errorState = Can_mcanGetProtocolStatus
    (&gCan_DriverObj.canController[ControllerId]);
    *ErrorStatePtr = errorState;
  }

  return retVal;
}

/*******************************************************************************
 * Can_GetControllerMode
 ******************************************************************************/
 /**
 * \brief This service reports about the current status of the requested
 *        CAN controller.
 *
 * \verbatim
 * Service name: Can_GetControllerMode
 * Syntax: Std_ReturnType Can_GetControllerMode(uint8 Controller,
 *                     Can_ControllerStateType* ControllerModePtr)
 * Service ID[hex]: 0x12
 * Sync/Async: Synchronous
 * Reentrancy: Non Reentrant
 * Parameters (in): Controller
 *                  - CAN controller for which the status shall be changed
 * Parameters (out): ControllerModePtr
 *                  - Pointer to a memory location, where
 *                    the current mode of the CAN controller will be stored.
 * Parameters (inout):  None
 * Return value: Std_ReturnType
 *               - E_OK: request accepted
 *               - E_NOT_OK: request not accepted.
 * Description:  This service reports about the current status of the requested
 *               CAN controller.
 * \endverbatim 
  *****************************************************************************/

/* [SWS_Can_91014][SWS_Can_91015],[SWS_Can_91016],[SWS_Can_91017],
   [SWS_Can_91018] */

FUNC(Std_ReturnType, CAN_CODE)Can_GetControllerMode(uint8 Controller,
  Can_ControllerStateType* ControllerModePtr)
{
  Std_ReturnType    retVal = (Std_ReturnType)E_NOT_OK;
#if (CAN_DEV_ERROR_DETECT == STD_ON)
  if (gCanInitDone == (boolean)FALSE)
  {
    (void)Det_ReportError((uint16)CAN_MODULE_ID,
      (uint8)CAN_INSTANCE_ID,
      (uint8)CAN_GETCTRMODE_ID,
      (uint8)CAN_E_UNINIT);
  }
  else if (Controller >= (gCan_DriverObj.canMaxControllerCount))
  {
    (void)Det_ReportError((uint16)CAN_MODULE_ID,
      (uint8)CAN_INSTANCE_ID,
      (uint8)CAN_GETCTRMODE_ID,
      (uint8)CAN_E_PARAM_CONTROLLER);
  }
  else if (ControllerModePtr == NULL_PTR)
  {
    (void)Det_ReportError((uint16)CAN_MODULE_ID,
      (uint8)CAN_INSTANCE_ID,
      (uint8)CAN_GETCTRMODE_ID,
      (uint8)CAN_E_PARAM_POINTER);
  }
  else
#endif
  {
    retVal = (Std_ReturnType)E_OK;
    *ControllerModePtr = gCan_DriverObj.canController[Controller].canState;
  }

  return retVal;
}

#define CAN_STOP_SEC_ISR_CODE
#include "Can_MemMap.h"

/*******************************************************************************
 *  End of File: Can.c
 ******************************************************************************/
