/*!
* @file     Can_Hw.c
*
* @version  1.0.0
*
* @brief    AUTOSAR CAN Driver implementations
 *           
* @attention
*
* Project Name      : AUTOSAR MCAL
*
* Platform          : Arm
*
* Autosar Standard  : Classic Platform 4.4.0
*
* Compiled Version  : G32A10xx_MCAL_1_0_0_15-Nov-25
*
* Copyright (C) 2026 Geehy Semiconductor
*
* You may not use this file except in compliance with the
* GEEHY COPYRIGHT NOTICE (Geehy Semiconductor Software License Agreement).
*
* The program is only for reference, which is distributed in the hope
* that it will be usefull and instructional for customers to develop
* their software. Unless required by applicable law or agreed to in
* writing, the program is distributed on an "AS IS" BASIS, WITHOUT
* ANY WARRANTY OR CONDITIONS OF ANY KIND, either express or implied.
* See the Geehy Semiconductor Software License Agreement for the governing permissions
* and limitations under the License.
*/


/*
* MISRA-C:2012 compliance checks
*
*      Can_Hw_c_MISRA_REF1
*          Breaks the required CMN-0.4 of MISRA 2012 guidelines,
*          A grouping of messages for Dataflow Recovery
*
*      Can_Hw_c_MISRA_REF2
*          Breaks the required Rule-11.3 of MISRA 2012 guidelines,
*          A conversion shall not be performed between a pointer to object type and a pointer to a different object type
*
*/

#ifdef __cplusplus
extern "C"{
#endif

#include "Can.h"
#include "CanIf_Cbk.h"
#include "Det.h"
#include "Mcu_RcmTypes.h"

#include "SchM_Can.h"
#include "Mcal.h"

#ifndef CAN_ENABLE_TIMEOUT_AS_LOOP
    #include "Os.h"
#endif
/** @addtogroup G32A10xx_StdPeriphDriver
  @{
*/

/** @defgroup CAN_Driver
  * @brief CAN driver modules
  @{
*/

/** @defgroup CAN_Macros
  @{
*/
/*******************************************************************************
                    VENDOR ID & AUTOSAR VERSION INFO
*******************************************************************************/
/** Vendor ID (vendorId) of the dedicated implementation of this module according to the AUTOSAR vendor list. */
#define CAN_HW_VENDOR_ID                    0x00C1U
/** Module ID of this module, as defined in the BSW Module List. */
#define CAN_HW_MODULE_ID                    0x0050U
/** Major version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CAN_HW_AR_RELEASE_MAJOR_VERSION     0x04U
/** Minor version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CAN_HW_AR_RELEASE_MINOR_VERSION     0x04U
/** Revision version number of AUTOSAR release on which the appropriate implementation is based on. */
#define CAN_HW_AR_RELEASE_REVISION_VERSION  0x00U
/** Major version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CAN_HW_SW_MAJOR_VERSION             0x01U
/** Minor version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CAN_HW_SW_MINOR_VERSION             0x00U
/** Patch level version number of the vendor specific implementation of the module. The numbering is vendor specific. */
#define CAN_HW_SW_PATCH_VERSION             0x00U
/**@} end of group CAN_Macros */
/*******************************************************************************
                                VERSION CHECK
*******************************************************************************/
/* Make sure the vendor id is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_VENDOR_ID != CAN_HW_H_VENDOR_ID)
    #error "Vendor id mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the module id is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_MODULE_ID != CAN_HW_H_MODULE_ID)
    #error "Module id mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the AUTOSAR major version number is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_AR_RELEASE_MAJOR_VERSION != CAN_HW_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR major version number mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the AUTOSAR minor version number is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_AR_RELEASE_MINOR_VERSION != CAN_HW_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR minor version number mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the AUTOSAR revision version number is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_AR_RELEASE_REVISION_VERSION != CAN_HW_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR revision version number mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the software major version number is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_SW_MAJOR_VERSION != CAN_HW_H_SW_MAJOR_VERSION)
    #error "Software major version number mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the software minor version number is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_SW_MINOR_VERSION != CAN_HW_H_SW_MINOR_VERSION)
    #error "Software minor version number mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the software patch version number is the same between Can_Hw.c and Can_Hw.h */
#if (CAN_HW_SW_PATCH_VERSION != CAN_HW_H_SW_PATCH_VERSION)
    #error "Software patch version number mismatch between Can_Hw.c and Can_Hw.h"
#endif
/* Make sure the vendor id is the same between Can_Hw.c and Can.h */
#if (CAN_HW_VENDOR_ID != CAN_H_VENDOR_ID)
    #error "Vendor id mismatch between Can_Hw.c and Can.h"
#endif
/* Make sure the module id is the same between Can_Hw.c and Can.h */
#if (CAN_HW_MODULE_ID != CAN_H_MODULE_ID)
    #error "Module id mismatch between Can_Hw.c and Can.h"
#endif
/* Make sure the AUTOSAR major version number is the same between Can_Hw.c and Can.h */
#if (CAN_HW_AR_RELEASE_MAJOR_VERSION != CAN_H_AR_RELEASE_MAJOR_VERSION)
    #error "AUTOSAR major version number mismatch between Can_Hw.c and Can.h"
#endif
/* Make sure the AUTOSAR minor version number is the same between Can_Hw.c and Can.h */
#if (CAN_HW_AR_RELEASE_MINOR_VERSION != CAN_H_AR_RELEASE_MINOR_VERSION)
    #error "AUTOSAR minor version number mismatch between Can_Hw.c and Can.h"
#endif
/* Make sure the AUTOSAR revision version number is the same between Can_Hw.c and Can.h */
#if (CAN_HW_AR_RELEASE_REVISION_VERSION != CAN_H_AR_RELEASE_REVISION_VERSION)
    #error "AUTOSAR revision version number mismatch between Can_Hw.c and Can.h"
#endif
/* Make sure the software major version number is the same between Can_Hw.c and Can.h */
#if (CAN_HW_SW_MAJOR_VERSION != CAN_H_SW_MAJOR_VERSION)
    #error "Software major version number mismatch between Can_Hw.c and Can.h"
#endif
/* Make sure the software minor version number is the same between Can_Hw.c and Can.h */
#if (CAN_HW_SW_MINOR_VERSION != CAN_H_SW_MINOR_VERSION)
    #error "Software minor version number mismatch between Can_Hw.c and Can.h"
#endif
/* Make sure the software patch version number is the same between Can_Hw.c and Can.h */
#if (CAN_HW_SW_PATCH_VERSION != CAN_H_SW_PATCH_VERSION)
    #error "Software patch version number mismatch between Can_Hw.c and Can.h"
#endif

#ifdef ENABLE_INTERMODULE_MCAL_CHECK
    /* Make sure the AUTOSAR major version number is the same between Can_Hw.c and CanIf_Cbk.h */
    #if (CAN_HW_AR_RELEASE_MAJOR_VERSION != CANIF_CBK_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR major version number mismatch between Can_Hw.c and CanIf_Cbk.h"
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Can_Hw.c and CanIf_Cbk.h */
    #if (CAN_HW_AR_RELEASE_MINOR_VERSION != CANIF_CBK_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR minor version number mismatch between Can_Hw.c and CanIf_Cbk.h"
    #endif
    /* Make sure the AUTOSAR major version number is the same between Can_Hw.c and Mcal.h */
    #if (CAN_HW_AR_RELEASE_MAJOR_VERSION != MCAL_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR major version number mismatch between Can_Hw.c and Mcal.h"
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Can_Hw.c and Mcal.h */
    #if (CAN_HW_AR_RELEASE_MINOR_VERSION != MCAL_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR minor version number mismatch between Can_Hw.c and Mcal.h"
    #endif
    /* Make sure the AUTOSAR major version number is the same between Can_Hw.c and SchM_Can.h */
    #if (CAN_HW_AR_RELEASE_MAJOR_VERSION != SCHM_CAN_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR major version number mismatch between Can_Hw.c and SchM_Can.h"
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Can_Hw.c and SchM_Can.h */
    #if (CAN_HW_AR_RELEASE_MINOR_VERSION != SCHM_CAN_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR minor version number mismatch between Can_Hw.c and SchM_Can.h"
    #endif
    /* Make sure the AUTOSAR major version number is the same between Can_Hw.c and Det.h */
    #if (CAN_HW_AR_RELEASE_MAJOR_VERSION != DET_H_AR_RELEASE_MAJOR_VERSION)
        #error "AUTOSAR major version number mismatch between Can_Hw.c and Det.h"
    #endif
    /* Make sure the AUTOSAR minor version number is the same between Can_Hw.c and Det.h */
    #if (CAN_HW_AR_RELEASE_MINOR_VERSION != DET_H_AR_RELEASE_MINOR_VERSION)
        #error "AUTOSAR minor version number mismatch between Can_Hw.c and Det.h"
    #endif

    #ifndef CAN_ENABLE_TIMEOUT_AS_LOOP
        /* Make sure the AUTOSAR major version number is the same between Can_Hw.c and Os.h */
        #if (CAN_HW_AR_RELEASE_MAJOR_VERSION != OS_H_AR_RELEASE_MAJOR_VERSION)
            #error "AUTOSAR major version number mismatch between Can_Hw.c and Os.h"
        #endif
        /* Make sure the AUTOSAR minor version number is the same between Can_Hw.c and Os.h */
        #if (CAN_HW_AR_RELEASE_MINOR_VERSION != OS_H_AR_RELEASE_MINOR_VERSION)
            #error "AUTOSAR minor version number mismatch between Can_Hw.c and Os.h"
        #endif
    #endif /* CAN_ENABLE_TIMEOUT_AS_LOOP */
#endif /* ENABLE_INTERMODULE_MCAL_CHECK */

/*******************************************************************************
                            GLOBAL VARIABLES
*******************************************************************************/
/** @defgroup CAN_Variable
  @{
*/
#define CAN_START_SEC_CONST_UNSPECIFIED
#include "Can_MemMap.h"

/** Base address of the CAN controllers */
CONST(uint32, CAN_CONST) CAN_BASEADDR_ARR[1] = { CAN1_BASEADDR };

#if (STD_ON == CAN_ENABLE_FD_MODE)
static const VAR(uint8, CAN_VAR) Can_GblFdDlcConvDb[CAN_MSG_DATA_LEN_CAL_SIXTEEN] = \
{0, 1, 2, 3, 4, 5, 6, 7, 8, 12, 16, 20, 24, 32, 48, 64};
#endif

static const VAR(uint8, CAN_VAR) Can_DataRegionRegValToByteSize[CAN_BUF_DATA_REGION_SIZE_TYPE_COUNT] = \
{8, 12, 16, 20, 24, 32, 48, 64};

#define CAN_STOP_SEC_CONST_UNSPECIFIED
#include "Can_MemMap.h"

#define CAN_START_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Can_MemMap.h"

/** Timeout value for CAN operations */
static VAR(uint32, CAN_VAR) g_canTimeoutDuration;

/** Runtime status of the CAN controllers */
VAR(Can_ControllerStatusType, CAN_VAR) g_canControllerStatus[CAN_MAXCTRL_NUMBER_CFG];

#define CAN_STOP_SEC_VAR_NO_INIT_UNSPECIFIED
#include "Can_MemMap.h"

#define CAN_START_SEC_VAR_INIT_UNSPECIFIED
#include "Can_MemMap.h"

#if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
/** The ICOM message counter array */
static VAR(uint16, CAN_VAR) g_IcomMsgCtrVal[CAN_NOOF_ICOM_MSG_CONFIG] = {0};
#endif /* STD_ON == CAN_PUBLIC_ICOM_ENABLE */

static VAR(PduIdType, CAN_VAR) g_SwObjectHandle[CAN_NOOF_TX_HW_BUFF_AVAILABLE] = {0};

#if (STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE)
static VAR(PduIdType, CAN_VAR) g_CanTxSwObjPriority[CAN_NOOF_TX_HW_BUFF_AVAILABLE] = {0};
#endif

#define CAN_STOP_SEC_VAR_INIT_UNSPECIFIED
#include "Can_MemMap.h"
/**@} end of group CAN_Variable */
/*******************************************************************************
                        LOCAL FUNCTION DECLARATIONS
*******************************************************************************/
/** @defgroup CAN_Fuctions
  @{
*/
#define CAN_START_SEC_CODE
#include "Can_MemMap.h"

#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_CheckPayloadLength(
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_CONST) PduInfoPtr,
#if (STD_OFF == CAN_ENABLE_FD_MODE)
    VAR(uint16, AUTOMATIC) MbGlobalIndex,
#endif
    VAR(boolean, AUTOMATIC) EnabledFd, VAR(uint8, AUTOMATIC) Controller);
#endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */

LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WaitEnterInitMode(VAR(uint8, AUTOMATIC) HwOffset);
#if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WaitExitInitMode(VAR(uint8, AUTOMATIC) HwOffset);
#endif

LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WaitRegBitChange(VAR(uint32, AUTOMATIC) RegAddr, 
    VAR(uint32, AUTOMATIC) BitMask, VAR(uint8, AUTOMATIC) CheckBitVal);

#ifndef CAN_ENABLE_TIMEOUT_AS_LOOP
LOCAL_INLINE FUNC(uint32, CAN_CODE) Can_Hw_CalculateTimeoutValue(void);
#endif

static FUNC(void, CAN_CODE) Can_Hw_InitBaudrate(
    CONST(uint8, AUTOMATIC) HwOffset,
    CONST(uint8, AUTOMATIC) Controller,
    CONST(uint8, AUTOMATIC) BaudrateIndex);

LOCAL_INLINE FUNC(Can_FilterStandardEleType*, CAN_CODE)Can_Hw_GetStandardFilterEleAddr(
    CONST(uint32, AUTOMATIC) StandardFilterListStartAddr, 
    CONST(uint8, AUTOMATIC) filterIndex);

LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_InitStandardFilterEle(
    P2CONST(Can_FilterEleType, AUTOMATIC, CAN_APPL_CONST) FilterElePtr);

LOCAL_INLINE FUNC(Can_FilterExtendedEleType*, CAN_CODE) Can_Hw_GetExtendedFilterEleAddr(
    CONST(uint32, AUTOMATIC) ExtendedFilterListStartAddr, 
    CONST(uint8, AUTOMATIC) filterIndex);

LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_InitExtendedFilterEle(P2CONST(Can_FilterEleType, AUTOMATIC, CAN_APPL_CONST) FilterElePtr);
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_ClrRxBufNewDataFlg(CONST(uint8, CAN_CONST) HwOffset);
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_ClrRxFifo0Data(CONST(uint8, CAN_CONST) HwOffset);
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_ClrRxFifo1Data(CONST(uint8, CAN_CONST) HwOffset);
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_RxExtractData(CONST(uint8, AUTOMATIC) Controller,
    CONST(uint8, AUTOMATIC) RxBuffIndex, CONST(Can_RxDataCheckType, AUTOMATIC) RxBufferType, 
    CONST(Can_HwHandleType, AUTOMATIC) MbHrh);
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_FindValidRxMb(CONST(uint8, AUTOMATIC) Controller,
    CONST(Can_RxDataCheckType, AUTOMATIC) CheckBuffType,
    CONST(uint8, AUTOMATIC) RxBuffIndex, P2VAR(Can_HwHandleType, AUTOMATIC, CAN_APPL_DATA) MbHrhPtr, 
    CONST(boolean, AUTOMATIC) PriodicCheck, VAR(uint8, AUTOMATIC) PeriodRef);

#if (STD_ON == CAN_TRIGGER_TRANSMIT_ENABLE)
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_UpdatePduInfo(
    VAR(uint16, AUTOMATIC) MbGlobalIndex,
    CONSTP2VAR(Can_PduType, AUTOMATIC, CAN_APPL_DATA) TempPduInfoPtr, 
    CONSTP2CONST(Can_PduType, AUTOMATIC, CAN_APPL_DATA) PduInfoPtr);
#endif

static FUNC(void, CAN_CODE) Can_Hw_InitTxMBs(CONST(uint8, AUTOMATIC) Controller, 
    CONST(uint8, AUTOMATIC) HwOffset);

static FUNC(void, CAN_CODE) Can_Hw_InitTxEvtFifo(
    CONST(uint8, CAN_CONST) HwOffset);

static FUNC(void, CAN_CODE) Can_Hw_InitFilters(
    CONST(uint8, CAN_CONST) HwOffset);

static FUNC(void, CAN_CODE) Can_Hw_InitRxMBs(
    CONST(uint8, CAN_CONST) HwOffset);

#if (STD_ON == CAN_RXFIFO_ENABLE)
static FUNC(void, CAN_CODE) Can_Hw_InitRxFiFo(
    CONST(uint8, CAN_CONST) HwOffset);
#endif /* STD_ON == CAN_RXFIFO_ENABLE */

static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_ResetController(void);

static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetControllerToStopMode(
    CONST(uint8, CAN_CONST) Controller,
    VAR(boolean, AUTOMATIC) NotifyCanIf);

static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetControllerToStartMode(
    CONST(uint8, CAN_CONST) Controller);

static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetControllerToSleepMode(
    CONST(uint8, CAN_CONST) Controller);

#if (STD_ON == CAN_ABORT_MB_API_ENABLE)
static FUNC(void, CAN_CODE) Can_Hw_CancelMb(
    CONST(uint8, CAN_CONST) Controller,
    VAR(uint16, AUTOMATIC) MbGlobalIndex);
#endif /* STD_ON == CAN_ABORT_MB_API_ENABLE */

static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WriteMb(
    CONST(uint8, CAN_CONST) Controller,
    VAR(uint16, AUTOMATIC) MbGlobalIndex ,
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_CONST) PduInfoPtr);

#if (STD_ON == CAN_ENABLE_ERM)
static FUNC(void, CAN_CODE) Can_Hw_InitErm(void);
#endif

extern FUNC(boolean, COM_APPL_CODE) Can_LPduReceiveCalloutFunction(
    uint8 Hrh,
    Can_IdType CanId,
    uint8 CanDlc,
    const uint8* CanSduPtr);

#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
extern FUNC(Std_ReturnType, CAN_CODE) Can_CheckControllerId(
    VAR(uint8, AUTOMATIC) ApiId,
    VAR(uint8, AUTOMATIC) Controller);
#endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */

/*******************************************************************************
                            LOCAL FUNCTIONS
*******************************************************************************/
/*!
* @brief    Validate payload length before transmission
*
* @param[in]    PduInfoPtr      Index of the controller
* @param[in]    MbGlobalIndex   Index of the MB
* @param[in]    EnabledFd       Whether or not enable CAN FD
* @param[in]    Controller      Index of the controller
*/
#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_CheckPayloadLength(
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_CONST) PduInfoPtr,
#if (STD_OFF == CAN_ENABLE_FD_MODE)
    VAR(uint16, AUTOMATIC) MbGlobalIndex,
#endif /* STD_ON == CAN_ENABLE_FD_MODE */
    VAR(boolean, AUTOMATIC) EnabledFd, VAR(uint8, AUTOMATIC) Controller)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_OK;

#if (STD_OFF == CAN_ENABLE_FD_MODE)
    result = (PduInfoPtr->length <= 8U) ? (Std_ReturnType)E_OK : (Std_ReturnType)E_NOT_OK;
    (void)EnabledFd;
    (void)MbGlobalIndex;
#else /* STD_ON == CAN_ENABLE_FD_MODE */
    
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    VAR(uint32, AUTOMATIC) txescRegVal = REG_READ32(CAN_TXESC_REG_ADDR(hwOffset));
    VAR(uint8, AUTOMATIC) txDataRegionSize = Can_DataRegionRegValToByteSize[txescRegVal];

    /* Check data length */
    if ((((boolean)FALSE == EnabledFd) && ((PduInfoPtr->length) > (uint8)8U)) ||
        ((PduInfoPtr->length) > txDataRegionSize) ||
        (((((uint32)PduInfoPtr->id) & (uint32)CAN_ID_FD_DESCRIPTOR) != CAN_ID_FD_DESCRIPTOR) && ((PduInfoPtr->length) > (uint8)8U)))
    {
        result = (Std_ReturnType)E_NOT_OK;
    }
    else
    {
        /* Intentionally Empty */
    }
#endif /* STD_OFF == CAN_ENABLE_FD_MODE */

    if ((Std_ReturnType)E_NOT_OK == result)
    {
        (void)Det_ReportError((uint16)CAN_H_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                              (uint8)CAN_SID_WRITE, (uint8)CAN_E_PARAM_DATA_LENGTH);
    }
    else
    {
        /* Intentionally Empty */
    }
    return result;
}
#endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */

/*!
* @brief Wait until the register bit change
*
* @param[in]    RegAddr  Register address to be checked
* @param[in]    BitMask  Bit mask to be checked
* @param[in]    CheckBitVal  Expected bit value (CAN_BIT_RESET / CAN_BIT_RESET)
*
* @retval E_OK:     Register bit has changed to expected value
* @retval E_NOT_OK: Timeout has reached
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WaitRegBitChange(VAR(uint32, AUTOMATIC) RegAddr, 
    VAR(uint32, AUTOMATIC) BitMask, VAR(uint8, AUTOMATIC) CheckBitVal)
{
    VAR(Std_ReturnType, AUTOMATIC) result = E_NOT_OK;
    VAR(uint32, AUTOMATIC) totalElapsedTime = 0;

#ifndef CAN_ENABLE_TIMEOUT_AS_LOOP
    VAR(TickType, AUTOMATIC) startTime = 0U;
    VAR(TickType, AUTOMATIC) elapsedTime = 0U;
    (void)GetCounterValue((CounterType)CAN_TIMEOUT_COUNTER_NAME, &startTime);
#endif

    totalElapsedTime = 0U;
    while ((totalElapsedTime < g_canTimeoutDuration) &&
           ((((((uint32)REG_READ32(RegAddr) & BitMask) != BitMask)) && ((CheckBitVal == (uint8)CAN_BIT_SET))) || 
            (((((uint32)REG_READ32(RegAddr) & BitMask) == BitMask)) && ((CheckBitVal == (uint8)CAN_BIT_RESET))) || 
            (((((uint32)REG_READ32(RegAddr) & BitMask) == (uint8)CAN_BIT_RESET)) && (CAN_REGISTER_BITS_NOT_ZERO == CheckBitVal))))
    {
    #ifdef CAN_ENABLE_TIMEOUT_AS_LOOP
        totalElapsedTime++;
    #else
        (void)GetElapsedValue((CounterType)CAN_TIMEOUT_COUNTER_NAME, &startTime, &elapsedTime);
        totalElapsedTime += elapsedTime;
    #endif
    }
    result = (totalElapsedTime < g_canTimeoutDuration) ?
             (Std_ReturnType)E_OK : (Std_ReturnType)E_NOT_OK;
    return result;
}

/*!
* @brief Wait until the enter the initialization mode
*
* @param[in]    HwOffset  Controller hardware offset
*
* @retval E_OK:     Enter initialization mode successful
* @retval E_NOT_OK: Enter initialization mode failed
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WaitEnterInitMode(VAR(uint8, AUTOMATIC) HwOffset)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    
    /* Set the INIT bit region in the CCCR Register */
    REG_BIT_SET32(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_INIT_MASK);
    /* Wait until the INIT bit is set */
    result = Can_Hw_WaitRegBitChange(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_INIT_MASK, (uint8)CAN_BIT_SET);

    if((Std_ReturnType)E_OK == result)
    {
        /* Set the CCE bit region in the CCCR Register */
        REG_BIT_SET32(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_CCE_MASK);
        /* Wait until the CCE bit is set */
        result = Can_Hw_WaitRegBitChange(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_CCE_MASK, (uint8)CAN_BIT_SET);
    }
    else
    {
        result = (Std_ReturnType)E_NOT_OK;
    }

    return result;
}

#if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
/*!
* @brief Wait until the exit the initialization mode
*
* @param[in]    HwOffset  Controller hardware offset
*
* @retval E_OK:     Exit initialization mode successful
* @retval E_NOT_OK: Exit initialization mode failed
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WaitExitInitMode(VAR(uint8, AUTOMATIC) HwOffset)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    
    /* Clear the CCE bit region in the CCCR Register */
    REG_BIT_CLEAR32(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_CCE_MASK);
    /* Wait until the CCE bit is cleared */
    result = Can_Hw_WaitRegBitChange(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_CCE_MASK, (uint8)CAN_BIT_RESET);

    if((Std_ReturnType)E_OK == result)
    {
        /* Clear the INIT bit region in the CCCR Register */
        REG_BIT_CLEAR32(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_INIT_MASK);
        /* Wait until the INIT bit is cleared */
        result = Can_Hw_WaitRegBitChange(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_INIT_MASK, (uint8)CAN_BIT_RESET);
    }
    else
    {
        result = (Std_ReturnType)E_NOT_OK;
    }

    return result;
}
#endif

#ifndef CAN_ENABLE_TIMEOUT_AS_LOOP
/*!
* @brief    Calculate the timeout value
*/
LOCAL_INLINE FUNC(uint32, CAN_CODE) Can_Hw_CalculateTimeoutValue(void)
{
    VAR(float32, AUTOMATIC) timeoutFloat = 0;
    uint32 timeout = 0;

    timeoutFloat = (float32)(CAN_TIMEOUT_VALUE / (float32)CAN_TIMEOUT_COUNTER_TICK());
    timeout = ((timeoutFloat - (float32)((uint32)timeoutFloat)) > (float32)0) ?
              (uint32)((uint32)timeoutFloat + (uint32)1) :
              (uint32)((uint32)timeoutFloat);
    return timeout;
}
#endif /* CAN_ENABLE_TIMEOUT_AS_LOOP */

/*!
* @brief    Get a standard filter element address
*
* @param[in] StandardFilterListStartAddr  Standard filter list start address
* @param[in] filterIndex              Index of the filter element
*
* @retval Can_FilterStandardEleType*   Pointer to the standard filter element
*/
LOCAL_INLINE FUNC(Can_FilterStandardEleType*, CAN_CODE) Can_Hw_GetStandardFilterEleAddr(
    CONST(uint32, AUTOMATIC) StandardFilterListStartAddr, CONST(uint8, AUTOMATIC) filterIndex)
{
    VAR(uint32, AUTOMATIC) standardFilterEleAddr = 0U;

    standardFilterEleAddr = StandardFilterListStartAddr + 
        (uint32)(filterIndex * (uint32)CAN_STANDARD_FILTER_ELE_SIZE_U32);

    return (Can_FilterStandardEleType*)standardFilterEleAddr;
}

/*!
* @brief    Initialize a standard filter element
*
* @param[in] FilterElePtr Pointer to filter element
*
*/
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_InitStandardFilterEle(P2CONST(Can_FilterEleType, AUTOMATIC, CAN_APPL_CONST) FilterElePtr)
{
    P2VAR(volatile Can_FilterStandardEleType, AUTOMATIC, CAN_APPL_DATA) standardFilterElePtr = NULL_PTR;
    VAR(volatile Can_FilterStandardEleType, AUTOMATIC) standardFilterEleTemp = {0U};

    /* Get the standard filter element address/pointer */
    standardFilterElePtr = Can_Hw_GetStandardFilterEleAddr(
        g_canConfigPtr->msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_STD_FILTERS],
        FilterElePtr->filterIndex);
    
    /* Initialize filter element */
    if(CAN_FILTER_ELE_COFIG_STORE_RX_BUF != FilterElePtr->elementConfig)
    {
        /* Set the SFID2[10:0] as a standard id */
        standardFilterEleTemp.sfid2 =  FilterElePtr->id2;
    }
    else
    {
        /* Set the SFID2[10:0] as a Rx buffer id */
        standardFilterEleTemp.sfid2 =  (uint32)FilterElePtr->rxBufferOffset;
    }

    /* Set the SFID1[26:16] as a standard id */
    standardFilterEleTemp.sfid1 = FilterElePtr->id1;
    /* Set the filter element configuration:SFEC[29:27] */
    standardFilterEleTemp.sfec = (uint32)FilterElePtr->elementConfig;
    /* Set the filter action:SFT[31:30] */
    standardFilterEleTemp.sft = (uint32)FilterElePtr->filterAction;

    /* Write to the hardware RAM */
    *standardFilterElePtr = standardFilterEleTemp;
}

/*!
* @brief    Get a extended filter element address
*
* @param[in] ExtendedFilterListStartAddr  Extended filter list start address
* @param[in] filterIndex              Index of the filter element
*
* @retval Can_FilterExtendedEleType*   Pointer to the extended filter element
*/
LOCAL_INLINE FUNC(Can_FilterExtendedEleType*, CAN_CODE) Can_Hw_GetExtendedFilterEleAddr(
    CONST(uint32, AUTOMATIC) ExtendedFilterListStartAddr, CONST(uint8, AUTOMATIC) filterIndex)
{
    VAR(uint32, AUTOMATIC) extendedFilterEleAddr = 0U;

    extendedFilterEleAddr = ExtendedFilterListStartAddr + 
        (uint32)(filterIndex * (uint32)CAN_EXTENDED_FILTER_ELE_SIZE_U32);

    return (Can_FilterExtendedEleType*)extendedFilterEleAddr;
}

/*!
* @brief    Initialize a extended filter element
*
* @param[in] FilterElePtr Pointer to filter element
*
*/
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_InitExtendedFilterEle(P2CONST(Can_FilterEleType, AUTOMATIC, CAN_APPL_CONST) FilterElePtr)
{
    P2VAR(volatile Can_FilterExtendedEleType, AUTOMATIC, CAN_APPL_DATA) extendedFilterElePtr = NULL_PTR;
    VAR(volatile Can_FilterExtendedEleType, AUTOMATIC) externFilterEleTemp = {0U};

    /* Get the standard filter element address/pointer */
    extendedFilterElePtr = Can_Hw_GetExtendedFilterEleAddr(
        g_canConfigPtr->msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_EXT_FILTERS],
        FilterElePtr->filterIndex);
    
    /* Initialize filter element */
    if(CAN_FILTER_ELE_COFIG_STORE_RX_BUF != FilterElePtr->elementConfig)
    {
        /* Set the EFID2[28:0] as a standard id */
        externFilterEleTemp.filterExtEle1.efid2 =  FilterElePtr->id2;
    }
    else
    {
        /* Set the EFID2[28:0] as a Rx buffer id */
        externFilterEleTemp.filterExtEle1.efid2 =  (uint32)FilterElePtr->rxBufferOffset;
    }

    /* Set the EFID1[28:0] as a standard id */
    externFilterEleTemp.filterExtEle0.efid1 = FilterElePtr->id1;
    /* Set the filter element configuration:EFEC[31:29] */
    externFilterEleTemp.filterExtEle0.efec = (uint32)FilterElePtr->elementConfig;
    /* Set the filter action:EFT[31:30] */
    externFilterEleTemp.filterExtEle1.eft = (uint32)FilterElePtr->filterAction;

    /* Write to the hardware RAM */
    *extendedFilterElePtr = externFilterEleTemp;
}

/*!
* @brief    Clear the Rx Buffer New Data flag
*
* @param[in]    HwOffset  Controller hardware offset
*/
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_ClrRxBufNewDataFlg(CONST(uint8, CAN_CONST) HwOffset)
{
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_DATA) msgRamConfigPtr = (g_canConfigPtr->msgRamConfigPtr);
    
    /* Check if has Rx Buffer */
    if(msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_BUFFERS] > 0U)
    {
        /* Clear all Rx Buffer New Data flags */
        REG_WRITE32(CAN_NDAT1_REG_ADDR(HwOffset), 0xFFFFFFFFU);
        REG_WRITE32(CAN_NDAT2_REG_ADDR(HwOffset), 0xFFFFFFFFU);
    }
    else
    {
        /* Intentionally Empty */
    }
}

#if (STD_ON == CAN_RXFIFO_ENABLE)
/*!
* @brief    Clear the Rx FIFO 0 data
*
* @param[in]    HwOffset  Controller hardware offset
*/
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_ClrRxFifo0Data(CONST(uint8, CAN_CONST) HwOffset)
{
    VAR(uint32, AUTOMATIC) fifoSize = 0;
    VAR(uint32, AUTOMATIC) dataCnt = 0;
    VAR(uint32, AUTOMATIC) circleCnt = 0;
    VAR(uint32, AUTOMATIC) readIncex = 0;

    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_DATA) msgRamConfigPtr = g_canConfigPtr->msgRamConfigPtr;
    
    /* Check if has Rx Buffer */
    if(msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_FIFO0] > 0U)
    {
        /* Get the fifo 0 size */
        fifoSize = msgRamConfigPtr->rxFIFO0Size;
        /* Get the data count in the fifo 0 */
        dataCnt = REG_READ32(CAN_RXF0S_REG_ADDR(HwOffset)) & CAN_RXF0S_F0FL_MASK;
        /* Clear all Rx Buffer New Data flags */
        while((dataCnt > (uint32)0) && (circleCnt < fifoSize))
        {
            /* Release the fifo 0 output mailbox */
            readIncex = (REG_READ32(CAN_RXF0S_REG_ADDR(HwOffset)) & CAN_RXF0S_F0GI_MASK) >> CAN_RXF0S_F0GI_SHIFT;
            /* Set the F0AI to the read index to release the mailbox */
            REG_WRITE32(CAN_RXF0A_REG_ADDR(HwOffset), readIncex);
            /* Get the data count in the fifo 0 */
            dataCnt = REG_READ32(CAN_RXF0S_REG_ADDR(HwOffset)) & CAN_RXF0S_F0FL_MASK;
            circleCnt++;
        }
    }
    else
    {
        /* Intentionally Empty */
    }
}

/*!
* @brief    Clear the Rx FIFO 1 data
*/
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_ClrRxFifo1Data(CONST(uint8, CAN_CONST) HwOffset)
{
    VAR(uint32, AUTOMATIC) fifoSize = 0;
    VAR(uint32, AUTOMATIC) dataCnt = 0;
    VAR(uint32, AUTOMATIC) circleCnt = 0;
    VAR(uint32, AUTOMATIC) readIncex = 0;

    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_DATA) msgRamConfigPtr = g_canConfigPtr->msgRamConfigPtr;
    
    /* Check if has Rx Buffer */
    if(msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_FIFO1] > 0U)
    {
        /* Get the fifo 1 size */
        fifoSize = msgRamConfigPtr->rxFIFO1Size;
        /* Get the data count in the fifo 1 */
        dataCnt = REG_READ32(CAN_RXF1S_REG_ADDR(HwOffset)) & CAN_RXF1S_F1FL_MASK;
        /* Clear all Rx Buffer New Data flags */
        while((dataCnt > (uint32)0) && (circleCnt < fifoSize))
        {
            /* Release the fifo 1 output mailbox */
            readIncex = (REG_READ32(CAN_RXF1S_REG_ADDR(HwOffset)) & CAN_RXF1S_F1GI_MASK) >> CAN_RXF1S_F1GI_SHIFT;
            /* Set the F0AI to the read index to release the mailbox */
            REG_WRITE32(CAN_RXF1A_REG_ADDR(HwOffset), readIncex);
            /* Get the data count in the fifo 1 */
            dataCnt = REG_READ32(CAN_RXF1S_REG_ADDR(HwOffset)) & CAN_RXF1S_F1FL_MASK;
            circleCnt++;
        }
    }
    else
    {
        /* Intentionally Empty */
    }
}
#endif /* STD_ON == CAN_RXFIFO_ENABLE */

/*!
* @brief    Check for next available transmit Queue slot
* @param[in]    Controller      Index of the controller
* 
* @retval   uint8   Next available transmit Queue slot index, 0xFF means no slot available
*/
LOCAL_INLINE FUNC(uint8, CAN_CODE) Can_Hw_CheckQueueMask(CONST(uint8, AUTOMATIC) Controller)
{
    VAR(uint32, AUTOMATIC) canTxIndex = 0U;
    VAR(uint8, AUTOMATIC) slotValue = 0xFF;
    VAR(uint32, AUTOMATIC) canSlotmask = 0U;
    
    VAR(uint32, AUTOMATIC) txTempbuffReg = 0U;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    
    txTempbuffReg = REG_READ32(CAN_TXBC_REG_ADDR(hwOffset));
    
    /* Check for slot in Queue */
    for(canTxIndex = (uint32)((txTempbuffReg & CAN_TXBC_NDTB_MASK) >> CAN_TXBC_NDTB_SHIFT); canTxIndex < ((uint32)
          ((uint32)((txTempbuffReg & CAN_TXBC_NDTB_MASK) >> CAN_TXBC_NDTB_SHIFT) + 
           (uint32)((txTempbuffReg & CAN_TXBC_TFQS_MASK) >> CAN_TXBC_TFQS_SHIFT))); canTxIndex++)
    {
        canSlotmask = ((uint32)1U << canTxIndex);
        /* Check if Tx Queue slot available */
        if((((g_canControllerStatus[Controller].txMask) & canSlotmask) == canSlotmask) && 
            (CAN_TXBRP_TRP_MASK(canTxIndex) != (REG_BIT_GET32(CAN_TXBRP_REG_ADDR(hwOffset), 
             CAN_TXBRP_TRP_MASK(canTxIndex)))))
        {
            slotValue = (uint8) canTxIndex;
            break;
        }
        else
        {
            /* nothing */
        }
    }
    
    return slotValue;
}

#if(STD_ON == CAN_PUBLIC_ICOM_ENABLE)
/*!
* @brief    Check for Greater/Smaller operation
* @param[in]    ValData      Value data to be compared
* @param[in]    ConfigData   Configured data to be compared
* @param[in]    SignalOperType   Signal operation type
* @param[out]   CheckVal     Pointer to the check value
* 
* @retval   Std_ReturnType   E_OK: Condition met, E_NOT_OK: Condition not met
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE)  Can_Hw_IcomCheckGreaterSmaller(
    CONST(uint8, AUTOMATIC) ValData, CONST(uint8, AUTOMATIC) ConfigData,
    CONSTP2VAR(uint8, AUTOMATIC, CAN_APPL_DATA) CheckVal, 
    CONST(Can_IcomSignalOperType, AUTOMATIC) SignalOperType)
{
    /* API return status */
    VAR(Std_ReturnType, AUTOMATIC) apiStatus = E_NOT_OK;
    
    /* Check SignalOperType is Greater */
    if(CAN_ICOM_OPER_GREATER == SignalOperType)
    {
        /* Data in is lesser than compare value */
        if (ValData < ConfigData)
        {
            apiStatus = E_NOT_OK;
        }
        /* Data in is greater than compare value */
        else if (ValData > ConfigData)
        {
            apiStatus = E_OK;
            (*CheckVal)++;
        }
        else
        {
            /* Do Nothing */
        }
    }
    /* Check SignalOperType is Smaller */
    else
    {
        /* Verify the signal value and masked payload data */
        if (ValData > ConfigData)
        {
            apiStatus = E_NOT_OK;
        }
        /* Data in is lesser than compare value */
        else if (ValData < ConfigData)
        {
            apiStatus = E_OK;
            (*CheckVal)++;
        }
        else
        {
            /* Do Nothing */
        }
    }

    return apiStatus;
}

/*!
* @brief    Validate the ICOM message signals
* @param[in]    MessageIndex      Index of the ICOM message
* @param[in]    PduInfoPtr    Pointer to Pdu Info structure
* 
* @retval   Std_ReturnType   E_OK: Message is valid, E_NOT_OK: Message is invalid
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE)  Can_Hw_IcomValidateMsgSignal(
    CONST(uint16, AUTOMATIC) MessageIndex,
    CONSTP2CONST(PduInfoType, AUTOMATIC, CAN_APPL_DATA) PduInfoPtr)
{
    VAR(uint32, AUTOMATIC) signalIndex = 0U;
    VAR(uint16, AUTOMATIC) firstSignalIndex = 0U;
    VAR(uint16, AUTOMATIC) noOfMsgSignal = 0U;
    VAR(uint8, AUTOMATIC) msgCtr = 0U;
    VAR(uint8, AUTOMATIC) dataIndex = 0U;
    VAR(uint8, AUTOMATIC) dataCnt = 0U;
    VAR(uint8, AUTOMATIC) checkIndex = 0U;
    VAR(uint8, AUTOMATIC) tempData[8] = {0};
    P2VAR(uint8, CAN_CONST, CAN_APPL_CONST) checkIndexPtr = NULL_PTR;
    VAR(Std_ReturnType, AUTOMATIC) apiStatus = E_NOT_OK;
    P2CONST(Can_IcomConfigType, CAN_CONST, CAN_APPL_CONST) tempIcomConfigPtr = g_canStaticConfigPtr->icomConfigPtr;

    /* Initialize the temporary array */
    for(dataIndex = 0U; dataIndex < 8U; dataIndex++)
    {
        tempData[dataIndex] = 0U;
    }
    
    /* First signal index */
    firstSignalIndex = tempIcomConfigPtr->icomMsgConfigPtr[MessageIndex].icomFirstSignalIndx;
    /* No of signal configuration */
    noOfMsgSignal = tempIcomConfigPtr->icomMsgConfigPtr[MessageIndex].icomNoOfSignalIndx;
    /* Number of bytes to be checked */
    msgCtr = tempIcomConfigPtr->icomMsgConfigPtr[MessageIndex].icomDLC;
    
    /* Message signal validation */
    for (signalIndex = firstSignalIndex; signalIndex <
         ((uint32)firstSignalIndex + (uint32)noOfMsgSignal); signalIndex++)
    {
        /*Initialize check index */
        checkIndex = 0U;
        checkIndexPtr = &checkIndex;
        dataCnt = msgCtr;
        
        /* Reception of messages for configured n times:
         * If a byte of message is not matching, the message is invalidated
         */
        while(0U != dataCnt)
        {
            dataCnt--;
            dataIndex = dataCnt;
            /* Mask the received payload and signal mask value */
            tempData[dataIndex] = (PduInfoPtr->SduDataPtr[dataIndex] \
                                   & (tempIcomConfigPtr->icomRxSignalConfigPtr[signalIndex]. \
                                      icomSignalMask[dataIndex]));
            /* Get the Signal operation */
            switch(tempIcomConfigPtr->icomRxSignalConfigPtr[signalIndex].icomSignalOper)
            {
                /* The ICOM signal operation is AND */
                case CAN_ICOM_OPER_AND:
                {
                    /* Verify the signal value and masked payload data */
                    if (0U != (tempData[dataIndex] & \
                                               (tempIcomConfigPtr->icomRxSignalConfigPtr[signalIndex]. \
                                                icomSignalValue[dataIndex])))
                    {
                        checkIndex++;
                    }
                    else
                    {
                        /* Reset the data count and set status not ok */
                        dataCnt = 0;
                        apiStatus = E_NOT_OK;
                    }
                    
                    if(msgCtr == checkIndex)
                    {
                        /* All bytes are validated */
                        apiStatus = E_OK;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                break;
                /* Verify the signal value and masked payload data */
                case CAN_ICOM_OPER_EQUAL:
                {
                    /* Verify the signal value and masked payload data */
                    if (tempData[dataIndex] == \
                        (tempIcomConfigPtr->icomRxSignalConfigPtr[signalIndex]. \
                         icomSignalValue[dataIndex]))
                    {
                        checkIndex++;
                    }
                    else
                    {
                        /* Reset the data count and set status not ok */
                        dataCnt = 0;
                        apiStatus = E_NOT_OK;
                    }
                    
                    if(checkIndex == msgCtr)
                    {
                        /* All bytes are validated */
                        apiStatus = E_OK;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                break;
                /* The ICOM signal operation is Greater */
                case CAN_ICOM_OPER_GREATER:
                {
                    apiStatus = Can_Hw_IcomCheckGreaterSmaller(tempData[dataIndex], 
                                 (tempIcomConfigPtr->icomRxSignalConfigPtr[signalIndex].icomSignalValue[dataIndex]),
                                 checkIndexPtr, CAN_ICOM_OPER_GREATER);
                
                    if(E_NOT_OK == apiStatus)
                    {
                        /* Reset the data count */
                        dataCnt = 0;
                        apiStatus = E_NOT_OK;
                    }
                    else if(msgCtr == checkIndex)
                    {
                        /* All bytes are validated */
                        apiStatus = E_OK;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                break;
                /* The ICOM signal operation is Smaller */
                case CAN_ICOM_OPER_SMALLER:
                {
                
                    apiStatus = Can_Hw_IcomCheckGreaterSmaller(tempData[dataIndex],
                                 (tempIcomConfigPtr->icomRxSignalConfigPtr[signalIndex].icomSignalValue[dataIndex]),
                                 checkIndexPtr, CAN_ICOM_OPER_SMALLER);
                    
                    if(E_NOT_OK == apiStatus)
                    {
                        /* Reset the data count */
                        dataCnt = 0;
                        apiStatus = E_NOT_OK;
                    }
                    else if(msgCtr == checkIndex)
                    {
                        /* All bytes are validated */
                        apiStatus = E_OK;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                break;
                default:
                {
                    /* signal value and data when NORed if gives valid value */
                    if (0U != (tempData[dataIndex] ^ \
                                               tempIcomConfigPtr->icomRxSignalConfigPtr[signalIndex]. \
                                               icomSignalValue[dataIndex]))
                    {
                        checkIndex++;
                    }
                    else
                    {
                        /* Reset the data count and set status not ok */
                        dataCnt = 0;
                        apiStatus = E_NOT_OK;
                    }
                    
                    if(checkIndex == msgCtr)
                    {
                        /* All bytes are validated */
                        apiStatus = E_OK;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                break;
            }
        }

        if(E_OK ==  apiStatus)
        {
            /* Message is valid, exit from loop */
            break;
        }
        else
        {
            /* Intentionally Empty */
        }
    }
    
    return apiStatus;
}

/*!
* @brief    This function is used for ICOM message validation
* @param[in]    MailboxPtr    Pointer to the CAN hardware mailbox
* @param[in]    PduInfoPtr    Pointer to the PDU info structure
* 
*/
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_IcomValidateMsg(CONSTP2CONST(Can_HwType, AUTOMATIC, CAN_APPL_DATA) MailboxPtr,
    CONSTP2CONST(PduInfoType, AUTOMATIC, CAN_APPL_DATA) PduInfoPtr)
{
    VAR(Can_IdType, AUTOMATIC) icomRxMsgId = 0U;
    VAR(Can_IdType, AUTOMATIC) icomCheckMsgId = 0U;
    VAR(uint16, AUTOMATIC) icomMsgIndex = 0U;
    VAR(uint16, AUTOMATIC) msgIndex = 0U;
    VAR(uint8, AUTOMATIC) icomIndex = 0U;
    VAR(uint16, AUTOMATIC) icomNoOfRxMsg = 0U;
    VAR(uint8, AUTOMATIC) controllerId = 0U;
    VAR(Std_ReturnType, AUTOMATIC) apiStatus = E_NOT_OK;
    VAR(Std_ReturnType, AUTOMATIC) rxIndicationStatus = E_NOT_OK;
    P2CONST(Can_IcomConfigType, CAN_CONST, CAN_APPL_CONST) tempIcomConfigPtr = g_canStaticConfigPtr->icomConfigPtr;

    /* Set with Controller Configuration Id */
    controllerId = MailboxPtr->ControllerId;

    /* Get the first receive configuration index */
    while (icomIndex < tempIcomConfigPtr->icomConfigsCount)
    {
        if (controllerId ==
            (uint8)(tempIcomConfigPtr->icomSetConfigPtr[icomIndex].icomConfigId))
        {
            /* Get the first receive configuration index */
            icomMsgIndex = tempIcomConfigPtr->icomSetConfigPtr[icomIndex].icomFirstMsgIndx;
            /* Get the total number of ICOM Receive messages configured*/
            icomNoOfRxMsg = tempIcomConfigPtr->icomSetConfigPtr[icomIndex].icomNoOfMsgIndx;
            break;
        }
        else
        {
            /* nothing */
        }
        icomIndex++;
    }

    /* Set with First index value */
    msgIndex = icomMsgIndex;
    while(msgIndex < (icomMsgIndex + icomNoOfRxMsg))
    {
        /* Set with Icom Rx message Id */
        icomRxMsgId = MailboxPtr->CanId & ~(CAN_ID_IDE_U32);
        /* check if icomMaskRef is configured */
        if(0U != tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomMaskRef)
        {
            /* Mask the received message ID with the ICOM Message Id mask */
            icomRxMsgId &= (tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomMaskRef);
            icomCheckMsgId = (tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomMsgId &\
                              tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomMaskRef);
        }
        else
        {
            icomCheckMsgId = tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomMsgId;
        }
        
        /* Compare Masked id with configured Id */
        if(icomRxMsgId == icomCheckMsgId)
        {
            /* Compare payload length(DLC)and if mismatch set as wake-up */
            if( PduInfoPtr->SduLength == tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomDLC)
            {
                rxIndicationStatus = E_OK;
                apiStatus = E_OK;
            }
            else
            {
                /* Check payload length error is configured */
                /* Set Status as Wakeup condition cause */
                if((boolean)TRUE == tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomLengthErr)
                {
                    rxIndicationStatus = E_OK;
                    apiStatus = E_NOT_OK;
                }
                else
                {
                    apiStatus = E_NOT_OK;
                    rxIndicationStatus = E_NOT_OK;
                }
            }
        
            /* Check if signal/data comparison is required */
            if ((E_OK == apiStatus) && (0U != \
                                        tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomNoOfSignalIndx))
            {
                /* Invoke function for Message signal validation */
                apiStatus = Can_Hw_IcomValidateMsgSignal(msgIndex, PduInfoPtr);
                rxIndicationStatus = apiStatus;
            }
            else
            {
                /* nothing */
            }
            
            /* Check counter value is configured or not */
            if((E_OK == apiStatus) && (0U != \
                                       tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomCntrVal))
            {
                SchM_Enter_Can_CAN_CRITICAL_SECTION0();
                /* Increment Message Counter Value */
                g_canControllerStatus[controllerId].icomMsgCntrValPtr[msgIndex]++;
                /* Check if the message with the ID is received n times on the
                communication channel. */
                if(tempIcomConfigPtr->icomMsgConfigPtr[msgIndex].icomCntrVal == 
                    g_canControllerStatus[controllerId].icomMsgCntrValPtr[msgIndex])
                {
                    /* Set Status as Wakeup condition cause */
                    rxIndicationStatus = E_OK;
                    g_canControllerStatus[controllerId].icomMsgCntrValPtr[msgIndex] = 0U;
                }
                else
                {
                    /* reset Wake up cause till counter value matches */
                    rxIndicationStatus = E_NOT_OK;
                }
                SchM_Exit_Can_CAN_CRITICAL_SECTION0();
            }
            else
            {
                /* nothing */
            }
            
            /* Set Exit condition if Wakeup Cause is enabled */
            if(E_OK == rxIndicationStatus)
            {
                /* Call CanIf_RxIndication received message matches the wakeup */
                CanIf_RxIndication(MailboxPtr, PduInfoPtr);
                /* Set Exit Condition */
                msgIndex = (icomMsgIndex + icomNoOfRxMsg);
            }
            else
            {
                /* nothing */
            }
        }
        else
        {
            /* nothing */
        }
        /* Increment to point next Message configuration*/
        msgIndex++;
    }
}
#endif

#if (STD_ON == CAN_TRIGGER_TRANSMIT_ENABLE)
/*!
* @brief    Update the PduInfo with CanIf_TriggerTransmit API
* @param[in]    MbGlobalIndex     Index of the Mailbox in global Mailbox array
* @param[in]    TempPduInfoPtr    Pointer to temporary PduInfo structure
* @param[in]    PduInfoPtr        Pointer to original PduInfo structure
* 
* @retval   Std_ReturnType   E_OK: TriggerTransmit successful, E_NOT_OK: TriggerTransmit failed
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_UpdatePduInfo(
    VAR(uint16, AUTOMATIC) MbGlobalIndex,
    CONSTP2VAR(Can_PduType, AUTOMATIC, CAN_APPL_DATA) TempPduInfoPtr, 
    CONSTP2CONST(Can_PduType, AUTOMATIC, CAN_APPL_DATA) PduInfoPtr)
{
    /* PduInfoType structure variable */
    VAR(PduInfoType, AUTOMATIC) pduInfoTrigger = 0;
    P2VAR(PduInfoType, AUTOMATIC, CAN_APPL_DATA) writePduInfoPtr = NULL_PTR;
    P2CONST(Can_TxMbConfigType, AUTOMATIC, CAN_APPL_CONST) txMbObjPtr = NULL_PTR;
    VAR(uint8, AUTOMATIC) triggerStatus = 0u;
    VAR(Std_ReturnType, AUTOMATIC) result = E_OK;

    /* Set with TX object configuration start index */
    txMbObjPtr = g_canConfigPtr->txMbConfigContainerPtr->txMbConfigPtr;
    /* initialize Pointers PduInfoPtr and TempPduInfo */
    writePduInfoPtr = &pduInfoTrigger;
    /* Check Trigger Transmit is Enabled */
    if(TRUE == txMbObjPtr[MbGlobalIndex].trigTxStatus)
    {
        /*Store Data pointer and Data length*/
        writePduInfoPtr->SduDataPtr = PduInfoPtr->sdu;
        writePduInfoPtr->SduLength =  (uint8)(PduInfoPtr->length);
        /* CanIf_TriggerTransmit() to acquire the PDUs data */
        triggerStatus = CanIf_TriggerTransmit(PduInfoPtr->swPduHandle, writePduInfoPtr);
        /* Check Trigger Status */
        if(E_NOT_OK != triggerStatus)
        {
            /*Store the updated Data pointer and Data length*/
            TempPduInfoPtr->sdu = writePduInfoPtr->SduDataPtr;
            TempPduInfoPtr->length = (uint8)(writePduInfoPtr->SduLength);
        }
        else
        {
            /* Set value with NOT OK */
            result = E_NOT_OK;
        }
    }
    else
    {
        /*Store the Data pointer and Data length*/
        TempPduInfoPtr->sdu = PduInfoPtr->sdu;
        TempPduInfoPtr->length = PduInfoPtr->length;
    }

    return result;
}
#endif

/*!
* @brief    Extract the received message data from the CAN controller Rx buffer/FIFO
* @param[in]    Controller     Index of the controller
* @param[in]    RxBuffIndex    Index of the Rx buffer/FIFO
* @param[in]    RxBufferType   Type of the Rx buffer/FIFO
* 
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_RxExtractData(CONST(uint8, AUTOMATIC) Controller,
    CONST(uint8, AUTOMATIC) RxBuffIndex, CONST(Can_RxDataCheckType, AUTOMATIC) RxBufferType, 
    CONST(Can_HwHandleType, AUTOMATIC) MbHrh)
{
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_DATA) msgRamCfgPtr = g_canConfigPtr->msgRamConfigPtr;
    P2CONST(volatile Can_RxMsgType, AUTOMATIC, CAN_APPL_DATA) rxMsgRAMPtr = NULL_PTR;
    VAR(Can_HwType, AUTOMATIC) rxMailBoxInfo = {0};
    VAR(PduInfoType, AUTOMATIC) rxPduInfo = {0};
    VAR(volatile uint32, AUTOMATIC) rxReadStartAddr = 0U;
    VAR(uint32, AUTOMATIC) rxReadOffsetAddr = 0U;
    VAR(uint8, AUTOMATIC) regDataSize = 0U;
    VAR(uint8, AUTOMATIC) rxMsgDLC = 0U;
    VAR(uint8, AUTOMATIC)  rxMsgCnt = 0U;
    VAR(uint32, AUTOMATIC) rxMsgId = 0U;
#if (STD_ON == CAN_ENABLE_FD_MODE)
    VAR(uint8, AUTOMATIC) canRxMessageData[CAN_MAX_FD_DATA_LENGTH] = {0};
#else
    VAR(uint8, AUTOMATIC) canRxMessageData[CAN_MAX_DATA_LENGTH] = {0};
#endif
#if (STD_ON == CAN_ENABLE_LPDU_NOTIFICATION)
    VAR(boolean, AUTOMATIC) retVal = FALSE;
#endif
    VAR(Std_ReturnType, AUTOMATIC) result = E_OK;

#if (STD_ON == CAN_RXFIFO_ENABLE)
    /* Check requested buffer type */
    if(CAN_RX_DATA_CHECK_FIFO0 == RxBufferType)
    {
        /* Read Rx Message RAM start address of RXFIFO0 */
        rxReadStartAddr = msgRamCfgPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_FIFO0];
        regDataSize = (uint8)g_canConfigPtr->rxConfigPtr->rxFifo0DataFieldSize;
    }
    else if(CAN_RX_DATA_CHECK_FIFO1 == RxBufferType)
    {
        /* Read Rx Message RAM start address of RXFIFO1 */
        rxReadStartAddr = msgRamCfgPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_FIFO1];
        regDataSize = (uint8)g_canConfigPtr->rxConfigPtr->rxFifo1DataFieldSize;
    }
    else
#endif
    {
        /* Read Rx Message RAM start address of dedicated buffer */
        rxReadStartAddr = msgRamCfgPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_BUFFERS];
        regDataSize = (uint8)g_canConfigPtr->rxConfigPtr->rxBufferDataFieldSize;
    }

    /* Start Address value is not 0 and find the MB */
    if(0U != rxReadStartAddr)
    {
        /* Calculate the offset address of the Rx buffer/FIFO */
        rxReadOffsetAddr = RxBuffIndex;

        /* Load the data receive message buffer address */
        rxReadStartAddr = rxReadStartAddr + (uint32)(rxReadOffsetAddr * 
            (CAN_MSG_RAM_ELEMENT_HEAD_SIZE + (uint32)Can_DataRegionRegValToByteSize[regDataSize]));
    
        /* The pointer cast is used to cast the address of Dedicated Rx buffer Type to the Rx buffer elements structure
        type */
        rxMsgRAMPtr = (volatile Can_RxMsgType*) rxReadStartAddr;
        /* Extract DLC information */
        rxMsgDLC = rxMsgRAMPtr->rxMsgR1.dlc;
        
        /* Extract receive Msg.ID and ID Type */
        if (0U == rxMsgRAMPtr->rxMsgR0.xtd)
        {
          /* Read received message Id and Message type */
          rxMsgId = rxMsgRAMPtr->rxMsgR0.id >> CAN_MSG_STANDARD_ID_SHIFT_EIGHTEEN;
        }
        else
        {
          /* Set message ID type as extended and extract the message ID */
          rxMsgId = CAN_ID_IDE_U32;
          /* Copy message ID  */
          rxMsgId |= (Can_IdType)rxMsgRAMPtr->rxMsgR0.id;
        }
    
        /* Read receive data information from R1 RAM element */
#if (STD_ON == CAN_ENABLE_FD_MODE)
        if((uint8)CAN_BIT_SET == rxMsgRAMPtr->rxMsgR1.fdf)
        {
            /* Set FD bit of MsgId */
            rxMsgId |= (Can_IdType)CAN_ID_FD_DESCRIPTOR;
        }
        else
        {
            /* nothing */
        }
#endif

        /* Clear to read from Byte0 */
        rxMsgCnt = 0U;

#if (STD_ON == CAN_ENABLE_FD_MODE)
        /* Convert DLC length to Number of Data Bytes supported by Hw */
        rxMsgDLC = Can_GblFdDlcConvDb[rxMsgDLC];
#endif

        /* Copy Message from RAM section to local data buffer */
        while(rxMsgCnt < rxMsgDLC)
        {
            /* copy data from byte0 to n the buffer */
            canRxMessageData[rxMsgCnt] = rxMsgRAMPtr->rxMsgDb[rxMsgCnt].db;
            /* Increment to point next byte */
            rxMsgCnt++;
        }
        /* Call CanIf_RxIndication function with receive message information */
        rxMailBoxInfo.CanId = rxMsgId;
        rxMailBoxInfo.ControllerId = Controller;
        rxPduInfo.SduLength = rxMsgDLC;
        rxMailBoxInfo.Hoh = MbHrh;
        rxPduInfo.SduDataPtr = &canRxMessageData[0];

/* CAN public ICOM support is enabled */
#if(STD_ON == CAN_PUBLIC_ICOM_ENABLE)
        /* Check ICOM enabled */
        if((boolean)TRUE == g_canControllerStatus[Controller].icomEnableStatus)
        {
            /* Call Message validate function */
            Can_Hw_IcomValidateMsg(&rxMailBoxInfo, &rxPduInfo);
        }
        else
#endif
        {
          /* Check CAN LPdu callout function configured */
#if (STD_ON == CAN_ENABLE_LPDU_NOTIFICATION)
            /* Call the LPDU callout function to check the return value */
            retVal = Can_LPduReceiveCalloutFunction((uint8)MbHrh, rxMsgId, rxMsgDLC, rxPduInfo.SduDataPtr);
            
            if((boolean)TRUE == retVal)
#endif
            {
                /* Notify to reception of message to CAN IF layer */
                CanIf_RxIndication(&rxMailBoxInfo, &rxPduInfo);
            }
#if (STD_ON == CAN_ENABLE_LPDU_NOTIFICATION)
            else
            {
                /* nothing */
            }
#endif
        }
    }
    else
    {
        result = E_NOT_OK;
    }

    return result;
}

#if (STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE)
/*!
* @brief     Transmit Handler function to process the transmitted messages
* @param[in]    CtrlIndex     Index of the controller
* @param[in]    SwObjIndx     Configured Software Object Index
* @param[in]    HthRefPeriods  Reference period of the HTH
* 
* @retval   Std_ReturnType   E_OK: Handler found for this period, 
*                            E_NOT_OK: No handler configured for this period
*/
static Std_ReturnType Can_Hw_PeriodCheckSwHandle(
    CONST(uint8, AUTOMATIC) CtrlIndex,
    const uint16 SwObjIndx, CONST(uint8, AUTOMATIC) HthRefPeriods)
{
    VAR(Std_ReturnType, AUTOMATIC) swObjFound = E_NOT_OK;
    VAR(uint8, AUTOMATIC) hwControllerId = 0U;
    VAR(uint8, AUTOMATIC) mailBoxIndx = 0U;
    VAR(uint16, AUTOMATIC) swObjIndxCalc = 0U;
    VAR(Can_HwHandleType, AUTOMATIC) txDedicatedCnt = 0U;
    VAR(uint32, AUTOMATIC) txSlotMask = 0U;
    VAR(PduIdType, AUTOMATIC) pduHandle = 0U;
    VAR(uint16, AUTOMATIC) circleCnt = 0U;
    VAR(uint8, AUTOMATIC) txQueueSize = 0U;
    VAR(Can_HwHandleType, AUTOMATIC) hthIndex = 0U;
    VAR(Can_TxBufModeType, AUTOMATIC) bufferType = CAN_TX_MODE_FIFO;

    P2CONST(Can_TxMbConfigsContainerType, AUTOMATIC, CAN_APPL_DATA) txMbCfgPtr = g_canConfigPtr->txMbConfigContainerPtr;
    /* Set pointer variable with Message RAM Configuration structure */
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_DATA) msgRamCfgPtr = g_canConfigPtr->msgRamConfigPtr;

    /* Read all the HTH status corresponding with period */
    while((circleCnt < txMbCfgPtr->txMbCount) && (E_NOT_OK == swObjFound))
    {
        /* Read Hw associated with HTH */
        hwControllerId = txMbCfgPtr->txMbConfigPtr[circleCnt].hwControllerId;
        /* Check If Controller Id is configured */
        if((hwControllerId == CtrlIndex) && 
           (HthRefPeriods == txMbCfgPtr->txMbConfigPtr[circleCnt].mainFunctionRwPeriodRef))
        {
            /* Read Mask value */
            mailBoxIndx = txMbCfgPtr->txMbConfigPtr[circleCnt].txBuffIndx;
            /* Retrive core specific Hth of the hardware object */
            bufferType = txMbCfgPtr->txMbConfigPtr[circleCnt].txBufferModeType;
            /* Check if buffer is dedicated buffer */
            if(CAN_TX_MODE_DEDICATE_BUF == bufferType)
            {
                /* Calculate Sw Obj Handle index */
                swObjIndxCalc = (uint16)(((uint16)hwControllerId * (uint16)CAN_NOOF_TX_HW_BUFF_AVAILABLE) + (uint16)mailBoxIndx);
                
                /* Check if calculated SW obj handle is same as configuredSW obj handle */
                if(SwObjIndx == swObjIndxCalc)
                {
                    /* Get Pdu Handle */
                    pduHandle = g_canControllerStatus[hwControllerId].swObjectHandle[SwObjIndx];
                    txSlotMask = ((uint32)1 << mailBoxIndx);
                    
                    /* Check if slot is valid Tx slot */
                    if((txSlotMask & (g_canControllerStatus[hwControllerId].backupTxMask)) == txSlotMask)
                    {
                        SchM_Enter_Can_CAN_CRITICAL_SECTION9();
                        
                        /* Release Tx Element */
                        g_canControllerStatus[hwControllerId].txMask |= txSlotMask;
                        
                        SchM_Exit_Can_CAN_CRITICAL_SECTION9();
                    }
                    else
                    {
                        /* nothing */
                    }
                    
                    /* Set with Exact PduHandle Stored Index value */
                    /* Call Transmission confirmation to upper-layer with L-PDU handle */
                    CanIf_TxConfirmation(pduHandle);
                    
                    /* handler configured for this period in the current core */
                    swObjFound = E_OK;
                }
                else
                {
                    /* nothing */
                }
            }
            else
            {
                txDedicatedCnt = msgRamCfgPtr->txDedBuffCount;
                txQueueSize = msgRamCfgPtr->txFifoQueueSize;
                hthIndex = txDedicatedCnt;
                /* Scan through Hth buffers used */
                while((hthIndex < (txDedicatedCnt + txQueueSize)) && \
                      (E_NOT_OK == swObjFound))
                {
                    /* Calculate Sw Obj Handle index */
                    swObjIndxCalc = (uint16)(((uint16)hwControllerId * \
                                              (uint16)CAN_NOOF_TX_HW_BUFF_AVAILABLE) + (uint16)hthIndex);
                    /* Check ifcalculated SW obj handle is same as configured SW obj handle */
                    if(SwObjIndx == swObjIndxCalc)
                    {
                        pduHandle = g_canControllerStatus[hwControllerId].swObjectHandle[SwObjIndx];
                        
                        txSlotMask = ((uint32)1U << hthIndex);
                        
                        /* Check if this element belong to Tx object */
                        if((txSlotMask & g_canControllerStatus[hwControllerId].backupTxMask) == txSlotMask)
                        {
                          SchM_Enter_Can_CAN_CRITICAL_SECTION10();
                        
                          /* Release Tx object Element */
                          g_canControllerStatus[hwControllerId].txMask |= txSlotMask;
                        
                          SchM_Exit_Can_CAN_CRITICAL_SECTION10();
                        }
                        else
                        {
                            /* nothing */
                        }
                        
                        /* Set with Exact PduHandle Stored Index value */
                        /* Call Transmission confirmation to upper-layer with L-PDU handle*/
                        CanIf_TxConfirmation(pduHandle);
                        
                        /* handler configured for this period in the current core */
                        swObjFound = E_OK;
                    }
                    else
                    {
                        /* nothing */
                    }
                    hthIndex++;
                }
            }
        }
        else
        {
            /* nothing */
        }
        circleCnt++;
    }

    return swObjFound;
}

/*!
* @brief    Transmit Event Handler function to process the transmitted events periodically
* @param[in]    Controller     Index of the controller
* @param[in]    PeriodRef      This value indicates the periodic reference
* 
*/
/*** @warning Can_Hw_c_MISRA_REF1 Analysis time of function 'Can_Hw_TxEventHandlerPeriodic' has exceeded the configured maximum: '15000ms'. 
     Dataflow analysis continues with the next function. */
LOCAL_INLINE FUNC(void, CAN_CODE) Can_Hw_TxEventHandlerPeriodic(CONST(uint8, AUTOMATIC) Controller, 
    CONST(uint8, AUTOMATIC) PeriodRef)
{
    /* Det check status */
    VAR(Std_ReturnType, AUTOMATIC) swObjFound = E_NOT_OK;
    volatile P2CONST(Can_TxEvtFifoEleType, AUTOMATIC, CAN_APPL_DATA) txEvntReadDataPtr = NULL_PTR;
    VAR(uint8, AUTOMATIC) txHandleIndx = 0U;
    VAR(uint32, AUTOMATIC) txEvntFIFOstartAddr = 0U;
    VAR(uint32, AUTOMATIC) txEvntFIFORealAddr = 0U;
    VAR(uint32, AUTOMATIC) txEvntFIFOGetIndex = 0U;
    VAR(uint8, AUTOMATIC) txEvntFillLvlVal = 0U;
    VAR(uint8, AUTOMATIC) loopExitFlag = 0U;
    VAR(uint16, AUTOMATIC) swObjIndx = 0U;
    VAR(uint8, AUTOMATIC) count2 = 0U;
    VAR(uint8, AUTOMATIC) count = 0U;
    VAR(uint8, AUTOMATIC) queueEleCount = 0U;

    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    /* Set pointer variable with Message RAM Configuration structure */
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_DATA) msgRamCfgPtr = g_canConfigPtr->msgRamConfigPtr;

    /* search through controller specific Tx buffer priority list */
    while(count < CAN_NOOF_TX_HW_BUFF_AVAILABLE)
    {
        /* retrive the Sw object handle for the current priority */
        swObjIndx = g_canControllerStatus[Controller].txSwObjPriorityPtr[count];
        /* Check If SwObj index is invalid */
        if(CAN_SWOBJECT_INVALID_VAL == swObjIndx)
        {
            /* Reset the message order count and stop mb scanning */
            count = (uint8)CAN_NOOF_TX_HW_BUFF_AVAILABLE;
        }
        else
        {
            /* Check if the sw object handle is configured for this period */
            swObjFound = Can_Hw_PeriodCheckSwHandle(Controller, \
                         swObjIndx, PeriodRef);
            
            if(E_OK == swObjFound)
            {
              /* Loop for total no of HW buffer */
              for(count2 = count; count2 < (CAN_NOOF_TX_HW_BUFF_AVAILABLE - 1U); count2++)
              {
                  g_canControllerStatus[Controller].txSwObjPriorityPtr[count2] =
                      g_canControllerStatus[Controller].txSwObjPriorityPtr[count2 + 1U];
                  g_canControllerStatus[Controller].txSwObjPriorityPtr[count2 + 1U] = 
                      CAN_SWOBJECT_INVALID_VAL;
              }
            }
            else
            {
                /* Reset the message order count */
                queueEleCount += 1U;
                count++;
            }
        }
    }
    
    /* Set Tx Event FIFO Start Address */
    txEvntFIFOstartAddr = msgRamCfgPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_TX_EVENT_FIFO];
    /* if LOST is raised as HW event */
    if(CAN_IR_TEFL_MASK == (REG_READ32(CAN_IR_REG_ADDR(hwOffset)) & CAN_IR_TEFL_MASK))
    {
    #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CAN_HW_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                      (uint8)CAN_SID_MAIN_MULTI_WRITE, (uint8)CAN_E_DATALOST);
    #endif
        /* Clear TEFN and TEFL flags as well if SET */
        REG_BIT_SET32(CAN_IR_REG_ADDR(hwOffset), CAN_IR_TEFL_MASK);
    }
    else
    {
        /* Do nothing */
    }
    
    /* Set safety loop exit flag with value zero */
    loopExitFlag = 0U;
    /* Read Fill Level value */
    txEvntFillLvlVal = (uint8)((REG_READ32(CAN_TXEFS_REG_ADDR(hwOffset)) & CAN_TXEFS_EFFL_MASK) >> CAN_TXEFS_EFFL_SHIFT);
    
    while((0U != txEvntFillLvlVal) && (CAN_NOOF_TX_HW_BUFF_AVAILABLE > loopExitFlag))
    {
        /* Read TxEvent buffer index */
        txEvntFIFOGetIndex = (REG_READ32(CAN_TXEFS_REG_ADDR(hwOffset)) & CAN_TXEFS_EFGI_MASK) >> CAN_TXEFS_EFGI_SHIFT;
        /* Set Real Event FIFO element address */
        txEvntFIFORealAddr = txEvntFIFOstartAddr + (txEvntFIFOGetIndex * (uint32)CAN_TX_EVT_FIFO_ELEMENT_SIZE_U32);
        
        /* Load EventFIFO element address */
        txEvntReadDataPtr = (volatile Can_TxEvtFifoEleType*)txEvntFIFORealAddr;
        /* Read Message Marker */
        txHandleIndx = (Can_HwHandleType)txEvntReadDataPtr->txEvtE1.mm;
        /* Calculate Sw Obj Handle index */
        swObjIndx = (uint16)((Controller * (uint16)CAN_NOOF_TX_HW_BUFF_AVAILABLE) + txHandleIndx);
        swObjFound = Can_Hw_PeriodCheckSwHandle(Controller, swObjIndx, PeriodRef);
        /* Check if Sw Obj Handle index is valid */
        if(E_OK != swObjFound)
        {
            g_canControllerStatus[Controller].txSwObjPriorityPtr[queueEleCount] = swObjIndx;
            queueEleCount += 1U;
        }
        else
        {
            /* Do nothing */
        }
        
        /* Acknowledge shall set to free the Tx Event FIFO */
        REG_WRITE32(CAN_TXEFA_REG_ADDR(hwOffset), txEvntFIFOGetIndex);
        /* Increment exit loop condition for safety */
        loopExitFlag++;
        /* Read Fill Level value */
        txEvntFillLvlVal = (uint8)((REG_READ32(CAN_TXEFS_REG_ADDR(hwOffset)) & CAN_TXEFS_EFFL_MASK) >> CAN_TXEFS_EFFL_SHIFT);
    }
}
#endif

/*!
* @brief    This function is used to find the valid Rx MB for the given buffer type and index
* @param[in]    CheckBuffType  This value indicates the buffer type to be checked
* @param[in]    RxBuffIndex    This value indicates the buffer index to be checked
* @param[out]   MbHrhPtr       Pointer to store the found MB/HRH handle
* @param[in]    PriodicCheck   This flag indicates whether periodic check is required
* @param[in]    PeriodRef      This value indicates the periodic reference
* 
*/
LOCAL_INLINE FUNC(Std_ReturnType, CAN_CODE) Can_Hw_FindValidRxMb(CONST(uint8, AUTOMATIC) Controller,
    CONST(Can_RxDataCheckType, AUTOMATIC) CheckBuffType,
    CONST(uint8, AUTOMATIC) RxBuffIndex, P2VAR(Can_HwHandleType, AUTOMATIC, CAN_APPL_DATA) MbHrhPtr, 
    CONST(boolean, AUTOMATIC) PriodicCheck, VAR(uint8, AUTOMATIC) PeriodRef)
{
    VAR(uint16, AUTOMATIC) mbGlobalIndex = 0U;
    VAR(Std_ReturnType, AUTOMATIC) findMbRes = (Std_ReturnType)E_NOT_OK;
    P2CONST(Can_RxMbConfigsContainerType,  AUTOMATIC, CAN_APPL_DATA) rxMbConfigContainerPtr = g_canConfigPtr->rxMbConfigContainerPtr;

    /* Loop through all configured Rx MBs, find the right configured MB */
    while (mbGlobalIndex < (uint16)rxMbConfigContainerPtr->rxMbCount)
    {
        if(Controller == rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].hwControllerId) 
        {
            if((CAN_RX_DATA_CHECK_DEDICATED_BUFFER == CheckBuffType) && 
                (RxBuffIndex == rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxBuffIndx))
            { 
                if((boolean)TRUE == PriodicCheck)
                {
                    if(PeriodRef == rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].mainFunctionRwPeriodRef)
                    {
                        /* Get the HRH/MB handle */
                        *MbHrhPtr = rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxHwObjId;
                        findMbRes = E_OK;
                        /* Refresh the mbGlobalIndex to jump the circle */
                        mbGlobalIndex = (uint16)rxMbConfigContainerPtr->rxMbCount;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                else
                {
                    /* Get the HRH/MB handle */
                    *MbHrhPtr = rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxHwObjId;
                    findMbRes = E_OK;
                    /* Refresh the mbGlobalIndex to jump the circle */
                    mbGlobalIndex = (uint16)rxMbConfigContainerPtr->rxMbCount;
                }
            }
        #if (STD_ON == CAN_RXFIFO_ENABLE)
            else if((CAN_RX_DATA_CHECK_FIFO0 == CheckBuffType) && 
                    (CAN_RX_FIFO0_BUF_INDEX == rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxBuffIndx))
            {
                if((boolean)TRUE == PriodicCheck)
                {
                    if(PeriodRef == rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].mainFunctionRwPeriodRef)
                    {
                        /* Get the HRH/MB handle */
                        *MbHrhPtr = rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxHwObjId;
                        findMbRes = E_OK;
                        /* Refresh the mbGlobalIndex to jump the circle */
                        mbGlobalIndex = (uint16)rxMbConfigContainerPtr->rxMbCount;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                else
                {
                    /* Get the HRH/MB handle */
                    *MbHrhPtr = rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxHwObjId;
                    findMbRes = E_OK;
                    /* Refresh the mbGlobalIndex to jump the circle */
                    mbGlobalIndex = (uint16)rxMbConfigContainerPtr->rxMbCount;
                }
            }
            else if((CAN_RX_DATA_CHECK_FIFO1 == CheckBuffType) && 
                    (CAN_RX_FIFO1_BUF_INDEX == rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxBuffIndx))
            {
                if((boolean)TRUE == PriodicCheck)
                {
                    if(PeriodRef == rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].mainFunctionRwPeriodRef)
                    {
                        /* Get the HRH/MB handle */
                        *MbHrhPtr = rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxHwObjId;
                        findMbRes = E_OK;
                        /* Refresh the mbGlobalIndex to jump the circle */
                        mbGlobalIndex = (uint16)rxMbConfigContainerPtr->rxMbCount;
                    }
                    else
                    {
                        /* Intentionally Empty */
                    }
                }
                else
                {
                    /* Get the HRH/MB handle */
                    *MbHrhPtr = rxMbConfigContainerPtr->rxMbConfigPtr[mbGlobalIndex].rxHwObjId;
                    findMbRes = E_OK;
                    /* Refresh the mbGlobalIndex to jump the circle */
                    mbGlobalIndex = (uint16)rxMbConfigContainerPtr->rxMbCount;
                }
            }
        #endif 
            else
            {
                /* Intentionally Empty */
            }
        }
        else
        {
            /* Intentionally Empty */
        }

        mbGlobalIndex++;
    }

    return findMbRes;
}

/*******************************************************************************
                            GLOBAL FUNCTIONS
*******************************************************************************/
/*!
* @brief    Activate pretended networking mode for the controller
*
* @param[in]    Controller      Index of the controller
* @param[in]    IcomConfigIndex Icom configuration index
*
* @retval   E_OK:       Operation was successful
* @retval   E_NOT_OK:   Operation was failed
*/
#if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetIcomConfig(
    CONST(uint8, AUTOMATIC) Controller,
    VAR(uint8, AUTOMATIC) IcomConfigIndex)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, AUTOMATIC) hwOffset = 0U;
    VAR(uint8, AUTOMATIC) circleCnt = 0U;

    P2VAR(Can_FilterStandardEleType, AUTOMATIC, CAN_APPL_DATA) standardFilterElePtr = NULL_PTR;
    P2VAR(Can_FilterExtendedEleType, AUTOMATIC, CAN_APPL_DATA) extendedFilterElePtr = NULL_PTR;
    P2CONST(Can_IcomConfigType, CAN_CONST, CAN_APPL_CONST) tempIcomConfigPtr = g_canStaticConfigPtr->icomConfigPtr;
    P2CONST(Can_FilterConfigType, CAN_CONST, CAN_APPL_CONST) filterConfigPtr = g_canConfigPtr->filterConfigPtr;

    hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    if ((Std_ReturnType)E_OK == Can_Hw_WaitEnterInitMode(hwOffset))
    {
        /* Check if Wakeup on bus off condition is configured */
        if ((boolean)FALSE == tempIcomConfigPtr->icomSetConfigPtr[IcomConfigIndex].icomWakeOnBusOff)
        {
            /* Bus off interrupt of the current CAN node is enabled or not */
            #if (STD_OFF == CAN_BUSOFF_INTERRUPT_HANDLE_ENABLE)
                /* Disable Bus off interrupt of the current CAN node */
                REG_BIT_CLEAR32(CAN_IE_REG_ADDR(hwOffset), CAN_IE_BOE_MASK);
            #endif

            /* Set the ICOM Wake on bus off status */
            g_canControllerStatus[Controller].icomConfgBOStatus = FALSE;
        }
        else
        {
            /* If Can event handling interrupt enabled */
            #if (STD_ON == CAN_BUSOFF_INTERRUPT_HANDLE_ENABLE)
                /* Enable Bus off interrupt of the current CAN node */
                REG_BIT_SET32(CAN_IE_REG_ADDR(hwOffset), CAN_IE_BOE_MASK);
            #endif

            /* Set the ICOM Wake on bus off status */
            g_canControllerStatus[Controller].icomConfgBOStatus = TRUE;
        }

        /* If SID filter is not empty */
        if(filterConfigPtr->standardListSize > 0U)
        {
            /* Set with all standard filter configuration */
            for(circleCnt = 0; circleCnt < filterConfigPtr->standardListSize; circleCnt++)
            {
                /* Set with SID Filter element address */
                standardFilterElePtr = Can_Hw_GetStandardFilterEleAddr(
                    g_canConfigPtr->msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_STD_FILTERS],
                    filterConfigPtr->standardFiltersPtr[circleCnt].filterIndex);
                
                /* If Pretended Network OFF */
                if((boolean)FALSE == filterConfigPtr->standardFiltersPtr[circleCnt].canIdPNSupport)
                {
                    /* Set to Reject Message with Filter element */
                    standardFilterElePtr->sfec = (uint32)CAN_FILTER_ELE_COFIG_DISABLE;
                }
                else
                {
                    /* nothing */
                }
            }
        }
        else
        {
            /* nothing */
        }
        
        /* If XID filter is not empty */
        if(filterConfigPtr->extendedListSize > 0U)
        {
            /* Set with all standard filter configuration */
            for(circleCnt = 0; circleCnt < filterConfigPtr->extendedListSize; circleCnt++)
            {
                /* Set with XID Filter element address */
                extendedFilterElePtr = Can_Hw_GetExtendedFilterEleAddr(
                    g_canConfigPtr->msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_EXT_FILTERS],
                    filterConfigPtr->extendedFiltersPtr[circleCnt].filterIndex);
                
                /* If Pretended Network OFF */
                if((boolean)FALSE == filterConfigPtr->extendedFiltersPtr[circleCnt].canIdPNSupport)
                {
                    /* Set to Reject Message with Filter element */
                    extendedFilterElePtr->filterExtEle0.efec = (uint32)CAN_FILTER_ELE_COFIG_DISABLE;
                }
                else
                {
                    /* nothing */
                }
            }
        }
        else
        {
            /* nothing */
        }

        /* Store ICOM Configuration ID */
        g_canControllerStatus[Controller].activeIcomCfgId = 
            tempIcomConfigPtr->icomSetConfigPtr[IcomConfigIndex].icomConfigId;
        /*Set the pretended network status for the current CAN controller */
        g_canControllerStatus[Controller].icomEnableStatus = TRUE;

        if((Std_ReturnType)E_OK == Can_Hw_WaitExitInitMode(hwOffset))
        {
            result = (Std_ReturnType)E_OK;
        }
        else
        {
            /* Intentionally Empty */
        }
    }
    else
    {
        /* Intentionally Empty */
    }

    return result;
}

/*!
* @brief    Deactivate pretended networking mode for the controller
*
* @param[in]    Controller  Index of the controller
*
* @retval   E_OK:       Operation was successful
* @retval   E_NOT_OK:   Operation was failed
*/
FUNC(Std_ReturnType, CAN_CODE) Can_Hw_DeactivateIcom(
    CONST(uint8, AUTOMATIC) Controller)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, AUTOMATIC) icomConfigId = 0U;
    VAR(uint8, AUTOMATIC) icomIndex = 0U;
    VAR(uint16, AUTOMATIC) icomMsgTempIndex = 0;
    VAR(uint16, AUTOMATIC) icomMsgIndex = 0U;
    VAR(uint16, AUTOMATIC) icomNoOfRxMsg = 0U;
    VAR(uint8, AUTOMATIC) circleCnt = 0U;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    P2VAR(Can_FilterStandardEleType, AUTOMATIC, CAN_APPL_DATA) standardFilterElePtr = NULL_PTR;
    P2VAR(Can_FilterExtendedEleType, AUTOMATIC, CAN_APPL_DATA) extendedFilterElePtr = NULL_PTR;
    P2CONST(Can_IcomConfigType, CAN_CONST, CAN_APPL_CONST) tempIcomConfigPtr = g_canStaticConfigPtr->icomConfigPtr;
    P2CONST(Can_FilterConfigType, CAN_CONST, CAN_APPL_CONST) filterConfigPtr = g_canConfigPtr->filterConfigPtr;

    /* Get ICOM configuration ID*/
    icomConfigId = g_canControllerStatus[Controller].activeIcomCfgId;
    /* Get the first receive configuration index */
     while (icomIndex < tempIcomConfigPtr->icomConfigsCount)
     {
        if (icomConfigId ==
            (uint8)(tempIcomConfigPtr->icomSetConfigPtr[icomIndex].icomConfigId))
        {
            /* Get the first receive configuration index */
            icomMsgIndex = tempIcomConfigPtr->icomSetConfigPtr[icomIndex].icomFirstMsgIndx;
            /* Get the total number of ICOM Receive messages configured*/
            icomNoOfRxMsg = tempIcomConfigPtr->icomSetConfigPtr[icomIndex].icomNoOfMsgIndx;
            break;
        }
        else
        {
            /* nothing */
        }
        icomIndex++;
     }

    if ((Std_ReturnType)E_OK == Can_Hw_WaitEnterInitMode(hwOffset))
    {
        /* Check if Wakeup on bus off condition is configured */
        if((boolean)TRUE != g_canControllerStatus[Controller].icomConfgBOStatus)
        {
        #if (STD_ON == CAN_BUSOFF_INTERRUPT_HANDLE_ENABLE)
            /* Re enable the Bus Off interrupt of the requested CAN node */
            REG_BIT_SET32(CAN_IE_REG_ADDR(hwOffset), CAN_IE_BOE_MASK);
        #endif
        }
        else
        {
            /* nothing */
        }

         /* If SID filter is not empty */
        if(filterConfigPtr->standardListSize > 0U)
        {    
          /* Set with all standard filter configuration */
          for(circleCnt = 0; circleCnt < filterConfigPtr->standardListSize; circleCnt++)
          {
              /* Set with SID Filter element address */
              standardFilterElePtr = Can_Hw_GetStandardFilterEleAddr(
                g_canConfigPtr->msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_STD_FILTERS],
                filterConfigPtr->standardFiltersPtr[circleCnt].filterIndex);

              /* If Pretended Network OFF */
              if((boolean)FALSE == filterConfigPtr->standardFiltersPtr[circleCnt].canIdPNSupport)
              {
                  /* Set to Message with Filter element configuration */
                  standardFilterElePtr->sfec = (uint32)filterConfigPtr->standardFiltersPtr[circleCnt].elementConfig;
              }
              else
              {
                  /* nothing */
              }
          }
        }
        else
        {
            /* nothing */
        }
        
        /* If XID filter is not empty */
        if(filterConfigPtr->extendedListSize > 0U)
        {
            /* Set with all standard filter configuration */
            for(circleCnt = 0; circleCnt < filterConfigPtr->extendedListSize; circleCnt++)
            {
                /* Set with XID Filter element address */
                extendedFilterElePtr = Can_Hw_GetExtendedFilterEleAddr(
                    g_canConfigPtr->msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_EXT_FILTERS],
                    filterConfigPtr->extendedFiltersPtr[circleCnt].filterIndex);

                /* If Pretended Network OFF */
                if((boolean)FALSE == filterConfigPtr->extendedFiltersPtr[circleCnt].canIdPNSupport)
                {
                    /* Set to Message with Filter element configuration */
                    extendedFilterElePtr->filterExtEle0.efec = (uint32)filterConfigPtr->extendedFiltersPtr[circleCnt].elementConfig;
                }
                else
                {
                    /* nothing */
                }
            }
        }
        else
        {
            /* nothing */
        }

        if((Std_ReturnType)E_OK == Can_Hw_WaitExitInitMode(hwOffset))
        {
            result = (Std_ReturnType)E_OK;
        }
        else
        {
            /* Intentionally Empty */
        }

        if(E_OK == result)
        {
            icomMsgTempIndex = icomMsgIndex;
            while(icomMsgTempIndex < (icomMsgIndex + icomNoOfRxMsg))
            {
                /* Clear Msg Counter values */
                g_canControllerStatus[Controller].icomMsgCntrValPtr[icomMsgTempIndex] = 0U;
                /* Increment message counter index */
                icomMsgTempIndex++;
            }

            /* Clear the ICOM Wake on bus off status */
            g_canControllerStatus[Controller].icomConfgBOStatus = FALSE;
            /* Set the pretended network status for the current CAN controller */
            g_canControllerStatus[Controller].icomEnableStatus = FALSE;
            /* Clear ICOM Configuration ID */
            g_canControllerStatus[Controller].activeIcomCfgId = 0U;
            
            /* Allow Can_Writes - Icom de-activation completed */
            g_canControllerStatus[Controller].icomBlockWriteCalls = FALSE;
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        /* Intentionally Empty */
    }
    return result;
}
#endif /* STD_ON == CAN_PUBLIC_ICOM_ENABLE */

/*!
* @brief    This function is used for the cancellation of transmission,
*           If there any Tx buffer with pending transmission request.
* @param[in]    Controller      Index of the controller
* 
*/
FUNC(void, CAN_CODE) Can_Hw_CancelPendingTx(CONST(uint8, AUTOMATIC)  Controller)
{
    VAR(uint16, AUTOMATIC) txHwIndex = 0U;
    VAR(uint16, AUTOMATIC) swObjIndx = 0U;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    
    /* Transmit hardware objects are configured for current core */
    if(0U != g_canConfigPtr->txMbConfigContainerPtr->txMbCount)
    {
        for (txHwIndex = 0U; txHwIndex < CAN_MAX_TX_BUFFER_INDEX; txHwIndex++)
        {
            /* Calculate Sw Obj Handle index */
            swObjIndx = (uint16)(((uint16)Controller * CAN_MAX_TX_BUFFER_INDEX) + (uint16)txHwIndex);
            g_canControllerStatus[Controller].swObjectHandle[swObjIndx] = 0U;
        }
        
        /* Check for pending request */
        if(0U != REG_READ32(CAN_TXBRP_REG_ADDR(hwOffset)))
        {
            /* Set the pending request with cancellation request */
            REG_WRITE32(CAN_TXBCR_REG_ADDR(hwOffset), 0xFFFFFFFFU);
        }
        else
        {
            /* nothing */
        }
        
        /* Rebuild mask Queue eleemnt mask */
        g_canControllerStatus[Controller].txMask = g_canControllerStatus[Controller].backupTxMask;
    }
    else
    {
        /* nothing */
    }
}

/*!
* @brief    Receive Handler function to process the received messages
* @param[in]    Controller     Index of the controller
* @param[in]    CheckBuffType  Type of receive buffer to be checked
* @param[in]    PriodicCheck   This flag indicates whether periodic check is required
* @param[in]    PeriodRef      This value indicates the periodic reference
* 
*/
FUNC(void, CAN_CODE) Can_Hw_ReceiveHandler(CONST(uint8, AUTOMATIC) Controller,
    CONST(Can_RxDataCheckType, AUTOMATIC) CheckBuffType, CONST(boolean, AUTOMATIC) PriodicCheck,
    VAR(uint8, AUTOMATIC) PeriodRef)
{
    VAR(uint32, AUTOMATIC) rxNDATValue = 0U;
    VAR(uint32, AUTOMATIC) rxNDATValue0 = 0U;
    VAR(uint32, AUTOMATIC) rxNDATValue1 = 0U;
    VAR(uint32, AUTOMATIC) rxDedMask = 0U;
    VAR(uint32, AUTOMATIC) periodicRxDedMask0 = 0U;
    VAR(uint32, AUTOMATIC) periodicRxDedMask1 = 0U;
    VAR(uint32, AUTOMATIC) irRegValue = 0U;
    VAR(uint8, AUTOMATIC) rxHandleBuffPos = 0U;
    VAR(uint8, AUTOMATIC) regSet = 0U;
    VAR(uint8, AUTOMATIC) circleCnt = 0U;
    VAR(uint8, AUTOMATIC) loopExitFlag = 0;
#if (STD_ON == CAN_RXFIFO_ENABLE)
    VAR(uint8, AUTOMATIC) fifo0Size = g_canConfigPtr->msgRamConfigPtr->rxFIFO0Size;
    VAR(uint8, AUTOMATIC) fifo1Size = g_canConfigPtr->msgRamConfigPtr->rxFIFO1Size;
#endif
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    VAR(Can_HwHandleType, AUTOMATIC) mbHrh = 0U;
    VAR(Std_ReturnType, AUTOMATIC) findMbRes = (Std_ReturnType)E_NOT_OK;

    /* Recieve data buffer is dedicated Type */
    if(CAN_RX_DATA_CHECK_DEDICATED_BUFFER == CheckBuffType)
    {
        rxNDATValue0 = REG_READ32(CAN_NDAT1_REG_ADDR(hwOffset));
        rxNDATValue1 = REG_READ32(CAN_NDAT2_REG_ADDR(hwOffset));
        /* Set with first bit position*/
        rxHandleBuffPos = 0U;
        /* Read first NDAT0 buffer value */
        rxNDATValue = rxNDATValue0;

        /* Read NDAT1 and NDAT2 */
        /* Loop to read the data registers */
        for(regSet = 0U; regSet < 2U ; regSet++)
        {
            /* Set mask value */
            rxDedMask = 1U;
            /* loop to get the Rx dedicated buffers, Check any one of the Rx dedicated buffer is received with new data */
            while(circleCnt < 32U)
            {
                /* Check buffer with mask position is received data or not */
                if(0U != (rxNDATValue & rxDedMask))
                {
                    findMbRes = Can_Hw_FindValidRxMb(Controller, CAN_RX_DATA_CHECK_DEDICATED_BUFFER, rxHandleBuffPos, 
                        &mbHrh, PriodicCheck, PeriodRef);
                    
                    if(E_OK == findMbRes)
                    {
                        /* Retrieve data from recieved message */
                        (void)Can_Hw_RxExtractData(Controller, rxHandleBuffPos, \
                                            CAN_RX_DATA_CHECK_DEDICATED_BUFFER, mbHrh);
                        /* If periodic check is enabled */
                        if((boolean)TRUE == PriodicCheck)
                        {
                            if(rxHandleBuffPos < 32U)
                            {
                                periodicRxDedMask0 |= ((uint32)1U << (uint32)circleCnt);
                            }
                            else
                            {
                                periodicRxDedMask1 |= ((uint32)1U << (uint32)circleCnt);
                            }
                        }
                        else
                        {
                            /* Do nothing */
                        }
                    }
                    else
                    {
                        /* nothing */
                    }
              }
              else
              {
                  /* nothing */
              }
              /* Set mask for check next buffer status */
              rxDedMask = rxDedMask << 1U;
              /* Increment bit position */
              rxHandleBuffPos++;
              circleCnt++;
            }
            /* After completion of read NDAT1 load NDAT_value with NDAT2 register value */
            rxNDATValue = rxNDATValue1;
            /* Set Buffer position from value 32 for NDAT2 */
            rxHandleBuffPos = 32U;
            circleCnt = 0U;
        }
        
        /* If periodic check is enabled */
        if((boolean)TRUE == PriodicCheck)
        {
            /* Clear NDAT Register for receive new message */
            REG_WRITE32(CAN_NDAT1_REG_ADDR(hwOffset), periodicRxDedMask0);
            REG_WRITE32(CAN_NDAT2_REG_ADDR(hwOffset), periodicRxDedMask1);
        }
        else
        {
            /* Clear NDAT Register for receive new message */
            REG_WRITE32(CAN_NDAT1_REG_ADDR(hwOffset), rxNDATValue0);
            REG_WRITE32(CAN_NDAT2_REG_ADDR(hwOffset), rxNDATValue1);
        }
    }
    else
    {
        /* nothing */
    }

#if (STD_ON == CAN_RXFIFO_ENABLE)
    /* Recieve buffer type is Rx FIFO 0 */
    if(CAN_RX_DATA_CHECK_FIFO0 == CheckBuffType)
    {
        /* Read IR Register value */
        irRegValue = REG_READ32(CAN_IR_REG_ADDR(hwOffset));
        
        /* Check Received CAN message is lost or not */
        if(CAN_IR_RF0L_MASK == (irRegValue & CAN_IR_RF0L_MASK))
        {
        #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
            (void)Det_ReportError((uint16)CAN_HW_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                              (uint8)CAN_SID_MAIN_READ, (uint8)CAN_E_DATALOST);
        #endif
            /* Clear the flag */
            REG_BIT_SET32(CAN_IR_REG_ADDR(hwOffset), CAN_IR_RF0L_MASK);
        }
        else
        {
          /* Do nothing */
        }
        
        /* Find the valid FIFO0 */
        findMbRes = Can_Hw_FindValidRxMb(Controller, CAN_RX_DATA_CHECK_FIFO0, 0U, &mbHrh, PriodicCheck, PeriodRef);

        if(E_OK == findMbRes)
        {
            /* Loop till all messages are read in Rx FIFO 0 or read max configured messages in FIFO */
            while((((REG_READ32(CAN_RXF0S_REG_ADDR(hwOffset)) & CAN_RXF0S_F0FL_MASK) >> CAN_RXF0S_F0FL_SHIFT) > 0U) && 
                (loopExitFlag < fifo0Size))
            {
                loopExitFlag++;
                /* a. Read all FIFO slots and acknowledge to free up slots b. Notify upper layer */
                /* Read Rx FIFO 0 Get Index */
                rxHandleBuffPos = (uint8)((REG_READ32(CAN_RXF0S_REG_ADDR(hwOffset)) & CAN_RXF0S_F0GI_MASK) >> CAN_RXF0S_F0GI_SHIFT);
                /* Invoke data retrieve function */
                (void)Can_Hw_RxExtractData(Controller, rxHandleBuffPos, CAN_RX_DATA_CHECK_FIFO0, mbHrh);

                /* Set read Acknowledge of buffer */
                REG_WRITE32(CAN_RXF0A_REG_ADDR(hwOffset), rxHandleBuffPos);
            }
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        /* nothing */
    }

    /* Recieve buffer type is Rx FIFO 1 */
    if(CAN_RX_DATA_CHECK_FIFO1 == CheckBuffType)
    {
        loopExitFlag = 0;
        /* Read IR Register value */
        irRegValue = REG_READ32(CAN_IR_REG_ADDR(hwOffset));
        /* Check Received CAN message is lost or not */
        if(CAN_IR_RF1L_MASK == (irRegValue & CAN_IR_RF1L_MASK))
        {
        #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
            (void)Det_ReportError((uint16)CAN_HW_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                              (uint8)CAN_SID_MAIN_READ, (uint8)CAN_E_DATALOST);
        #endif
            /* Clear the flag */
            REG_BIT_SET32(CAN_IR_REG_ADDR(hwOffset), CAN_IR_RF1L_MASK);
        }
        else
        {
            /* Do nothing */
        }

        /* Find the valid FIFO1 */
        findMbRes = Can_Hw_FindValidRxMb(Controller, CAN_RX_DATA_CHECK_FIFO1, 0U, &mbHrh, PriodicCheck, PeriodRef);
        
        if(E_OK == findMbRes)
        {
            /* Loop till all messages are read in Rx FIFO 1 or read max configured messages in FIFO */
            while((((REG_READ32(CAN_RXF1S_REG_ADDR(hwOffset)) & CAN_RXF1S_F1FL_MASK) >> CAN_RXF1S_F1FL_SHIFT) > 0U) && 
                (loopExitFlag < fifo1Size))
            {
                loopExitFlag++;
                /* a. Read all FIFO slots and acknowledge to free up slots b. Notify upper layer */
                /* Read Rx FIFO 1 Get Index */
                rxHandleBuffPos = (uint8)((REG_READ32(CAN_RXF1S_REG_ADDR(hwOffset)) & CAN_RXF1S_F1GI_MASK) >> CAN_RXF1S_F1GI_SHIFT);
                /* Invoke data retrieve message function */
                (void)Can_Hw_RxExtractData(Controller, rxHandleBuffPos, CAN_RX_DATA_CHECK_FIFO1, mbHrh);
                /* Set read Acknowledge of buffer */
                REG_WRITE32(CAN_RXF1A_REG_ADDR(hwOffset), rxHandleBuffPos);
            }
        }
        else
        {
            /* Do nothing */
        }
    }
    else
    {
        /* nothing */
    }
#endif /* STD_ON == CAN_RXFIFO_ENABLE */
}

/*!
* @brief    Transmit Event Handler function to process the transmitted messages
* @param[in]    Controller     Index of the controller
* 
*/
FUNC(void, CAN_CODE) Can_Hw_TxEventHandler(CONST(uint8, AUTOMATIC) Controller)
{
    volatile P2CONST(Can_TxEvtFifoEleType, AUTOMATIC, CAN_APPL_DATA) txEvntReadDataPtr = NULL_PTR;
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_CONST) msgRamCfgPtr = NULL_PTR;
    VAR(uint32, AUTOMATIC) txEvntFIFOstartAddr = 0U;
    VAR(uint32, AUTOMATIC) txEvntFIFORealAddr = 0U;
    VAR(uint32, AUTOMATIC) txEvntFIFOGetIndex = 0U;
    VAR(Can_HwHandleType, AUTOMATIC) txHandleIndx = 0U;
    VAR(uint8, AUTOMATIC) txEvntFillLvlVal = 0U;
    VAR(uint8, AUTOMATIC) loopExitFlag = 0U;
    VAR(uint16, AUTOMATIC) swObjIndx = 0U;
    VAR(uint32, AUTOMATIC) txSlotIndex = 0U;
    VAR(PduIdType, AUTOMATIC) pduHandle = 0U;
    
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    
    /* Set pointer variable with Message RAM Configuration structure */
    msgRamCfgPtr = g_canConfigPtr->msgRamConfigPtr;
    
    /* if LOST is raised as HW event */
    if(CAN_IR_TEFL_MASK == (REG_READ32(CAN_IR_REG_ADDR(hwOffset)) & CAN_IR_TEFL_MASK))
    {
    #if (STD_ON == CAN_TX_EVT_FIFO_LOST_ELE_NOTIFICATION_ENABLE)
        /* Call the user notification */
        if(NULL_PTR != g_canConfigPtr->controllersInfoPtr[Controller].notificationConfigPtr->txEvtFifoLostMsgNotification)
        {
            g_canConfigPtr->controllersInfoPtr[Controller].notificationConfigPtr->txEvtFifoLostMsgNotification();
        }
        else
        {
             /* Do nothing */
        }
    #endif
        /* Clear TEFN and TEFL flags as well if SET */
        REG_BIT_SET32(CAN_IR_REG_ADDR(hwOffset), CAN_IR_TEFL_MASK);
    }
    else
    {
        /* Do nothing */
    }
    
    /* Set Tx Event FIFO Start Address */
    txEvntFIFOstartAddr = msgRamCfgPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_TX_EVENT_FIFO];
    /* Read Fill Level value */
    txEvntFillLvlVal = (uint8)((REG_READ32(CAN_TXEFS_REG_ADDR(hwOffset)) & CAN_TXEFS_EFFL_MASK) >> CAN_TXEFS_EFFL_SHIFT);
    /* Read Tx event FIFO register for read No of stored Events and CAN_NOOF_TX_HW_BUFF_AVAILABLE > loopExitFlag */
    while((0U != txEvntFillLvlVal) && (CAN_NOOF_TX_HW_BUFF_AVAILABLE > loopExitFlag))
    {
        /* Read TxEvent buffer index */
        txEvntFIFOGetIndex = ((REG_READ32(CAN_TXEFS_REG_ADDR(hwOffset)) & CAN_TXEFS_EFGI_MASK) >> CAN_TXEFS_EFGI_SHIFT);
        /* Set Real Event FIFO element address */
        txEvntFIFORealAddr = txEvntFIFOstartAddr + (txEvntFIFOGetIndex * (uint32)CAN_TX_EVT_FIFO_ELEMENT_SIZE_U32);
        
        /* Load Event FIFO element address */
        txEvntReadDataPtr = (volatile Can_TxEvtFifoEleType*)txEvntFIFORealAddr;
        /* Read Message Marker */
        txHandleIndx = (Can_HwHandleType)txEvntReadDataPtr->txEvtE1.mm;
        /* Calculate Sw Obj Handle index */
        swObjIndx = (uint16)(((uint16)Controller * CAN_NOOF_TX_HW_BUFF_AVAILABLE) + (uint16)txHandleIndx);
        
        /* Release Tx buffer before notification by copying the id */
        pduHandle = g_canControllerStatus[Controller].swObjectHandle[swObjIndx];
        
        txSlotIndex = ((uint32)1U << txHandleIndx);
        
        /* Check if this element belong to configured Tx objects */
        if((txSlotIndex & g_canControllerStatus[Controller].backupTxMask) == txSlotIndex)
        {
            /* Enter Critical Section */
            SchM_Enter_Can_CAN_CRITICAL_SECTION2();

            /* Release Transmit object */
            g_canControllerStatus[Controller].txMask |= txSlotIndex;

            /* Exit Critical Section */
            SchM_Exit_Can_CAN_CRITICAL_SECTION2();
        }
        else
        {
            /* nothing */
        }
        
        /* Acknowledge shall set to free the Tx Event FIFO */
        REG_WRITE32(CAN_TXEFA_REG_ADDR(hwOffset), txEvntFIFOGetIndex);
        
        /* Set with Exact PduHandle Stored Index value */
        /* Call Transmission confirmation to upper-layer with L-PDU handle */
        CanIf_TxConfirmation(pduHandle);
        
        /* Increment exit loop condition for safety */
        loopExitFlag++;
        
        /* Read Fill Level value */
        txEvntFillLvlVal = (uint8)((REG_READ32(CAN_TXEFS_REG_ADDR(hwOffset)) & CAN_TXEFS_EFFL_MASK) >> CAN_TXEFS_EFFL_SHIFT);
    }
}

#if (STD_OFF == CAN_RX_INTERRUPT_HANDLE_ENABLE)
/*!
* @brief    Performs the polling of RX indications
*/
FUNC(void, CAN_CODE) Can_Hw_MainFunctionRead(void)
{
    VAR(uint8, AUTOMATIC) index = 0U;
    VAR(uint8, AUTOMATIC) hwOffset = 0U;

    /* Loop through all configured controller */
    while (index < (uint8)g_canStaticConfigPtr->controllersConfigured)
    {
        hwOffset = g_canControllerStaticConfigPtr[index].controllerOffset;

    #if (STD_ON == CAN_RXFIFO_ENABLE)
        /* Check if the Rx Fifo 0 */
        if (0U != REG_BIT_GET32(CAN_RXF0S_REG_ADDR(hwOffset), CAN_RXF0S_F0FL_MASK))
        {
            {
                Can_Hw_ReceiveHandler(index, CAN_RX_DATA_CHECK_FIFO0, FALSE, 0U);
            }
        }

        /* Check if the Rx Fifo 1 */
        if(0U !=  REG_BIT_GET32(CAN_RXF1S_REG_ADDR(hwOffset), CAN_RXF1S_F1FL_MASK))
        {
            {
                Can_Hw_ReceiveHandler(index, CAN_RX_DATA_CHECK_FIFO1, FALSE, 0U);
            }
        }
    #endif

        /* Check if the Rx dedicated buffer */
        Can_Hw_ReceiveHandler(index, CAN_RX_DATA_CHECK_DEDICATED_BUFFER, FALSE, 0U);

        index++;
    }
}

/*!
* @brief    Performs the polling of RX indications
*
* @param[in]    PeriodRef   Period reference
*/
FUNC(void, CAN_CODE) Can_Hw_MainFunctionMultipleRead(
    VAR(uint8, AUTOMATIC) PeriodRef)
{
    VAR(uint8, AUTOMATIC)   index = 0U;
    VAR(uint8, AUTOMATIC) hwOffset = 0U;

    /* Loop through all configured controller */
    while (index < (uint8)g_canStaticConfigPtr->controllersConfigured)
    {
        hwOffset = g_canControllerStaticConfigPtr[index].controllerOffset;

    #if (STD_ON == CAN_RXFIFO_ENABLE)
        /* Check the Rx Fifo 0 */
        if (0U != REG_BIT_GET32(CAN_RXF0S_REG_ADDR(hwOffset), CAN_RXF0S_F0FL_MASK))
        {
            Can_Hw_ReceiveHandler(index, CAN_RX_DATA_CHECK_FIFO0, TRUE, PeriodRef);
        }
        /* Check the Rx Fifo 1 */
        if(0U !=  REG_BIT_GET32(CAN_RXF1S_REG_ADDR(hwOffset), CAN_RXF1S_F1FL_MASK))
        {
            Can_Hw_ReceiveHandler(index, CAN_RX_DATA_CHECK_FIFO1, TRUE, PeriodRef);
        }
    #endif
        /* Check the Rx dedicated buffer */
        Can_Hw_ReceiveHandler(index, CAN_RX_DATA_CHECK_DEDICATED_BUFFER, TRUE, PeriodRef);

        index++;
    }
}
#endif /* STD_OFF == CAN_RX_INTERRUPT_HANDLE_ENABLE */

#if (STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE)
/*!
* @brief    Performs the polling of TX confirmations
*/
FUNC(void, CAN_CODE) Can_Hw_MainFunctionWrite(void)
{
    VAR(uint8, AUTOMATIC) index = 0U;

    /* Loop through all configured controllers */
    while (index < (uint8)g_canStaticConfigPtr->controllersConfigured)
    {
        if (CAN_CONTROLLER_INVALID != g_canControllerStaticConfigPtr[index].controllerOffset)
        {
            Can_Hw_TxEventHandler(index);
        }
        else
        {
            /* Intentionally Empty */
        }

        index++;
    }
}

/*!
* @brief    Performs the polling of TX confirmations
*
* @param[in]    PeriodRef   Period reference
*/
FUNC(void, CAN_CODE) Can_Hw_MainFunctionMultipleWrite(
    VAR(uint8, AUTOMATIC) PeriodRef)
{
    VAR(uint8, AUTOMATIC)   controller = 0U;
    VAR(uint8, AUTOMATIC) index = 0U;

    /* Loop through all configured controllers */
    while (index < (uint8)g_canStaticConfigPtr->controllersConfigured)
    {
        if (CAN_CONTROLLER_INVALID != g_canControllerStaticConfigPtr[index].controllerOffset)
        {
            Can_Hw_TxEventHandlerPeriodic(controller, PeriodRef);
        }
        else
        {
            /* Intentionally Empty */
        }

        index++;
    }
}
#endif /* STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE */

#if (STD_ON == CAN_ABORT_MB_API_ENABLE)
/*!
* @brief    Abort transmission of a CAN frame
*
* @param[in]    Hth The HW-transmit handle to be aborted
*/
FUNC(void, CAN_CODE) Can_Hw_AbortMb(VAR(Can_HwHandleType, AUTOMATIC) Hth)
{
    P2CONST(Can_TxMbConfigsContainerType, AUTOMATIC, CAN_APPL_DATA) txMbConfigContainerPtr = 
        g_canConfigPtr->txMbConfigContainerPtr;
    VAR(uint16, AUTOMATIC) mbGlobalIndex = 0U;
    VAR(uint8, AUTOMATIC) controller;

    while (mbGlobalIndex < txMbConfigContainerPtr->txMbCount)
    {
        if (((txMbConfigContainerPtr->txMbConfigPtr)[mbGlobalIndex]).txHwObjId == Hth)
        {
            break;
        }
        else
        {
            /* Intentionally Empty */
        }

        mbGlobalIndex++;
    }

    controller = ((txMbConfigContainerPtr->txMbConfigPtr)[mbGlobalIndex]).hwControllerId;

#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
    if ((Std_ReturnType)E_OK == Can_CheckControllerId((uint8)CAN_SID_ABORT_MB, controller))
#endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
    {
    #if ((STD_OFF == CAN_ABORT_ONLY_ONE_MB) && (STD_ON == CAN_MULTIPLEXED_TRANSMISSION_ENABLE))
        /* Multiplexed transmission is enabled, cancel all MBs if abort one MB is not configured. */
        while (mbGlobalIndex < txMbConfigContainerPtr->txMbCount)
        {
            if (((txMbConfigContainerPtr->txMbConfigPtr) + mbGlobalIndex)->txHwObjId != Hth)
            {
                break;
            }
            else
            {
                /* Intentionally Empty */
            }
            Can_Hw_CancelMb(controller, mbGlobalIndex);
            mbGlobalIndex++;
        }
    #else
        /* In other cases, cancel only one MB */
        Can_Hw_CancelMb(controller, mbGlobalIndex);
    #endif /* {(STD_OFF == CAN_ABORT_ONLY_ONE_MB) && (STD_ON == CAN_MULTIPLEXED_TRANSMISSION_ENABLE)} */
    }
#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
    else
    {
        /* Intentionally Empty */
    }
#endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
}
#endif /* STD_ON == CAN_ABORT_MB_API_ENABLE */

#ifdef CAN_SET_BAUDRATE_API
#if (STD_ON == CAN_SET_BAUDRATE_API)
/*!
* @brief    Set baudrate for the controller
*
* @param[in]    Controller  Index of the controller
*/
FUNC(void, CAN_CODE) Can_Hw_SetBaudrate(VAR(uint8, AUTOMATIC) Controller)
{
    VAR(uint8, AUTOMATIC) baudrateIndex = 0U;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;

    /* Initialize baudrate */
    baudrateIndex = g_canControllerStatus[Controller].currentBaudrateIndex;
    Can_Hw_InitBaudrate(hwOffset, Controller, baudrateIndex);
}
#endif /* STD_ON == CAN_SET_BAUDRATE_API */
#endif /* CAN_SET_BAUDRATE_API */

/*!
* @brief    Performs the polling of CAN controller mode transitions
*/
FUNC(void, CAN_CODE) Can_Hw_MainFunctionMode(void)
{
    VAR(uint32, AUTOMATIC)  hwState = 0U;
    VAR(uint8, AUTOMATIC)   hwOffset = 0U;
    VAR(uint8, AUTOMATIC)   controller = 0U;

    /* Loop through all configured controllers */
    while (controller < (uint8)g_canStaticConfigPtr->controllersConfigured)
    {
        if ((CAN_CONTROLLER_INVALID == g_canControllerStaticConfigPtr[controller].controllerOffset) ||
            (CAN_CS_SLEEP == g_canControllerStatus[controller].controllerState))
        {
            controller++;
            continue;
        }
        else
        {
            /* Intentionally Empty */
        }

        hwOffset = g_canControllerStaticConfigPtr[controller].controllerOffset;
        hwState = (uint32)(REG_READ32(CAN_CCCR_REG_ADDR(hwOffset)) & CAN_CCCR_INIT_MASK);

        /* Check if logical state is synchronized with hardware state */
        if (CAN_CCCR_INIT_MASK != hwState)
        {
            /* Hardware state is STARTED, but logical state is STOPPED. */
            if (CAN_CS_STOPPED == g_canControllerStatus[controller].controllerState)
            {
                g_canControllerStatus[controller].controllerState = CAN_CS_STARTED;
                CanIf_ControllerModeIndication(controller, CANIF_CS_STARTED);
            }
            else
            {
                /* Intentionally Empty */
            }
        }
        else
        {
            /* Hardware state is STOPPED, but logical state is STARTED. */
            if (CAN_CS_STARTED == g_canControllerStatus[controller].controllerState)
            {
        #if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
                (void)Can_Hw_DeactivateIcom(controller);
        #endif /* STD_ON == CAN_PUBLIC_ICOM_ENABLE */

                g_canControllerStatus[controller].controllerState = CAN_CS_STOPPED;
                CanIf_ControllerModeIndication(controller, CANIF_CS_STOPPED);
            }
            else
            {
                /* Intentionally Empty */
            }
        }
        controller++;
    }
}

/*!
* @brief    Enable controller interrupts
*
* @param[in]    Controller          Index of the controller
* @param[in]    ControllerInfoPtr   Pointer to controller configuration
*/
FUNC(void, CAN_CODE) Can_Hw_EnableControllerInterrupts(
    VAR(uint8, AUTOMATIC) Controller)
{
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;

    SchM_Enter_Can_CAN_CRITICAL_SECTION8();
    /* Check disable interrupt count is greater than zero. */
    if (g_canControllerStatus[Controller].disableIntrpCount > 0U)
    {
        /* Incremental interrupt disable/enable count */
        g_canControllerStatus[Controller].disableIntrpCount = g_canControllerStatus[Controller].disableIntrpCount - (uint8)1;
        /* Check if disable count is zero or not */
        if (0U == g_canControllerStatus[Controller].disableIntrpCount)
        {
            /* Re enable the status of Interrupts configured */
            g_canControllerStatus[Controller].interruptMode = CAN_INTERRUPT_ENABLED;
            REG_WRITE32(CAN_IE_REG_ADDR(hwOffset), 
                g_canConfigPtr->interruptConfigPtr->intEnBits);
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        /* nothing */
    }
    SchM_Exit_Can_CAN_CRITICAL_SECTION8();
}

/*!
* @brief    Disable controller interrupts
*
* @param[in]    Controller  Index of the controller
*/
FUNC(void, CAN_CODE) Can_Hw_DisableControllerInterrupts(VAR(uint8, AUTOMATIC) Controller)
{
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    VAR(boolean, AUTOMATIC) doDisable = (boolean)FALSE;
    
    SchM_Enter_Can_CAN_CRITICAL_SECTION7();

    g_canControllerStatus[Controller].disableIntrpCount = g_canControllerStatus[Controller].disableIntrpCount + (uint8)1;

    /* Disable all interrupts for this CAN controller only at the first call of this function */
    if ((uint8)1 == g_canControllerStatus[Controller].disableIntrpCount)
    {
        doDisable = (boolean)TRUE;
    }
    else
    {
        /* Intentionally Empty */
    }

    SchM_Exit_Can_CAN_CRITICAL_SECTION7();

    if ((boolean)TRUE == doDisable)
    {
        /* Disable the status of Interrupts configured */
        g_canControllerStatus[Controller].interruptMode = CAN_INTERRUPT_DISABLED;
        REG_WRITE32(CAN_IE_REG_ADDR(hwOffset), 0U);
    }
    else
    {
        /* Intentionally Empty */
    }
}

/*!
* @brief    Initialize the controller
*
* @param[in]    Controller  Index of the controller
*/
FUNC(Std_ReturnType, CAN_CODE) Can_Hw_InitController(
    VAR(uint8, AUTOMATIC) Controller)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    VAR(uint32, AUTOMATIC) tmpAddr;
    VAR(uint8, AUTOMATIC) hwOffset = 0U;
    VAR(uint8, AUTOMATIC) baudrateIndex = 0U;

    baudrateIndex = g_canControllerStatus[Controller].currentBaudrateIndex;
    hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    (void)Can_Hw_ResetController();
    if ((Std_ReturnType)E_OK == Can_Hw_WaitEnterInitMode(hwOffset))
    {
        result = (Std_ReturnType)E_OK;
    }
    else
    {
        /* Intentionally Empty */
    }

    if ((Std_ReturnType)E_OK == result)
    {
        /* Initialize baudrate for the controller */
        Can_Hw_InitBaudrate(hwOffset, Controller, baudrateIndex);

        /* Set the cancel MB index to invalid value */
        g_canControllerStatus[Controller].mbCancelIndex = (Can_HwHandleType)CAN_MAX_TX_MB_SUPPORTED;

        /* Test mode configuration */
        if(CAN_CCCR_TEST_MASK == (g_canControllerStaticConfigPtr[Controller].controllerOptions & CAN_CCCR_TEST_MASK))
        {            
            SchM_Enter_Can_CAN_CRITICAL_SECTION5();
            if((boolean)TRUE == g_canControllerStaticConfigPtr[Controller].testConfigPtr->loopbackModeEnable)
            {
                /* Set the loop back mode and the TX bit region in the TEST Register */
                REG_BIT_SET32(CAN_TEST_REG_ADDR(hwOffset), CAN_TEST_LBCK_MASK);
            }
            else
            {
                /* nothing */
            }

            REG_RMW32(CAN_TEST_REG_ADDR(hwOffset), CAN_TEST_TX_MASK, 
                (uint32)g_canControllerStaticConfigPtr[Controller].testConfigPtr->txPinControl << CAN_TEST_TX_SHIFT);
            SchM_Exit_Can_CAN_CRITICAL_SECTION5();
        }
        else
        {
            /* Intentionally Empty */
        }

        /* Timestamp counter configuration */
        REG_RMW32(CAN_TSCC_REG_ADDR(hwOffset), CAN_TSCC_TSS_MASK, 
            (uint32)g_canControllerStaticConfigPtr[Controller].timestampConfigPtr->timestampCnterOperMode << CAN_TSCC_TSS_SHIFT);
        REG_RMW32(CAN_TSCC_REG_ADDR(hwOffset), CAN_TSCC_TCP_MASK, 
            (uint32)g_canControllerStaticConfigPtr[Controller].timestampConfigPtr->timestampCnterPscaler << CAN_TSCC_TCP_SHIFT);
        
        /* Timeout counter configuration */
        if((boolean)TRUE == g_canControllerStaticConfigPtr[Controller].timeoutCnterConfigPtr->timeoutCnterEnable)
        {
            /* Timeout counter enable */
            REG_BIT_SET32(CAN_TOCC_REG_ADDR(hwOffset), CAN_TOCC_ETOC_MASK);
            /* Timeout counter operation mode */
            REG_RMW32(CAN_TOCC_REG_ADDR(hwOffset), CAN_TOCC_TOS_MASK, 
                (uint32)g_canControllerStaticConfigPtr[Controller].timeoutCnterConfigPtr->timeoutCnterOperMode << CAN_TOCC_TOS_SHIFT);
            /* Timeout counter period */
            REG_RMW32(CAN_TOCC_REG_ADDR(hwOffset), CAN_TOCC_TOP_MASK, 
                (uint32)g_canControllerStaticConfigPtr[Controller].timeoutCnterConfigPtr->timeoutPeriod << CAN_TOCC_TOP_SHIFT);
        }
        else
        {
            /* Intentionally Empty */
        }

        /* RAM watchdog configuration */
        if(0U != g_canControllerStaticConfigPtr[Controller].rwdOptions)
        {
            REG_WRITE32(CAN_RWD_REG_ADDR(hwOffset), 
               g_canControllerStaticConfigPtr[Controller].rwdOptions);
        }
        else
        {
            /* Intentionally Empty */
        }

        /* Initialize the Message RAM */
        tmpAddr = CAN_SRAM_BASEADDR;
        for (; tmpAddr < CAN_SRAM_ENDADDR; tmpAddr += 4U)
        {
            REG_WRITE32(tmpAddr, (uint32)0U);
        }

    #if (STD_ON == CAN_ENABLE_ERM)
        /* Initialize the Error Recovery Mechanism,before operate the ram */
        Can_Hw_InitErm();
    #endif

    #if (STD_ON == CAN_RXFIFO_ENABLE)
        /* Initialize the Rx fifo */
        Can_Hw_InitRxFiFo(hwOffset);
    #endif
        /* Initialize the Rx buffers */
        Can_Hw_InitRxMBs(hwOffset);
        /* Initialize the Tx buffers */
        Can_Hw_InitTxMBs(Controller, hwOffset);
        /* Initialize the Tx event fifo */
        Can_Hw_InitTxEvtFifo(hwOffset);
        /* Initialize the filters */
        Can_Hw_InitFilters(hwOffset);

        /* Interrupt configuration */
        /* Set the interrupt enable bits */
        REG_WRITE32(CAN_IE_REG_ADDR(hwOffset),g_canConfigPtr->interruptConfigPtr->intEnBits);
        /* Set the interrupt line select bits */
        REG_WRITE32(CAN_ILS_REG_ADDR(hwOffset),g_canConfigPtr->interruptConfigPtr->intLineBits);
        /* Set the interrupt line enable bits */
        REG_WRITE32(CAN_ILE_REG_ADDR(hwOffset),g_canConfigPtr->interruptConfigPtr->intLineEnBits);
    
        /* Clear the interrupt flag */
        REG_WRITE32(CAN_IR_REG_ADDR(hwOffset), 0xFFFFFFFFU);

        /* Clear the Rx buffer New Data flag */
        Can_Hw_ClrRxBufNewDataFlg(hwOffset);
    #if (STD_ON == CAN_RXFIFO_ENABLE)
        /* Clear the Rx fifo0 data */
        Can_Hw_ClrRxFifo0Data(hwOffset);
        /* Clear the Rx fifo1 data */
        Can_Hw_ClrRxFifo1Data(hwOffset);
    #endif

        g_canControllerStatus[Controller].controllerState = CAN_CS_STOPPED;
    }
    else
    {
        /* Intentionally Empty */
    }
    return result;
}

/*!
* @brief    De-initialize the controller
*
* @param[in]    Controller  Index of the controller
*/
FUNC(void, CAN_CODE) Can_Hw_DeInitController(
    VAR(uint8, AUTOMATIC) Controller)
{
    (void)Can_Hw_ResetController();
    g_canControllerStatus[Controller].controllerState = CAN_CS_UNINIT;
}

/*!
* @brief    Initialize internal variables of the CAN driver
*/
FUNC(void, CAN_CODE) Can_Hw_InitVariables(void)
{
    VAR(uint8, AUTOMATIC) controller = 0U;
#if (STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE)
    VAR(uint8, AUTOMATIC) circleCnt = 0U;
#endif /* STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE */

/* Calculate timeout duration value */
#ifdef CAN_ENABLE_TIMEOUT_AS_LOOP
    g_canTimeoutDuration = (uint32)CAN_TIMEOUT_VALUE;
#else
    g_canTimeoutDuration = Can_Hw_CalculateTimeoutValue();
#endif /* CAN_ENABLE_TIMEOUT_AS_LOOP */

    /* Initialize all global variables for all controllers */
    while (controller < (uint8)g_canStaticConfigPtr->controllersConfigured)
    {
    #if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
        /* Pretended Networking deactivated by default */
        g_canControllerStatus[controller].icomConfgBOStatus = FALSE;
        g_canControllerStatus[controller].icomEnableStatus = FALSE;
        g_canControllerStatus[controller].icomBlockWriteCalls = FALSE;
        g_canControllerStatus[controller].activeIcomCfgId = 0U;
        g_canControllerStatus[controller].icomMsgCntrValPtr = g_IcomMsgCtrVal;
    #endif
        
        g_canControllerStatus[controller].txMask = 0U;
        g_canControllerStatus[controller].backupTxMask = 0U;
        g_canControllerStatus[controller].controllerState = CAN_CS_STOPPED;
        g_canControllerStatus[controller].interruptMode= CAN_INTERRUPT_ENABLED;
        g_canControllerStatus[controller].disableIntrpCount = 0U;
        /* Current platform only has one controller,so only use on arrary,otherwise must be different arrary for different controller */
        g_canControllerStatus[controller].swObjectHandle = g_SwObjectHandle;
        g_canControllerStatus[controller].currentBaudrateIndex = (uint8)(g_canControllersInfoPtr[controller].defaultBaudrateIndex);
    #if (STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE)
        for(circleCnt = 0U; circleCnt < CAN_NOOF_TX_HW_BUFF_AVAILABLE; circleCnt++)
        {
            g_CanTxSwObjPriority[circleCnt] = CAN_SWOBJECT_INVALID_VAL;
        }
        g_canControllerStatus[controller].txSwObjPriorityPtr = g_CanTxSwObjPriority;
    #endif /* STD_OFF == CAN_TX_INTERRUPT_HANDLE_ENABLE */
        controller++;
    }
}

/*!
* @brief    Transmit a CAN frame
*
* @param[in]    Hth         The HW-transmit handle
* @param[in]    PduInfoPtr  Pointer to the PDU
*/
FUNC(Std_ReturnType, CAN_CODE) Can_Hw_Write(
    Can_HwHandleType Hth,
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_CONST) PduInfoPtr)
{
#if (STD_ON == CAN_ENABLE_FD_MODE)
    VAR(uint8, AUTOMATIC) baudrateIndex = 0U;
    P2CONST(Can_ControllerInfoType, AUTOMATIC, CAN_APPL_CONST) ctrlInfo = NULL_PTR;
#endif /* STD_ON == CAN_ENABLE_FD_MODE */

    P2CONST(Can_TxMbConfigsContainerType, AUTOMATIC, CAN_APPL_CONST) txMbConfigContainerPtr = 
        g_canConfigPtr->txMbConfigContainerPtr;
    VAR(uint16, AUTOMATIC) mbGlobalIndex = 0U;
    VAR(uint8, AUTOMATIC) controller = 0U;
    VAR(boolean, AUTOMATIC) fdEnable = (boolean)FALSE;
    VAR(Std_ReturnType, AUTOMATIC) result = CAN_BUSY;
#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
    VAR(Std_ReturnType, AUTOMATIC) findRes = (Std_ReturnType)E_NOT_OK;
#endif

    /* Calculate the MB index. search any MB to be free, MBs that have the same ObjectID. */
    while (mbGlobalIndex < txMbConfigContainerPtr->txMbCount)
    {
        if (((txMbConfigContainerPtr->txMbConfigPtr)[mbGlobalIndex]).txHwObjId == Hth)
        {
        #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
            findRes = (Std_ReturnType)E_OK;
        #endif
            break;
        }
        else
        {
            /* Intentionally Empty */
        }
        mbGlobalIndex++;
    }

#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
    if((Std_ReturnType)E_OK == findRes)
    {
#endif
        /* Get the controller ID */
        controller = ((txMbConfigContainerPtr->txMbConfigPtr)[mbGlobalIndex]).hwControllerId;

    #if (STD_ON == CAN_ENABLE_FD_MODE)
        /* Check if FD baudrate is enabled */
        baudrateIndex = g_canControllerStatus[controller].currentBaudrateIndex;
        ctrlInfo = &g_canConfigPtr->controllersInfoPtr[controller];
        fdEnable = ((uint32)CAN_CCCR_FDOE_MASK == ((ctrlInfo->baudrateConfigs[baudrateIndex].isoAndFdConfig) & CAN_CCCR_FDOE_MASK)) ?
                   (boolean)TRUE : (boolean)FALSE;
    #endif /* STD_ON == CAN_ENABLE_FD_MODE */

    #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
        result = Can_Hw_CheckPayloadLength(PduInfoPtr, 
#if (STD_OFF == CAN_ENABLE_FD_MODE)
                                           mbGlobalIndex, 
#endif
                                           fdEnable, controller);
        if ((Std_ReturnType)E_OK == result)
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
        {
        #if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
            /* Check if pretended networking is activated, if yes, return CAN_BUSY. */
            if ((boolean)TRUE == g_canControllerStatus[controller].icomEnableStatus)
            {
                result = CAN_BUSY;
            }
            else
        #endif /* STD_ON == CAN_PUBLIC_ICOM_ENABLE */
            {
            #if (STD_ON == CAN_MULTIPLEXED_TRANSMISSION_ENABLE)
                /* Find a free MB for transmission if multiplexed transmission is enabled */
                do
                {
            #endif /* STD_ON == CAN_MULTIPLEXED_TRANSMISSION_ENABLE */
        
                    result = Can_Hw_WriteMb(controller, mbGlobalIndex, PduInfoPtr);
        
            #if (STD_ON == CAN_MULTIPLEXED_TRANSMISSION_ENABLE)
                    mbGlobalIndex++;
                } 
                while ((CAN_BUSY == result) && (mbGlobalIndex < txMbConfigContainerPtr->txMbCount) &&
                         (((txMbConfigContainerPtr->txMbConfigPtr)[mbGlobalIndex]).txHwObjId == Hth));
            #endif /* STD_ON == CAN_MULTIPLEXED_TRANSMISSION_ENABLE */
            }
        }
    #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
        else
        {
            /* Intentionally Empty */
        }
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
    }
    else
    {
        /* Intentionally Empty */
    }
#endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
    (void)fdEnable;

    return result;
}

/*!
* @brief    Check if bus off occurred for the controller
*
* @param[in]    Controller  Index of the controller
*
* @retval   E_OK:       Controller is in bus off state
* @retval   E_NOT_OK:   Controller is not in bus off state
*/
FUNC(Std_ReturnType, CAN_CODE) Can_Hw_IsBusOff(VAR(uint8, AUTOMATIC) Controller)
{
    VAR(Std_ReturnType, AUTOMATIC) result = E_NOT_OK;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;

    /* Check if the bus off flag is set */
    result = ((CAN_PSR_BO_MASK == (CAN_PSR_BO_MASK & (uint32)REG_READ32(CAN_PSR_REG_ADDR(hwOffset)))) && 
              (CAN_IR_BO_MASK == (CAN_IR_BO_MASK & (uint32)REG_READ32(CAN_IR_REG_ADDR(hwOffset))))) ?
             (Std_ReturnType)E_OK : (Std_ReturnType)E_NOT_OK;

    return result;
}

/*!
* @brief    Process the bus off interrupt
* @param[in]   Controller  Index of the controller
*/
FUNC(void, CAN_CODE) Can_Hw_BusOffHandler(CONST(uint8, AUTOMATIC) Controller)
{
    Can_Hw_CancelPendingTx(Controller);
}

/*!
* @brief    Get controller error state
*
* @param[in]    Controller  Index of the controller
*/
FUNC(Can_ErrorStateType, CAN_CODE) Can_Hw_GetControllerErrorState(VAR(uint8, AUTOMATIC) Controller)
{
    VAR(Can_ErrorStateType, AUTOMATIC) errorState = CAN_ERRORSTATE_ACTIVE;
    VAR(uint32, AUTOMATIC) errorValue = 0U;
    VAR(uint8, AUTOMATIC) hwOffset = 0U;

    /* Get the error state value */
    hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    errorValue = REG_READ32(CAN_PSR_REG_ADDR(hwOffset));

    if(CAN_PSR_BO_MASK == (errorValue & CAN_PSR_BO_MASK))
    {
        errorState = CAN_ERRORSTATE_BUSOFF;
    }
    else
    {
       if (CAN_PSR_EP_MASK == (errorValue & CAN_PSR_EP_MASK))
        {
            errorState = CAN_ERRORSTATE_PASSIVE;
        }
        else
        {
            errorState = CAN_ERRORSTATE_ACTIVE;
        }
    }


    return errorState;
}

/*!
* @brief    Set controller mode
*
* @param[in]    Controller          Index of the controller
* @param[in]    ControllerInfoPtr   Pointer to controller configuration
* @param[in]    Transition          Transition value to request new CAN controller mode
* @param[in]    NotifyCanIf         Whether or not to notify CanIf
*
* @retval   E_OK:       Operation was successful
* @retval   E_NOT_OK:   Operation was failed
*/
FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetControllerMode(
    VAR(uint8, AUTOMATIC) Controller,
    VAR(Can_ControllerStateType, AUTOMATIC) Transition,
    VAR(boolean, AUTOMATIC) NotifyCanIf)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;

    if (CAN_CS_SLEEP == Transition)
    {
        result = Can_Hw_SetControllerToSleepMode(Controller);
    }
    else if (CAN_CS_STARTED == Transition)
    {
        result = Can_Hw_SetControllerToStartMode(Controller);
    }
    else if (CAN_CS_STOPPED == Transition)
    {
        result = Can_Hw_SetControllerToStopMode(Controller, NotifyCanIf);
    }
    else
    {
#if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CAN_H_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                              (uint8)CAN_SID_SET_CONTROLLER_MODE, (uint8)CAN_E_TRANSITION);
#endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
    }
    
    return result;
}

/*!
* @brief    Initialize baudrate for the controller
*
* @param[in]    HwOffset        The hardware offset of the controller
* @param[in]    Controller      Index of the controller
* @param[in]    BaudrateIndex   Index of baudrate configuration
*/
static FUNC(void, CAN_CODE) Can_Hw_InitBaudrate(
    CONST(uint8, AUTOMATIC) HwOffset,
    CONST(uint8, AUTOMATIC) Controller,
    CONST(uint8, AUTOMATIC) BaudrateIndex)
{
    VAR(Can_ControllerInfoPtrType, AUTOMATIC) ctrlInfo = &(g_canConfigPtr->controllersInfoPtr[Controller]);
    VAR(uint32, AUTOMATIC) ctrlRegValue = 0U;
    VAR(uint32, AUTOMATIC) nbtpRegValue = 0U;
#if (STD_ON == CAN_ENABLE_FD_MODE)
    VAR(uint32, AUTOMATIC) dbtpRegValue = 0U;
#endif /* STD_ON == CAN_ENABLE_FD_MODE */

    ctrlRegValue = g_canControllerStaticConfigPtr[Controller].controllerOptions;
    SchM_Enter_Can_CAN_CRITICAL_SECTION5();
    REG_RMW32(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_CONFIG_MASK_U32, ctrlRegValue);
    SchM_Exit_Can_CAN_CRITICAL_SECTION5();

    /* Configure the normal baudrate */
    nbtpRegValue = ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].baudRate.timeSegment2) |
                   ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].baudRate.timeSegment1 << CAN_NBTP_NTSEG1_SHIFT) |
                   ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].baudRate.prescaler << CAN_NBTP_NBRP_SHIFT) |
                   ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].baudRate.syncJumpWidth << CAN_NBTP_NSJW_SHIFT);

    SchM_Enter_Can_CAN_CRITICAL_SECTION5();
    REG_WRITE32(CAN_NBTP_REG_ADDR(HwOffset), nbtpRegValue);
    SchM_Exit_Can_CAN_CRITICAL_SECTION5();

#if (STD_ON == CAN_ENABLE_FD_MODE)
    /* Configure the CAN FD baudrate if CAN FD is supported */
    if(CAN_CCCR_FDOE_MASK == ((ctrlInfo->baudrateConfigs[BaudrateIndex].isoAndFdConfig) & CAN_CCCR_FDOE_MASK))
    {
        /* Enable the CAN FD mode */
        REG_BIT_SET32(CAN_CCCR_REG_ADDR(HwOffset), (uint32)(CAN_CCCR_FDOE_MASK));

        /* Check if CAN FD bitrate switch is enabled */
        if ((boolean)FALSE == (ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.brsEnable))
        {
            /* Disable the CAN FD bitrate switch */
            REG_BIT_CLEAR32(CAN_CCCR_REG_ADDR(HwOffset), (uint32)(CAN_CCCR_BRSE_MASK));
        }
        else
        {
            /* Configure CAN FD baudrate */
            dbtpRegValue = ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.syncJumpWidth) |
                           ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.timeSegment2 << CAN_DBTP_DTSEG2_SHIFT) |
                           ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.timeSegment1 << CAN_DBTP_DTSEG1_SHIFT) |
                           ((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.prescaler << CAN_DBTP_DBRP_SHIFT);
            
            SchM_Enter_Can_CAN_CRITICAL_SECTION5();
            REG_WRITE32(CAN_DBTP_REG_ADDR(HwOffset), dbtpRegValue);
            SchM_Exit_Can_CAN_CRITICAL_SECTION5();

            /* Enable the CAN FD bitrate switch and FD mode */
            REG_BIT_SET32(CAN_CCCR_REG_ADDR(HwOffset), (uint32)(CAN_CCCR_BRSE_MASK));

         /* Configure the CAN FD Frame Specification */
    #if (STD_ON == CAN_CONTROLLER_ENABLE_ISO_CANFD)
        REG_RMW32(CAN_CCCR_REG_ADDR(HwOffset), CAN_CCCR_NISO_MASK,
                  ((uint32)(ctrlInfo->baudrateConfigs[BaudrateIndex].isoAndFdConfig & CAN_CCCR_NISO_MASK)));
    #endif
        }

        /* Check if transceiver delay compensation is enabled and set Transceiver Delay Compensation offset */
        if((boolean)TRUE == ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.tranceiverDelayComEnable)
        {
            REG_BIT_SET32(CAN_DBTP_REG_ADDR(HwOffset), (uint32)(CAN_DBTP_TDC_MASK));
            REG_RMW32(CAN_TDCR_REG_ADDR(HwOffset), CAN_TDCR_TDCO_MASK | CAN_TDCR_TDCF_MASK, 
                      ((((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.tranceiverDelayOffset << CAN_TDCR_TDCO_SHIFT)) | 
                      (((uint32)ctrlInfo->baudrateConfigs[BaudrateIndex].fastBaudRate.tranceiverDelayFilterWindow << CAN_TDCR_TDCF_SHIFT))));
        }
        else
        {
            /* Intentionally Empty */
        }
    }
    else
    {
        /* nothing */
    }
#endif /* STD_ON == CAN_ENABLE_FD_MODE */
}

/*!
* @brief    Initialize Tx message buffers
*
* @param[in]    Controller  Index of the controller
* @param[in]    HwOffset    The hardware offset of the controller
*/
static FUNC(void, CAN_CODE) Can_Hw_InitTxMBs(CONST(uint8, AUTOMATIC) Controller, 
    CONST(uint8, AUTOMATIC) HwOffset)
{
    P2CONST(Can_TxConfigType, AUTOMATIC, CAN_APPL_CONST) txConfigPtr = g_canConfigPtr->txConfigPtr;
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_CONST) msgRamConfigPtr = g_canConfigPtr->msgRamConfigPtr;
    VAR(uint32, AUTOMATIC) canTxSlotIndex = 0U;

    if(0U != msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_TX_BUFFERS])
    {
        /* Set Tx element data field size */
        REG_RMW32(CAN_TXESC_REG_ADDR(HwOffset), CAN_TXESC_TBDS_MASK, 
            (uint32)txConfigPtr->txBufferDataFieldSize << CAN_TXESC_TBDS_SHIFT);
        /* set Tx buffers start address in the Message RAM */
        REG_RMW32(CAN_TXBC_REG_ADDR(HwOffset), CAN_TXBC_TBSA_MASK, 
            (((msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_TX_BUFFERS]) - CAN_SRAM_BASEADDR
                ) >> CAN_RAM_ADDRESS_SHIFT_VAL) << CAN_TXBC_TBSA_SHIFT);
        
        if ((CAN_TX_MODE_DEDICATE_BUF == txConfigPtr->txMode) ||
            (CAN_TX_MODE_SHARE_FIFO == txConfigPtr->txMode) ||
            (CAN_TX_MODE_SHARE_QUEUE == txConfigPtr->txMode))
        {
            /* dedicated TX buffers operation */
            /* select number of Tx buffers */
            REG_RMW32(CAN_TXBC_REG_ADDR(HwOffset), (uint32)CAN_TXBC_NDTB_MASK, 
                (uint32)msgRamConfigPtr->txDedBuffCount << CAN_TXBC_NDTB_SHIFT);
            
            if((CAN_TX_MODE_SHARE_FIFO == txConfigPtr->txMode) || (CAN_TX_MODE_SHARE_QUEUE == txConfigPtr->txMode))
            {
                if(CAN_TX_MODE_SHARE_FIFO == txConfigPtr->txMode)
                {
                    /* Set Tx FIFO mode */
                    REG_BIT_CLEAR32(CAN_TXBC_REG_ADDR(HwOffset), CAN_TXBC_TFQM_MASK);
                }
                else if(CAN_TX_MODE_SHARE_QUEUE == txConfigPtr->txMode)
                {
                    /* Set Tx Queue mode */
                    REG_BIT_SET32(CAN_TXBC_REG_ADDR(HwOffset), CAN_TXBC_TFQM_MASK);
                }
                else
                {
                    /* Intentionally Empty */
                }

                /* Select number of Tx buffers to be used as Tx FIFO/Queue */
                REG_RMW32(CAN_TXBC_REG_ADDR(HwOffset), CAN_TXBC_TFQS_MASK, (uint32)msgRamConfigPtr->txFifoQueueSize << CAN_TXBC_TFQS_SHIFT);
            }
            else
            {
                /* nothing */
            }
            
            /* Enable Tx buffers transmission interrupts */
            REG_WRITE32(CAN_TXBTIE_REG_ADDR(HwOffset), txConfigPtr->txBufIntEnableBits);
        
            /* Enable Tx buffers cancellation finished interrupts */
            REG_WRITE32(CAN_TXBCIE_REG_ADDR(HwOffset), txConfigPtr->txBufCancelIntEnableBits);
            
        }
        else if((CAN_TX_MODE_FIFO == txConfigPtr->txMode) || (CAN_TX_MODE_QUEUE == txConfigPtr->txMode))
        {
            if(CAN_TX_MODE_FIFO == txConfigPtr->txMode)
            {
                /* Set Tx FIFO mode */
                REG_BIT_CLEAR32(CAN_TXBC_REG_ADDR(HwOffset), CAN_TXBC_TFQM_MASK);
            }
            else if(CAN_TX_MODE_QUEUE == txConfigPtr->txMode)
            {
                /* Set Tx Queue mode */
                REG_BIT_SET32(CAN_TXBC_REG_ADDR(HwOffset), CAN_TXBC_TFQM_MASK);
            }
            else
            {
                /* Intentionally Empty */
            }
            
            /* Select number of Tx buffers to be used as Tx FIFO/Queue */
            REG_RMW32(CAN_TXBC_REG_ADDR(HwOffset), CAN_TXBC_TFQS_MASK, 
                (uint32)msgRamConfigPtr->txFifoQueueSize << CAN_TXBC_TFQS_SHIFT);

            /* Enable Tx buffers transmission interrupts */
            REG_WRITE32(CAN_TXBTIE_REG_ADDR(HwOffset), txConfigPtr->txBufIntEnableBits);
        
            /* Enable Tx buffers cancellation finished interrupts */
            REG_WRITE32(CAN_TXBCIE_REG_ADDR(HwOffset), txConfigPtr->txBufCancelIntEnableBits);
        }
        else
        {
            /* Intentionally Empty */
        }

        /* Clear mask before usage */
        g_canControllerStatus[Controller].txMask = 0;
        
        /* Arrive at the Tx slots available */
        /* Create Mask for Tx Queue and Dedicated */
        for(canTxSlotIndex = 0U; canTxSlotIndex < ((uint32)
           ((uint32)msgRamConfigPtr->txFifoQueueSize + (uint32)msgRamConfigPtr->txDedBuffCount)); canTxSlotIndex++)
        {
            g_canControllerStatus[Controller].txMask |= ((uint32)1U << canTxSlotIndex);
        }
        
        /* Copy to back-up buffer mask as well */
        g_canControllerStatus[Controller].backupTxMask = g_canControllerStatus[Controller].txMask;
    }
    else
    {
        /* Intentionally Empty */
    }
}

/*!
* @brief    Initialize Tx event FIFO
*
* @param[in]    HwOffset    The hardware offset of the controller
*/
static FUNC(void, CAN_CODE) Can_Hw_InitTxEvtFifo(CONST(uint8, AUTOMATIC) HwOffset)
{
    P2CONST(Can_TxConfigType, AUTOMATIC, CAN_APPL_CONST) txConfigPtr = g_canConfigPtr->txConfigPtr;
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_CONST) msgRamConfigPtr = g_canConfigPtr->msgRamConfigPtr;

    if(msgRamConfigPtr->txEvntFIFOSize > 0U)
    {
        /* Set the Tx event fifo start address */
        REG_RMW32(CAN_TXEFC_REG_ADDR(HwOffset), CAN_TXEFC_EFSA_MASK, 
            (((msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_TX_EVENT_FIFO]) - CAN_SRAM_BASEADDR
                ) >> CAN_RAM_ADDRESS_SHIFT_VAL) << CAN_TXEFC_EFSA_SHIFT);
        /* Set the Tx event fifo size */
        REG_RMW32(CAN_TXEFC_REG_ADDR(HwOffset), CAN_TXEFC_EFS_MASK, 
            (uint32)msgRamConfigPtr->txEvntFIFOSize << CAN_TXEFC_EFS_SHIFT);
        /* Set the Tx event fifo watermark */
        REG_RMW32(CAN_TXEFC_REG_ADDR(HwOffset), CAN_TXEFC_EFWM_MASK, 
            (uint32)txConfigPtr->txEventFifoThreshold << CAN_TXEFC_EFWM_SHIFT);
    }
    else
    {
        /* Intentionally Empty */
    }
}

/*!
* @brief    Initialize the Rx filters
*
* @param[in]    HwOffset    The hardware offset of the controller
*/
static FUNC(void, CAN_CODE) Can_Hw_InitFilters(CONST(uint8, AUTOMATIC) HwOffset)
{
    VAR(uint8, AUTOMATIC)  filterEleIndex = 0U;
    P2CONST(Can_FilterConfigType, AUTOMATIC, CAN_APPL_CONST) filterConfigPtr = g_canConfigPtr->filterConfigPtr;
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_CONST) msgRamConfigPtr = g_canConfigPtr->msgRamConfigPtr;

    if(filterConfigPtr->standardListSize > 0U)
    {
        /* Standard filter configuration */
        if ((CAN_MSG_ID_LEN_STANDARD == filterConfigPtr->msgIdLen) ||
            (CAN_MSG_ID_LEN_BOTH == filterConfigPtr->msgIdLen))
        {
            /* Set standard filter start address */
            REG_RMW32(CAN_SIDFC_REG_ADDR(HwOffset), CAN_SIDFC_FLSSA_MASK, 
                (((msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_STD_FILTERS]) - 
                   CAN_SRAM_BASEADDR) >> CAN_RAM_ADDRESS_SHIFT_VAL) << CAN_SIDFC_FLSSA_SHIFT);
            /* Set standard filter element size */
            REG_RMW32(CAN_SIDFC_REG_ADDR(HwOffset), CAN_SIDFC_LSS_MASK, 
                (uint32)filterConfigPtr->standardListSize << CAN_SIDFC_LSS_SHIFT);
            /* Set standard filter no matching action */
            REG_RMW32(CAN_GFC_REG_ADDR(HwOffset), CAN_GFC_ANFS_MASK, 
                (uint32)filterConfigPtr->standardFilterForNonMatchingFrames << CAN_GFC_ANFS_SHIFT);
            /* Set standard filter remote frame action */
            if((boolean)TRUE == filterConfigPtr->rejectRemoteFramesWithStandardId)
            {
                REG_BIT_SET32(CAN_GFC_REG_ADDR(HwOffset), CAN_GFC_RRFS_MASK);
            }
            else
            {
                REG_BIT_CLEAR32(CAN_GFC_REG_ADDR(HwOffset), CAN_GFC_RRFS_MASK);
            }
        
            /* Initialization of standard ID filter elements */
            for(filterEleIndex = 0U; filterEleIndex < filterConfigPtr->standardListSize; filterEleIndex++)
            {
                Can_Hw_InitStandardFilterEle(&(filterConfigPtr->standardFiltersPtr)[filterEleIndex]);
            }
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        /* Intentionally Empty */
    }
    
    if(filterConfigPtr->extendedListSize > 0U)
    {
        /* Extended filter configuration */
        if ((CAN_MSG_ID_LEN_EXTENDED == filterConfigPtr->msgIdLen) ||
            (CAN_MSG_ID_LEN_BOTH == filterConfigPtr->msgIdLen))
        {
            /* Set extended filter start address */
            REG_RMW32(CAN_XIDFC_REG_ADDR(HwOffset), CAN_XIDFC_FLESA_MASK, 
                (((msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_EXT_FILTERS]) - 
                   CAN_SRAM_BASEADDR) >> CAN_RAM_ADDRESS_SHIFT_VAL) << CAN_XIDFC_FLESA_SHIFT);
            /* Set extended filter element size */
            REG_RMW32(CAN_XIDFC_REG_ADDR(HwOffset), CAN_XIDFC_LSE_MASK, 
                (uint32)filterConfigPtr->extendedListSize << CAN_XIDFC_LSE_SHIFT);
            /* Set extended filter no matching action */
            REG_RMW32(CAN_GFC_REG_ADDR(HwOffset), CAN_GFC_ANFE_MASK, 
                (uint32)filterConfigPtr->extendedFilterForNonMatchingFrames << CAN_GFC_ANFE_SHIFT);
            /* Set extended filter remote frame action */
            if((boolean)TRUE == filterConfigPtr->rejectRemoteFramesWithExtendedId)
            {
                REG_BIT_SET32(CAN_GFC_REG_ADDR(HwOffset), CAN_GFC_RRFE_MASK);
            }
            else
            {
                REG_BIT_CLEAR32(CAN_GFC_REG_ADDR(HwOffset), CAN_GFC_RRFE_MASK);
            }
        
            /* Initialization of extended ID filter elements */
            for(filterEleIndex = 0U; filterEleIndex < filterConfigPtr->extendedListSize; filterEleIndex++)
            {
                Can_Hw_InitExtendedFilterEle(&(filterConfigPtr->extendedFiltersPtr)[filterEleIndex]);
            }
        }
        else
        {
            /* nothing */
        }
    }
    else
    {
        /* Intentionally Empty */
    }
}

/*!
* @brief    Initialize Rx message dedicated buffers
*
* @param[in]    HwOffset    The hardware offset of the controller
*/
static FUNC(void, CAN_CODE) Can_Hw_InitRxMBs(CONST(uint8, AUTOMATIC) HwOffset)
{
    P2CONST(Can_RxConfigType, AUTOMATIC, CAN_APPL_CONST) rxConfigPtr = g_canConfigPtr->rxConfigPtr;
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_CONST) msgRamConfigPtr = g_canConfigPtr->msgRamConfigPtr;

    /* Config the RX Buffer */
    if((CAN_RX_MODE_DEDICATE_BUF == rxConfigPtr->rxMode) || (CAN_RX_MODE_SHARE_FIFO0 == rxConfigPtr->rxMode) ||
       (CAN_RX_MODE_SHARE_FIFO0 == rxConfigPtr->rxMode)  || (CAN_RX_MODE_SHARE_ALL == rxConfigPtr->rxMode))
    {
        /* Set Rx buffer data length */
        REG_RMW32(CAN_RXESC_REG_ADDR(HwOffset), CAN_RXESC_RBDS_MASK, 
            (uint32)rxConfigPtr->rxBufferDataFieldSize << CAN_RXESC_RBDS_SHIFT);
        /* Set Rx buffer start address in the Message RAM */
        REG_RMW32(CAN_RXBC_REG_ADDR(HwOffset), CAN_RXBC_RBSA_MASK, 
            ((((msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_BUFFERS]) - 
                CAN_SRAM_BASEADDR) >> CAN_RAM_ADDRESS_SHIFT_VAL)) << CAN_RXBC_RBSA_SHIFT);
    }
    else
    {
        /* nothing */
    }
}

/*!
* @brief    Initialize Rx Fifo for a CAN controller
*
* @param[in]    HwOffset    Hardware offset of the controller
*/
#if (STD_ON == CAN_RXFIFO_ENABLE)
static FUNC(void, CAN_CODE) Can_Hw_InitRxFiFo(CONST(uint8, AUTOMATIC) HwOffset)
{
    P2CONST(Can_RxConfigType, AUTOMATIC, CAN_APPL_CONST) rxConfigPtr = g_canConfigPtr->rxConfigPtr;
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_CONST) msgRamConfigPtr = g_canConfigPtr->msgRamConfigPtr;
    
    SchM_Enter_Can_CAN_CRITICAL_SECTION11();
    /* Config the RX FIFO0 */
    if(((CAN_RX_MODE_FIFO0 == rxConfigPtr->rxMode) || (CAN_RX_MODE_SHARE_FIFO0 == rxConfigPtr->rxMode) ||
       (CAN_RX_MODE_SHARE_ALL == rxConfigPtr->rxMode)) && (msgRamConfigPtr->rxFIFO0Size > 0U))
    {
        /* Set Rx FIFO0 data length */
        REG_RMW32(CAN_RXESC_REG_ADDR(HwOffset), CAN_RXESC_F0DS_MASK, 
            (uint32)rxConfigPtr->rxFifo0DataFieldSize << CAN_RXESC_F0DS_SHIFT);
        /* Set Rx FIFO0 start address in the Message RAM */
        REG_RMW32(CAN_RXF0C_REG_ADDR(HwOffset), CAN_RXF0C_F0SA_MASK, 
            (((msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_FIFO0]) - 
               CAN_SRAM_BASEADDR) >> CAN_RAM_ADDRESS_SHIFT_VAL) << CAN_RXF0C_F0SA_SHIFT);
        /* Set Rx FIFO0 size */
        REG_RMW32(CAN_RXF0C_REG_ADDR(HwOffset), CAN_RXF0C_F0S_MASK, 
            (uint32)msgRamConfigPtr->rxFIFO0Size << CAN_RXF0C_F0S_SHIFT);
        /* Set Rx FIFO0 watermark level */
        REG_RMW32(CAN_RXF0C_REG_ADDR(HwOffset), CAN_RXF0C_F0WM_MASK, 
            (uint32)rxConfigPtr->rxFifo0WatermarkLevel << CAN_RXF0C_F0WM_SHIFT);
        /* Set Rx FIFO0 operating mode */
        REG_RMW32(CAN_RXF0C_REG_ADDR(HwOffset), CAN_RXF0C_F0OM_MASK, 
            (uint32)rxConfigPtr->rxFifo0OperatingMode << CAN_RXF0C_F0OM_SHIFT);
    }
    else
    {
        /* nothing */
    }
    
    /* Config the RX FIFO1 */
    if(((CAN_RX_MODE_FIFO1 == rxConfigPtr->rxMode) || (CAN_RX_MODE_SHARE_FIFO1 == rxConfigPtr->rxMode) ||
       (CAN_RX_MODE_SHARE_ALL == rxConfigPtr->rxMode)) && (msgRamConfigPtr->rxFIFO1Size > (uint8)0))
    {
        /* Set Rx FIFO1 data length */
        REG_RMW32(CAN_RXESC_REG_ADDR(HwOffset), CAN_RXESC_F1DS_MASK, 
            (uint32)rxConfigPtr->rxFifo1DataFieldSize << CAN_RXESC_F1DS_SHIFT);
        /* Set Rx FIFO1 start address in the Message RAM */
        REG_RMW32(CAN_RXF1C_REG_ADDR(HwOffset), CAN_RXF1C_F1SA_MASK, 
            ((((msgRamConfigPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_RX_FIFO1]) - 
                CAN_SRAM_BASEADDR) >> CAN_RAM_ADDRESS_SHIFT_VAL)) << CAN_RXF1C_F1SA_SHIFT);
        /* Set Rx FIFO1 size */
        REG_RMW32(CAN_RXF1C_REG_ADDR(HwOffset), CAN_RXF1C_F1S_MASK, 
            (uint32)msgRamConfigPtr->rxFIFO1Size << CAN_RXF1C_F1S_SHIFT);
        /* Set Rx FIFO1 watermark level */
        REG_RMW32(CAN_RXF1C_REG_ADDR(HwOffset), CAN_RXF1C_F1WM_MASK, 
            (uint32)rxConfigPtr->rxFifo1WatermarkLevel << CAN_RXF1C_F1WM_SHIFT);
        /* Set Rx FIFO1 operating mode */
        REG_RMW32(CAN_RXF1C_REG_ADDR(HwOffset), CAN_RXF1C_F1OM_MASK, 
            (uint32)rxConfigPtr->rxFifo1OperatingMode << CAN_RXF1C_F1OM_SHIFT);
    }
    else
    {
        /* nothing */
    }
    SchM_Exit_Can_CAN_CRITICAL_SECTION11();
}
#endif /* STD_ON == CAN_RXFIFO_ENABLE */

/*!
* @brief    Reset the controller
*
* @param[in]    HwOffset    The hardware offset of the controller
*/
static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_ResetController(void)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_OK;

    /* Soft reset the controller */
    Mcu_Rcm_OperationPeriphReset(ENABLE, RCM_APB1_PERIPH, RCM_AHBRST1_CAN);
    Mcu_Rcm_OperationPeriphReset(DISABLE, RCM_APB1_PERIPH, RCM_AHBRST1_CAN);

    return result;
}

/*!
* @brief    Set controller to stop mode
*
* @param[in]    Controller          Index of the controller
* @param[in]    ControllerInfoPtr   Pointer to controller configuration
* @param[in]    NotifyCanIf         Whether or not to notify CanIf
*
* @retval   E_OK:       Operation was successful
* @retval   E_NOT_OK:   Operation was failed
*/
static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetControllerToStopMode(
    CONST(uint8, AUTOMATIC) Controller,
    VAR(boolean, AUTOMATIC) NotifyCanIf)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;

    switch (g_canControllerStatus[Controller].controllerState)
    {
    case CAN_CS_STARTED:
        /* Request for cancel pending request */
        Can_Hw_CancelPendingTx(Controller);
        /* Change controller state from STARTED to STOPPED */
        if ((Std_ReturnType)E_OK != Can_Hw_WaitEnterInitMode(hwOffset))
        {
            break;
        }
        else
        {
#if (STD_OFF == CAN_PUBLIC_ICOM_ENABLE)
            result = (Std_ReturnType)E_OK;
#endif
        }

        /* Check if interrupts are enabled by Can_EnableControllerInterrupts */
        if (CAN_INTERRUPT_ENABLED == g_canControllerStatus[Controller].interruptMode)
        {
            /* Disable all interrupts */
            REG_WRITE32(CAN_IE_REG_ADDR(hwOffset), 0U);
        }
        else
        {
            /* Intentionally Empty */
        }

        /* Clear all interrupt flags */
        REG_WRITE32(CAN_IR_REG_ADDR(hwOffset), 0xFFFFFFFFU);

    #if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
        /* Deactivate pretended networking before stopping the controller */
        result = Can_Hw_DeactivateIcom(Controller);
    #endif /* STD_ON == CAN_PUBLIC_ICOM_ENABLE */

         break;
    case CAN_CS_STOPPED:
        /* Return E_OK if the controller is already in STOPPED state */
        result = (Std_ReturnType)E_OK;
        break;
    case CAN_CS_SLEEP:
        /* Change controller state from SLEEP to STOPPED, nothing to do. */
        result = (Std_ReturnType)E_OK;
        break;
    default:
    #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CAN_H_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                              (uint8)CAN_SID_SET_CONTROLLER_MODE, (uint8)CAN_E_TRANSITION);
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
        result = (Std_ReturnType)E_NOT_OK;
        break;
    }

    if ((Std_ReturnType)E_OK == result)
    {
        g_canControllerStatus[Controller].controllerState = CAN_CS_STOPPED;
        if ((boolean)TRUE == NotifyCanIf)
        {
            CanIf_ControllerModeIndication(Controller, CANIF_CS_STOPPED);
        }
        else
        {
            /* Intentionally Empty */
        }
    }
    else
    {
        /* Intentionally Empty */
    }

    return result;
}

/*!
* @brief    Set controller to start mode
*
* @param[in]    Controller          Index of the controller
* @param[in]    ControllerInfoPtr   Pointer to controller configuration
*
* @retval   E_OK:       Operation was successful
* @retval   E_NOT_OK:   Operation was failed
*/
static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetControllerToStartMode(
    CONST(uint8, AUTOMATIC) Controller)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;

    switch (g_canControllerStatus[Controller].controllerState)
    {
    case CAN_CS_STOPPED:
        /* The state change is valid only from STOPPED to STARTED */
        if ((Std_ReturnType)E_OK != Can_Hw_InitController(Controller))
        {
            break;
        }
        else
        {
            /* Intentionally Empty */
        }

        /* Enable the controller */
        SchM_Enter_Can_CAN_CRITICAL_SECTION13();
        /* Clear the INIT bit region in the CCCR Register */
        REG_BIT_CLEAR32(CAN_CCCR_REG_ADDR(hwOffset), CAN_CCCR_INIT_MASK);
        /* Wait until the INIT bit is cleared */
        result = Can_Hw_WaitRegBitChange(CAN_CCCR_REG_ADDR(hwOffset), CAN_CCCR_INIT_MASK, (uint8)CAN_BIT_RESET);
        SchM_Exit_Can_CAN_CRITICAL_SECTION13();

        if((Std_ReturnType)E_OK == result)
        {
            /* Clear all interrupt flags */
            REG_WRITE32(CAN_IR_REG_ADDR(hwOffset), 0xFFFFFFFFU);

            /* Enable interrupts */
            if (g_canControllerStatus[Controller].interruptMode == CAN_INTERRUPT_ENABLED)
            {
                /* Re enable the status of Interrupts configured */
                REG_WRITE32(CAN_IE_REG_ADDR(hwOffset), g_canConfigPtr->interruptConfigPtr->intEnBits);
            }
            else
            {
                /* Intentionally Empty */
            }

            /* Read the ACT bit region in the PSR Register */
            /* Wait until the ACT bit is not 0 */
            result = Can_Hw_WaitRegBitChange(CAN_PSR_REG_ADDR(hwOffset), CAN_PSR_ACT_MASK, CAN_REGISTER_BITS_NOT_ZERO);
        }
        else
        {
            /* Intentionally Empty */
        }

    #if (STD_ON == CAN_PUBLIC_ICOM_ENABLE)
        /* Check if ICOM is enabled */
        if((E_OK == result) && (0U != g_canControllerStatus[Controller].activeIcomCfgId))
        {
            /* Deactivate ICOM */
            result = Can_Hw_DeactivateIcom(Controller);
        }
        else
        {
            /* Intentionally Empty */
        }
    #endif /* STD_ON == CAN_PUBLIC_ICOM_ENABLE */
        if(E_OK == result)
        {
            g_canControllerStatus[Controller].controllerState = CAN_CS_STARTED;
            CanIf_ControllerModeIndication(Controller, CANIF_CS_STARTED);
        }
        else
        {
            /* Intentionally Empty */
        }
        break;
    default:
    #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CAN_H_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                              (uint8)CAN_SID_SET_CONTROLLER_MODE, (uint8)CAN_E_TRANSITION);
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
        break;
    }

    return result;
}

/*!
* @brief    Set controller to sleep mode
*
* @param[in]    Controller  Index of the controller
*
* @retval   E_OK:       Operation was successful
* @retval   E_NOT_OK:   Operation was failed
*/
static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_SetControllerToSleepMode(
    CONST(uint8, AUTOMATIC) Controller)
{
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_NOT_OK;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;

    switch (g_canControllerStatus[Controller].controllerState)
    {
    case CAN_CS_STOPPED:
        /* The state change is valid only from STOPPED to SLEEP. */
        /* Set CCR with Clock Stop request */
        REG_BIT_SET32(CAN_CCCR_REG_ADDR(hwOffset), CAN_CCCR_CSR_MASK);
        /* Wait for the Clock Stop Acknowledge */
        result = Can_Hw_WaitRegBitChange(CAN_CCCR_REG_ADDR(hwOffset), CAN_CCCR_CSA_MASK, (uint8)CAN_BIT_SET);
        if((E_OK != result) )
        {
            /* Set current mode to SLEEP */
            g_canControllerStatus[Controller].controllerState = CAN_CS_SLEEP;
            CanIf_ControllerModeIndication(Controller, CANIF_CS_SLEEP);
        }
        else
        {
            /* Intentionally Empty */
        }        
        break;
    case CAN_CS_SLEEP:
        /* Return E_OK if the controller is already in SLEEP mode */
        result = (Std_ReturnType)E_OK;
        break;
    default:
    #if (STD_ON == CAN_DEV_ERROR_DETECT_ENABLE)
        (void)Det_ReportError((uint16)CAN_H_MODULE_ID, (uint8)CAN_HW_INSTANCE0,
                              (uint8)CAN_SID_SET_CONTROLLER_MODE, (uint8)CAN_E_TRANSITION);
    #endif /* STD_ON == CAN_DEV_ERROR_DETECT_ENABLE */
        break;
    }
    return result;
}

#if (STD_ON == CAN_ABORT_MB_API_ENABLE)
/*!
* @brief    Cancel transmission of a message
*
* @param[in]    Controller      Index of the controller
* @param[in]    MbGlobalIndex   Index of the MB
*/
static FUNC(void, CAN_CODE) Can_Hw_CancelMb(
    CONST(uint8, AUTOMATIC) Controller,
    VAR(uint16, AUTOMATIC) MbGlobalIndex)
{
    VAR(uint8, AUTOMATIC)  hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    VAR(uint8, AUTOMATIC)  mbIndex = ((g_canConfigPtr->txMbConfigContainerPtr->txMbConfigPtr)[MbGlobalIndex]).txBuffIndx;
    VAR(uint8, AUTOMATIC)  circleCnt = 0U;

    g_canControllerStatus[Controller].mbCancelIndex = (Can_HwHandleType)mbIndex;

    /* Check if the MB is a TX FIFO/QUEUE MB */
    if((uint8)Can_TX_FIFO_QUEUE_ID_32 == mbIndex)
    {
        /* Iterate through all the TX FIFO/QUEUE buffers and cancel them */
        for(circleCnt = CAN_TX_DEDICATED_BUF_CONFIG_NUMBER; 
            circleCnt < (CAN_TX_FIFO_QUEUE_CONFIG_SIZE + CAN_TX_DEDICATED_BUF_CONFIG_NUMBER); circleCnt++)
        {
            if (CAN_TXBRP_TRP_MASK(circleCnt) ==
                ((REG_READ32(CAN_TXBRP_REG_ADDR(hwOffset))) & ((uint32)(CAN_TXBRP_TRP_MASK(circleCnt)))))
            {
                /* Set the Tx Buffer cancel bit in the TXBCR register to abort the transmission */
                REG_BIT_SET32(CAN_TXBCR_REG_ADDR(hwOffset), (uint32)(CAN_TXBCR_CR_MASK(circleCnt)));
            }
            else
            {
                /* Intentionally Empty */
            }
        }
    }
    else
    {
        /* Check if the MB is still pending. */
        if (CAN_TXBRP_TRP_MASK(mbIndex) ==
            ((REG_READ32(CAN_TXBRP_REG_ADDR(hwOffset))) & ((uint32)(CAN_TXBRP_TRP_MASK(mbIndex)))))
        {
            /* Set the Tx Buffer cancel bit in the TXBCR register to abort the transmission */
            REG_BIT_SET32(CAN_TXBCR_REG_ADDR(hwOffset), (uint32)(CAN_TXBCR_CR_MASK(mbIndex)));
        }
        else
        {
            /* Intentionally Empty */
        }
    }
}
#endif /* STD_ON == CAN_ABORT_MB_API_ENABLE */

/*!
* @brief    Write data into the message buffer and start transmission
*
* @param[in]    Controller      Id of the controller
* @param[in]    MbGlobalIndex   Index of the MB
* @param[in]    PduInfoPtr      Pointer to the PDU
* @param[in]    EnabledFd       Whether or not enable CAN FD
*
* @retval   E_OK:       Operation was successful
* @retval   E_NOT_OK:   Operation was failed
*/
static FUNC(Std_ReturnType, CAN_CODE) Can_Hw_WriteMb(
    CONST(uint8, AUTOMATIC) Controller,
    VAR(uint16, AUTOMATIC) MbGlobalIndex,
    P2CONST(Can_PduType, AUTOMATIC, CAN_APPL_CONST) PduInfoPtr)
{
    P2CONST(Can_MessageRamConfigType, AUTOMATIC, CAN_APPL_CONST) msgRamCfgPtr = NULL_PTR;
    P2CONST(Can_TxMbConfigType, AUTOMATIC, CAN_APPL_CONST) txMbObjPtr = NULL_PTR;
    VAR(uint8, AUTOMATIC) hwOffset = g_canControllerStaticConfigPtr[Controller].controllerOffset;
    VAR(volatile uint32, AUTOMATIC) txWriteStartAddr = 0U;
    VAR(uint32, AUTOMATIC) buffIndexMask = 0U;
    VAR(uint8, AUTOMATIC) buffElementIndex = 0U;
    VAR(uint8, AUTOMATIC) txMsgDlc = 0U;
    VAR(uint8, AUTOMATIC) dataBytePos = 0U;
    VAR(uint16, AUTOMATIC) swObjIndx = 0U;
    P2VAR(Can_PduType, AUTOMATIC, CAN_APPL_DATA) tempPduInfoPtr = NULL_PTR;
    VAR(Can_PduType, AUTOMATIC) pduTemp;
    VAR(Std_ReturnType, AUTOMATIC) result = (Std_ReturnType)E_OK;
    VAR(Can_TxMsgType, AUTOMATIC)  txMsgBuffer = {0};
    P2CONST(uint32, AUTOMATIC, CAN_APPL_DATA)  txMsgBufferPtr = NULL_PTR;
    VAR(Can_TxBufModeType, AUTOMATIC) txBuffType = CAN_TX_MODE_FIFO;

    /* Set Message RAM configuration pointer with configuration address */
    msgRamCfgPtr = g_canConfigPtr->msgRamConfigPtr;
    /* Set with TX object configuration start index */
    txMbObjPtr = g_canConfigPtr->txMbConfigContainerPtr->txMbConfigPtr;
    /* Copy the buffer Type of requested HTH */
    txBuffType = txMbObjPtr[MbGlobalIndex].txBufferModeType;

    /* Set with Message RAM start address of Tx buffer */
    txWriteStartAddr = msgRamCfgPtr->canControllerMsgRAMMapPtr[CAN_MSG_RAM_SECTION_INDEX_TX_BUFFERS];
    
    /* Copy the buffer Index for Mask */
    buffIndexMask = ((uint32)1U << (uint32)(txMbObjPtr[MbGlobalIndex].txBuffIndx));

    /* Check Tx buffer Type for Start address calculation and buffer status */
    /* Dedicated buffer type */
    if(CAN_TX_MODE_DEDICATE_BUF == txBuffType)
    {
      /* Is buffer Free */
      if(((g_canControllerStatus[Controller].txMask & buffIndexMask) != buffIndexMask) ||
          (CAN_TXBRP_TRP_MASK(txMbObjPtr[MbGlobalIndex].txBuffIndx) == REG_BIT_GET32(CAN_TXBRP_REG_ADDR(hwOffset), 
           CAN_TXBRP_TRP_MASK(txMbObjPtr[MbGlobalIndex].txBuffIndx))))
      {
          result = CAN_BUSY;
      }
      else
      {
          /* Copy the exact buffer element offset */
          buffElementIndex = txMbObjPtr[MbGlobalIndex].txBuffIndx;
      }
    }
    else
    {
      /* Check TXQUEUE is Free or not */
      if(CAN_TXFQS_TFQF_MASK == REG_BIT_GET32(CAN_TXFQS_REG_ADDR(hwOffset), CAN_TXFQS_TFQF_MASK))
      {
          result = CAN_BUSY;
      }
      else
      {
        /* Check for next free slot in Tx Queue */
        buffElementIndex = Can_Hw_CheckQueueMask(Controller);

        if(buffElementIndex == 0xFFU)
        {
            result = CAN_BUSY;
        }
        else
        {
            /* block Tx slot */
            buffIndexMask = (uint32)((uint32)1U << (uint32)buffElementIndex);
        }
      }
    }
    
    tempPduInfoPtr = &pduTemp;

#if(STD_ON == CAN_PUBLIC_ICOM_ENABLE)
    /* Check controller is enabled for pretended networking */
    if((result == E_OK) && ((boolean)TRUE == g_canControllerStatus[Controller].icomBlockWriteCalls))
    {
        result = CAN_BUSY;
    }
    else
    {
        /* nothing */
    }
#endif

#if (STD_ON == CAN_TRIGGER_TRANSMIT_ENABLE)
    if(E_OK == result)
    {
        /* Call for trigger transmit status operations */
        result = Can_Hw_UpdatePduInfo(MbGlobalIndex, tempPduInfoPtr, PduInfoPtr);
    }
#else
    /*Store the Data pointer and Data length*/
    tempPduInfoPtr->sdu = PduInfoPtr->sdu;
    tempPduInfoPtr->length = PduInfoPtr->length;
#endif

    if(E_OK == result)
    {
        /* Lock Tx Queue slot - Only if all checks are passed */
        g_canControllerStatus[Controller].txMask &= ~((uint32)1U << buffElementIndex);

        /* Get the Tx Buffer start address */
        txWriteStartAddr = (txWriteStartAddr + ((CAN_MSG_RAM_ELEMENT_HEAD_SIZE + 
            (uint32)Can_DataRegionRegValToByteSize[g_canConfigPtr->txConfigPtr->txBufferDataFieldSize]) * buffElementIndex));
        /* Reset the T0 Msg buffer being accessed */
        txMsgBuffer.txMsgT0.esi = 0U;
        /* Reset the RTR bit to avoid transmit messages triggered by
        remote transmission requests */
        txMsgBuffer.txMsgT0.rtr = 0U;
        
        /* Check if the requested Id is extended or standard */
        if(CAN_ID_IDE_U32 == (PduInfoPtr->id & CAN_ID_IDE_U32))
        {
            /* Store extended Id and set XTD bit */
            txMsgBuffer.txMsgT0.xtd = 1U;
            txMsgBuffer.txMsgT0.id  = ((PduInfoPtr->id) & CAN_PDU_EXTENDED_ID_MASK);
        }
        else
        {
            /* shift Standard Identifier to position 28..18 */
            txMsgBuffer.txMsgT0.id = (((PduInfoPtr->id) & CAN_PDU_STANDARD_ID_MASK) << CAN_MSG_STANDARD_ID_SHIFT_EIGHTEEN);
            /* Set Id Type as Standard */
            txMsgBuffer.txMsgT0.xtd = 0U;
        }
        
        /* Set DLC with requested value */
        txMsgDlc = tempPduInfoPtr->length;
        
    #if (STD_ON == CAN_ENABLE_FD_MODE)
        /* Check FD frame need to be transmit */
        if(CAN_ID_FD_DESCRIPTOR == (PduInfoPtr->id & CAN_ID_FD_DESCRIPTOR))
        {
            /* Set Tx message with FD */
            txMsgBuffer.txMsgT1.fdf = 1U;
        }
        else
        {
            /* Set Tx message with Normal */
            txMsgBuffer.txMsgT1.fdf = 0U;
        }

        /* Check CAN FD frames transmitted with bit rate switching */
        if(CAN_CCCR_BRSE_MASK == REG_BIT_GET32(CAN_CCCR_REG_ADDR(hwOffset), (uint32)(CAN_CCCR_BRSE_MASK)))
        {
            /* Enable BRS */
            txMsgBuffer.txMsgT1.brs = 1U;
        }
        else
        {
            /* Disable BRS */
            txMsgBuffer.txMsgT1.brs = 0U;
        }

        /* Check DLC length and calculate the Hw support value if DLC > 24 */
        if (tempPduInfoPtr->length > CAN_MSG_DATA_LEN_CAL_SHIFT_TWENTYFOUR)
        {
            /* Set DLC length with Hw Supported value */
            txMsgDlc = (((tempPduInfoPtr->length + CAN_MSG_DATA_LEN_CAL_FIFTEEN) >> \
                       CAN_MSG_DATA_LEN_CAL_FOUR) + CAN_MSG_DATA_LEN_CAL_ELEVEN);
        }
        /* Check DLC length and calculate the Hw support value if DLC > 8 */
        else if (tempPduInfoPtr->length > CAN_MSG_DATA_LEN_CAL_EIGHT)
        {
            /* Set DLC length with Hw Supported value */
            txMsgDlc = (((tempPduInfoPtr->length + CAN_MSG_DATA_LEN_CAL_THREE) >> \
                       CAN_MSG_DATA_LEN_CAL_TWO) + CAN_MSG_DATA_LEN_CAL_SIX);
        }
        else
        {
            /* Do Nothing */
        }
    #endif
        
        /* Write DLC value to the T1 buffer */
        txMsgBuffer.txMsgT1.dlc = txMsgDlc;
        
        /* Write Event FIFO */
        txMsgBuffer.txMsgT1.efc = 1U;
        
        /* Calculate Sw Obj Handle index */
        swObjIndx = (uint16)(((uint16)Controller * CAN_NOOF_TX_HW_BUFF_AVAILABLE) + buffElementIndex);
        /* Store sPduHandle Id for Tx confirmation process */
        g_canControllerStatus[Controller].swObjectHandle[swObjIndx] = PduInfoPtr->swPduHandle;
        /* Write Message Marker with mb Index for the Tx confirmation process */
        txMsgBuffer.txMsgT1.mm = buffElementIndex;
        
        /* Set data byte position with zero index */
        dataBytePos = 0U;
        
    #if (STD_ON == CAN_ENABLE_FD_MODE)
        /* Convert DLC length to Number of Data Bytes supported by Hw */
        txMsgDlc = Can_GblFdDlcConvDb[txMsgDlc];
    #endif
        
        /* Set loop for write with Number of Data Byte */
        while(txMsgDlc > dataBytePos)
        {
          #if (STD_OFF == CAN_ENABLE_FD_MODE )
          /* Store the data to the Tx Buffer */
          txMsgBuffer.txMsgDb[dataBytePos].db = tempPduInfoPtr->sdu[dataBytePos];
          #else
          /* Check byte position is with in the DLC */
          if(dataBytePos < tempPduInfoPtr->length)
          {
            /* Store the data to the Tx Buffer */
            /* Copy Message data to the Tx Buffer */
            txMsgBuffer.txMsgDb[dataBytePos].db = tempPduInfoPtr->sdu[dataBytePos];
          }
          else
          {
            /* Store with padding values to the Tx buffer */
            txMsgBuffer.txMsgDb[dataBytePos].db = txMbObjPtr[MbGlobalIndex].canFdPaddValue;
          }
          #endif
        
          /* Set for next data byte */
          dataBytePos++;
        }

        /* Write the prepared Tx message buffer to the Message RAM */
        /*** @warning Can_Hw_c_MISRA_REF2 Casting to different object pointer type. */
        txMsgBufferPtr = (uint32*)&txMsgBuffer;

        for(dataBytePos = (uint8)0; dataBytePos < (CAN_MSG_RAM_ELEMENT_HEAD_SIZE + txMsgDlc); dataBytePos += (uint8)4)
        {
            *((uint32*)txWriteStartAddr) = *txMsgBufferPtr;
            txWriteStartAddr += (uint32)4;
            txMsgBufferPtr++;
        }

        /* Request for the Transmission */
        REG_BIT_SET32(CAN_TXBAR_REG_ADDR(hwOffset), buffIndexMask);
        g_canControllerStatus[Controller].txMask |= ((uint32)1U << buffElementIndex);
    }
    else
    {
        /* nothing */
    }

    return result;
}

#if (STD_ON == CAN_ENABLE_ERM)
/*!
* @brief    Initialize the Error Reporting Module (ERM)
*
* @param[in]    HwOffset      Id of the controller
*/
static FUNC(void, CAN_CODE) Can_Hw_InitErm(void)
{
    P2CONST(Can_ErmConfigType, AUTOMATIC, CAN_APPL_CONST) ermConfigPtr = g_canConfigPtr->ermConfigPtr;
    /* Set ERM with default values */
    REG_WRITE32(CAN_ERM_CTRL_REG_ADDR, ermConfigPtr->ermControlReg);

    /* Clear the sts flag */
    REG_WRITE32(CAN_ERM_STS_REG_ADDR, 0x07U);
}
#endif

#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"

/**@} end of group CAN_Fuctions */
#ifdef __cplusplus
}
#endif
/**@} end of group CAN_Driver */
/**@} end of group G32A10xx_StdPeriphDriver */
