/**
 *  @file FlexCAN_Ip_HwAccess.c
 *
 *  @brief FlexCAN Functions to Hardware Acess
 *
 *  @addtogroup FlexCAN
 *  @{
 */
 /*==================================================================================================
*   Project              : RTD AUTOSAR 4.4
*   Platform             : CORTEXM
*   Peripheral           : FLEXCAN
*   Dependencies         : 
*
*   Autosar Version      : 4.4.0
*   Autosar Revision     : ASR_REL_4_4_REV_0000
*   Autosar Conf.Variant :
*   SW Version           : 0.9.0
*   Build Version        : S32K3_RTD_0_9_0__ASR_REL_4_4_REV_0000_20210326
*
*   (c) Copyright 2020 - 2021 NXP Semiconductors
*   All Rights Reserved.
*
*   NXP Confidential. This software is owned or controlled by NXP and may only be
*   used strictly in accordance with the applicable license terms. By expressly
*   accepting such terms or by downloading, installing, activating and/or otherwise
*   using the software, you are agreeing that you have read, and that you agree to
*   comply with and are bound by, such license terms. If you do not agree to be
*   bound by the applicable license terms, then you may not retain, install,
*   activate or otherwise use the software.
==================================================================================================*/
/*==================================================================================================
*                                        INCLUDE FILES
* 1) system and project includes
* 2) needed interfaces from external units
* 3) internal and external interfaces from this unit
==================================================================================================*/
#include "FlexCAN_Ip_HwAccess.h"
#include "SchM_Can.h"

/*==================================================================================================
*                              SOURCE FILE VERSION INFORMATION
==================================================================================================*/
#define FLEXCAN_IP_HWACCESS_VENDOR_ID_C                      43
#define FLEXCAN_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION_C       4
#define FLEXCAN_IP_HWACCESS_AR_RELEASE_MINOR_VERSION_C       4
#define FLEXCAN_IP_HWACCESS_AR_RELEASE_REVISION_VERSION_C    0
#define FLEXCAN_IP_HWACCESS_SW_MAJOR_VERSION_C               0
#define FLEXCAN_IP_HWACCESS_SW_MINOR_VERSION_C               9
#define FLEXCAN_IP_HWACCESS_SW_PATCH_VERSION_C               0
/*==================================================================================================
*                                     FILE VERSION CHECKS
==================================================================================================*/
/* Check if current file and FlexCAN_Ip_HwAccess header file are of the same vendor */
#if (FLEXCAN_IP_HWACCESS_VENDOR_ID_C != FLEXCAN_IP_HWACCESS_VENDOR_ID_H)
    #error "FlexCAN_Ip_HwAccess.c and FlexCAN_Ip_HwAccess.h have different vendor ids"
#endif
/* Check if current file and CAN header file are of the same Autosar version */
#if ((FLEXCAN_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION_C    != FLEXCAN_IP_HWACCESS_AR_RELEASE_MAJOR_VERSION_H) || \
     (FLEXCAN_IP_HWACCESS_AR_RELEASE_MINOR_VERSION_C    != FLEXCAN_IP_HWACCESS_AR_RELEASE_MINOR_VERSION_H) || \
     (FLEXCAN_IP_HWACCESS_AR_RELEASE_REVISION_VERSION_C != FLEXCAN_IP_HWACCESS_AR_RELEASE_REVISION_VERSION_H))
    #error "AutoSar Version Numbers of FlexCAN_Ip_HwAccess.c and FlexCAN_Ip_HwAccess.h are different"
#endif
/* Check if current file and CAN header file are of the same Software version */
#if ((FLEXCAN_IP_HWACCESS_SW_MAJOR_VERSION_C != FLEXCAN_IP_HWACCESS_SW_MAJOR_VERSION_H) || \
     (FLEXCAN_IP_HWACCESS_SW_MINOR_VERSION_C != FLEXCAN_IP_HWACCESS_SW_MINOR_VERSION_H) || \
     (FLEXCAN_IP_HWACCESS_SW_PATCH_VERSION_C != FLEXCAN_IP_HWACCESS_SW_PATCH_VERSION_H))
    #error "Software Version Numbers of FlexCAN_Ip_HwAccess.c and FlexCAN_Ip_HwAccess.h are different"
#endif

#ifndef DISABLE_MCAL_INTERMODULE_ASR_CHECK
    /* Check if current file and SchM_Can header file are of the same version */
#endif
/*==================================================================================================
*                          LOCAL TYPEDEFS (STRUCTURES, UNIONS, ENUMS)
==================================================================================================*/

/*==================================================================================================
*                                       LOCAL MACROS
==================================================================================================*/
/* CAN FD extended data length DLC encoding */
#define CAN_DLC_VALUE_12_BYTES              9U
#define CAN_DLC_VALUE_16_BYTES              10U
#define CAN_DLC_VALUE_20_BYTES              11U
#define CAN_DLC_VALUE_24_BYTES              12U
#define CAN_DLC_VALUE_32_BYTES              13U
#define CAN_DLC_VALUE_48_BYTES              14U
#define CAN_DLC_VALUE_64_BYTES              15U

#define RxFifoFilterTableOffset             0x18U
#define FlexCanRxFifoAcceptRemoteFrame      1UL
#define FlexCanRxFifoAcceptExtFrame         1UL

#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
#define FlexCanEnhancedRxFifoOneIDFilter    0UL
#define FlexCanEnhancedRxFifoRangerIDFilter 1UL
#define FlexCanEnhancedRxFifoTwoIDFilter    2UL
#define EnhancedRxFifoFilterTableBase       0x0U
#endif

/* Determines the RxFIFO Filter element number */
#define RXFIFO_FILTER_ELEM_NUM(x) (((x) + 1U) * 8U)
/*==================================================================================================
*                                      LOCAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      GLOBAL CONSTANTS
==================================================================================================*/

/*==================================================================================================
*                                      GLOBAL VARIABLES
==================================================================================================*/
#define CAN_START_SEC_VAR_NO_INIT_32_NO_CACHEABLE
#include "Can_MemMap.h"

static volatile uint32 g_FlexCAN_u32ImaskBuff[FLEXCAN_INSTANCE_COUNT][FEATURE_CAN_MBDSR_COUNT];

#define CAN_STOP_SEC_VAR_NO_INIT_32_NO_CACHEABLE
#include "Can_MemMap.h"


#define CAN_START_SEC_CODE
#include "Can_MemMap.h"
/*==================================================================================================
*                                   LOCAL FUNCTION PROTOTYPES
==================================================================================================*/
static uint8 FlexCAN_ComputeDLCValue(uint8 payloadSize);

static void FlexCAN_ClearRAM(FLEXCAN_Type * base);

#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
static boolean FlexCAN_IsExpandableMemoryAvailable(const FLEXCAN_Type * base);
#endif /* if FEATURE_CAN_HAS_EXPANDABLE_MEMORY */

/*==================================================================================================
*                                       LOCAL FUNCTIONS
==================================================================================================*/
/*FUNCTION**********************************************************************
 *
 * Function Name: FLEXCAN_ComputeDLCValue
 * Description  : Computes the DLC field value, given a payload size (in bytes).
 *
 *END**************************************************************************/
static uint8 FlexCAN_ComputeDLCValue(uint8 payloadSize)
{
    uint32 ret = 0xFFU;                   /* 0,  1,  2,  3,  4,  5,  6,  7,  8, */
    static const uint8 payload_code[65] = { 0U, 1U, 2U, 3U, 4U, 5U, 6U, 7U, 8U,
                            /* 9 to 12 payload have DLC Code 12 Bytes */
                        CAN_DLC_VALUE_12_BYTES, CAN_DLC_VALUE_12_BYTES, CAN_DLC_VALUE_12_BYTES, CAN_DLC_VALUE_12_BYTES,
                            /* 13 to 16 payload have DLC Code 16 Bytes */
                        CAN_DLC_VALUE_16_BYTES, CAN_DLC_VALUE_16_BYTES, CAN_DLC_VALUE_16_BYTES, CAN_DLC_VALUE_16_BYTES,
                            /* 17 to 20 payload have DLC Code 20 Bytes */
                        CAN_DLC_VALUE_20_BYTES, CAN_DLC_VALUE_20_BYTES, CAN_DLC_VALUE_20_BYTES, CAN_DLC_VALUE_20_BYTES,
                            /* 21 to 24 payload have DLC Code 24 Bytes */
                        CAN_DLC_VALUE_24_BYTES, CAN_DLC_VALUE_24_BYTES, CAN_DLC_VALUE_24_BYTES, CAN_DLC_VALUE_24_BYTES,
                            /* 25 to 32 payload have DLC Code 32 Bytes */
                        CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES,
                        CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES, CAN_DLC_VALUE_32_BYTES,
                            /* 33 to 48 payload have DLC Code 48 Bytes */
                        CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
                        CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
                        CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
                        CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES, CAN_DLC_VALUE_48_BYTES,
                            /* 49 to 64 payload have DLC Code 64 Bytes */
                        CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES,
                        CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES,
                        CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES,
                        CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES, CAN_DLC_VALUE_64_BYTES };

    if (payloadSize <= 64U)
    {
        ret = payload_code[payloadSize];
    }
    else
    {
        /* The argument is not a valid payload size will return 0xFF*/
    }

    return (uint8)ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_ClearRAM
 * Description   : Clears FlexCAN memory positions that require initialization.
 *
 *END**************************************************************************/
static void FlexCAN_ClearRAM(FLEXCAN_Type * base)
{
    uint32 databyte;
    uint32 ram_addr;
    uint32 RAM_size   = FlexCAN_GetMaxMbNum(base) * 4U;
    uint32 RXIMR_size = FlexCAN_GetMaxMbNum(base);
    /* Address of base + ram offset to point to MB start address */
    volatile uint32 * RAM = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
    /* Clear MB region */
    for (databyte = 0U; databyte < RAM_size; databyte++)
    {
        RAM[databyte] = 0x0U;
    }
    RAM = base->RXIMR;
    /* Clear RXIMR region */
    for (databyte = 0U; databyte < RXIMR_size; databyte++)
    {
        RAM[databyte] = 0x0U;
    }
#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
    if (FlexCAN_IsExpandableMemoryAvailable(base))
    {
        RAM = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_EXP_RAM_OFFSET);
        /* Clear Expanded Memory region */
        for (databyte = 0U; databyte < CAN_RAM1n_COUNT; databyte++)
        {
            RAM[databyte] = 0x0U;
        }
    }
#endif /* if FEATURE_CAN_HAS_EXPANDABLE_MEMORY */

#if (FEATURE_CAN_HAS_MEM_ERR_DET == STD_ON)
    /* Start critical section: implementation depends on integrator */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_01();
    /* Set WRMFRZ bit in CTRL2 Register to grant write access to memory */
    base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_WRMFRZ_MASK) | FLEXCAN_CTRL2_WRMFRZ(1U);
    /* End critical section: implementation depends on integrator */
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_01();
    ram_addr = (uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET;
    RAM = (volatile uint32 *)ram_addr;
    /* Clear RXMGMASK, RXFGMASK, RX14MASK, RX15MASK RAM mapping */
    base->RXMGMASK = 0U;
    base->RXFGMASK = 0U;
    base->RX14MASK = 0U;
    base->RX15MASK = 0U;
#if (FEATURE_CAN_HAS_FD == STD_ON)
    /* Clear SMB FD region */
    for (databyte = 0U; databyte < (uint32)1U; databyte++)
    {
        RAM[databyte] = 0U;
    }
#endif
    /* Start critical section: implementation depends on integrator */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_01();
    /* Clear WRMFRZ bit in CTRL2 Register to restrict write access to memory */
    base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_WRMFRZ_MASK) | FLEXCAN_CTRL2_WRMFRZ(0U);
    /* End critical section: implementation depends on integrator */
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_01();
#endif /* if FEATURE_CAN_HAS_MEM_ERR_DET */
}

#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_IsExpandableMemoryAvailable
 * Description   : Checks if FlexCAN has expandable memory.
 * This function is private.
 *
 *END**************************************************************************/
static boolean FlexCAN_IsExpandableMemoryAvailable(const FLEXCAN_Type * base)
{
    uint32 i;
    static FLEXCAN_Type * const flexcanBase[] = CAN_BASE_PTRS_HAS_EXPANDABLE_MEMORY;
    boolean returnValue = FALSE;
    for (i = 0U; i < FEATURE_CAN_EXPANDABLE_MEMORY_NUM; i++)
    {
        if (base == flexcanBase[i])
        {
            returnValue = TRUE;
            break;
        }
    }

    return returnValue;
}

#endif /* if FEATURE_CAN_HAS_EXPANDABLE_MEMORY */

/*==================================================================================================
*                                       GLOBAL FUNCTIONS
==================================================================================================*/

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_ComputePayloadSize
 * Description   : Computes the maximum payload size (in bytes), given a DLC
 * field value.
 *
 *END**************************************************************************/
uint8 FlexCAN_ComputePayloadSize(uint8 dlcValue)
{
    uint8 ret = 8U;
    if (dlcValue <= 8U)
    {
        ret = dlcValue;
    }
#if (FEATURE_CAN_HAS_FD == STD_ON)
    else
    {
        switch (dlcValue)
        {
            case CAN_DLC_VALUE_12_BYTES:
                ret = 12U;
                break;
            case CAN_DLC_VALUE_16_BYTES:
                ret = 16U;
                break;
            case CAN_DLC_VALUE_20_BYTES:
                ret = 20U;
                break;
            case CAN_DLC_VALUE_24_BYTES:
                ret = 24U;
                break;
            case CAN_DLC_VALUE_32_BYTES:
                ret = 32U;
                break;
            case CAN_DLC_VALUE_48_BYTES:
                ret = 48U;
                break;
            case CAN_DLC_VALUE_64_BYTES:
                ret = 64U;
                break;
            default:
                /* The argument is not a valid DLC size */
                break;
        }
    }
#endif /* FEATURE_CAN_HAS_FD */

    return ret;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_GetMsgBuffRegion
 * Description   : Returns the start of a MB area, based on its index.
 *
 *END**************************************************************************/
volatile uint32 * FlexCAN_GetMsgBuffRegion(const FLEXCAN_Type * base,
                                           uint32 msgBuffIdx)
{
    uint8 arbitration_field_size = 8U;
    uint8 mb_size = 0U;
    uint32 ramBlockSize = 512U;
    uint32 ramBlockOffset = 0;
    uint32 msgBuffIdxBackup = msgBuffIdx;
    uint8 i=0U;
    uint8 maxMbNum=0U;
    uint32 mb_index=0U;
    uint8 payload_size=0U;
    volatile uint32 * RAM = (uint32*)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
    volatile uint32 * pAddressRet = NULL_PTR;
#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
    volatile uint32 * RAM_EXPANDED = (uint32*)((uint32)base + (uint32)FEATURE_CAN_EXP_RAM_OFFSET);
#endif

    for (i=0; i< (uint8)FEATURE_CAN_MBDSR_COUNT; i++)
    {
        payload_size = FlexCAN_GetPayloadSize(base, i);
        mb_size = (uint8)(payload_size + arbitration_field_size);
        maxMbNum = (uint8)(ramBlockSize / mb_size);
        if (maxMbNum > msgBuffIdxBackup)
        {
            break;
        }
        ramBlockOffset += 128U;
        msgBuffIdxBackup -= maxMbNum;
    }

#if (FEATURE_CAN_HAS_EXPANDABLE_MEMORY == STD_ON)
    if (((uint8)FEATURE_CAN_MBDSR_COUNT == i) && ((boolean)TRUE == FlexCAN_IsExpandableMemoryAvailable(base)))
    {
        /* Multiply the MB index by the MB size (in words) */
        /* for expanded ramblock:
         * maxMbNum per one block: 7
         * mb_size per one Mb: 72
        */
        mb_index = ((msgBuffIdxBackup / 7U) * 128U) + ((msgBuffIdxBackup % 7U) * (72U >> 2U));
        pAddressRet = &(RAM_EXPANDED[mb_index]);
    }
    else
#endif
    {
        /* Multiply the MB index by the MB size (in words) */
        mb_index = ramBlockOffset + ((msgBuffIdxBackup % (uint32)maxMbNum) * ((uint32)mb_size >> 2U));
        pAddressRet = &(RAM[mb_index]);
    }

    return pAddressRet;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_GetMaxMbNum
 * Description   : Computes the maximum RAM size occupied by MBs.
 *
 *END**************************************************************************/
uint32 FlexCAN_GetMaxMbNum(const FLEXCAN_Type * base)
{
    uint32 i, ret = 0u;
    static FLEXCAN_Type * const flexcanBase[] = FLEXCAN_BASE_PTRS;
    static const uint32 maxMbNum[] = FEATURE_CAN_MAX_MB_NUM_ARRAY;

    for (i = 0u; i < FLEXCAN_INSTANCE_COUNT; i++)
    {
        if (base == flexcanBase[i])
        {
            ret = maxMbNum[i];
        }
    }

    return ret;
}



/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_EnterFreezeMode
 * Description   : Enter the freeze mode.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_EnterFreezeMode(FLEXCAN_Type * base)
{
    uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
    uint32 timeElapsed = 0U;
    uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
    Flexcan_Ip_StatusType returnResult = FLEXCAN_STATUS_SUCCESS;
    /* Start critical section: implementation depends on integrator */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_02();
    base->MCR = (base->MCR & ~FLEXCAN_MCR_FRZ_MASK) | FLEXCAN_MCR_FRZ(1U);
    base->MCR = (base->MCR & ~FLEXCAN_MCR_HALT_MASK) | FLEXCAN_MCR_HALT(1U);
    if (((base->MCR & FLEXCAN_MCR_MDIS_MASK) >> FLEXCAN_MCR_MDIS_SHIFT) != 0U)
    {
        base->MCR &= ~FLEXCAN_MCR_MDIS_MASK;
    }
    /* End critical section: implementation depends on integrator */
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_02();
    /* Wait for entering the freeze mode */
    timeStart = 0U;
    while (((base->MCR & FLEXCAN_MCR_FRZACK_MASK) >> FLEXCAN_MCR_FRZACK_SHIFT) == 0U)
    {
        timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
        if (timeElapsed >= uS2Ticks)
        {
            returnResult = FLEXCAN_STATUS_TIMEOUT;
            break;
        }
    }

    return returnResult;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_Enable
 * Description   : Enable the clock for FlexCAN Module.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_Enable(FLEXCAN_Type * base)
{
    uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
    uint32 timeElapsed = 0U;
    uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
    Flexcan_Ip_StatusType returnValue = FLEXCAN_STATUS_SUCCESS;
    /* Start critical section: implementation depends on integrator */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_03();

    /* Enable Module */
    base->MCR &= ~FLEXCAN_MCR_MDIS_MASK;
    /* End critical section: implementation depends on integrator */
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_03();
    /* Wait for entering the freeze mode */
    timeStart = 0U;
    while (((base->MCR & FLEXCAN_MCR_FRZACK_MASK) >> FLEXCAN_MCR_FRZACK_SHIFT) == 0U)
    {
        timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
        if (timeElapsed >= uS2Ticks)
        {
            returnValue = FLEXCAN_STATUS_TIMEOUT;
            break;
        }
    }
    return returnValue;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_ExitFreezeMode
 * Description   : Exit of freeze mode.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_ExitFreezeMode(FLEXCAN_Type * base)
{
    uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
    uint32 timeElapsed = 0U;
    uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
    Flexcan_Ip_StatusType returnValue = FLEXCAN_STATUS_SUCCESS;

    /* Start critical section: implementation depends on integrator */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_04();
    base->MCR = (base->MCR & ~FLEXCAN_MCR_HALT_MASK) | FLEXCAN_MCR_HALT(0U);
    base->MCR = (base->MCR & ~FLEXCAN_MCR_FRZ_MASK) | FLEXCAN_MCR_FRZ(0U);
    /* End critical section: implementation depends on integrator */
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_04();
    /* Wait till exit freeze mode */
    while (((base->MCR & FLEXCAN_MCR_FRZACK_MASK) >> FLEXCAN_MCR_FRZACK_SHIFT) != 0U)
    {
        timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
        if (timeElapsed >= uS2Ticks)
        {
            returnValue = FLEXCAN_STATUS_TIMEOUT;
            break;
        }
    }
    return returnValue;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_Disable
 * Description   : Disable FlexCAN module.
 * This function will disable FlexCAN module.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_Disable(FLEXCAN_Type * base)
{
    uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
    uint32 timeElapsed = 0U;
    uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
    Flexcan_Ip_StatusType returnResult = FLEXCAN_STATUS_SUCCESS;
    /* To access the memory mapped registers */
    /* Enter disable mode (hard reset). */
    if (((base->MCR & FLEXCAN_MCR_MDIS_MASK) >> FLEXCAN_MCR_MDIS_SHIFT) == 0U)
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_05();
        /* Clock disable (module) */
        base->MCR = (base->MCR & ~FLEXCAN_MCR_MDIS_MASK) | FLEXCAN_MCR_MDIS(1U);
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_05();
        /* Wait until disable mode acknowledged */
        while (((base->MCR & FLEXCAN_MCR_LPMACK_MASK) >> FLEXCAN_MCR_LPMACK_SHIFT) == 0U)
        {
            timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
            if (timeElapsed >= uS2Ticks)
            {
                returnResult = FLEXCAN_STATUS_TIMEOUT;
                break;
            }
        }
    }
    return returnResult;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_SetErrIntCmd
 * Description   : Enable the error interrupts.
 * This function will enable Error interrupt.
 *
 *END**************************************************************************/
void FlexCAN_SetErrIntCmd(FLEXCAN_Type * base,
                          flexcan_int_type_t errType,
                          boolean enable)
{
    uint32 temp = (uint32)errType;
    /* Start critical section: implementation depends on integrator */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_06();
    if (enable)
    {
#if (FEATURE_CAN_HAS_FD == STD_ON)
        if (errType == FLEXCAN_INT_ERR_FAST)
        {
            base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_ERRMSK_FAST_MASK) | FLEXCAN_CTRL2_ERRMSK_FAST(1U);
            (void)temp;
        }
        else
#endif
        {
            if ((errType == FLEXCAN_INT_RX_WARNING) || (errType == FLEXCAN_INT_TX_WARNING))
            {
                base->MCR = (base->MCR & ~FLEXCAN_MCR_WRNEN_MASK) | FLEXCAN_MCR_WRNEN(1U);
            }
            (base->CTRL1) = ((base->CTRL1) | (temp));
        }
    }
    else
    {
#if (FEATURE_CAN_HAS_FD == STD_ON)
        if (errType == FLEXCAN_INT_ERR_FAST)
        {
            base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_ERRMSK_FAST_MASK) | FLEXCAN_CTRL2_ERRMSK_FAST(0U);
            (void)temp;
        }
        else
#endif
        {
            (base->CTRL1) = ((base->CTRL1) & ~(temp));
            temp = base->CTRL1;
            if (((temp & (uint32)FLEXCAN_INT_RX_WARNING) == 0U) && ((temp & (uint32)FLEXCAN_INT_TX_WARNING) == 0U))
            {
                /* If WRNEN disabled then both FLEXCAN_INT_RX_WARNING and FLEXCAN_INT_TX_WARNING will be disabled */
                base->MCR = (base->MCR & ~FLEXCAN_MCR_WRNEN_MASK) | FLEXCAN_MCR_WRNEN(0U);
            }
        }
    }
    /* End critical section: implementation depends on integrator */
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_06();
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_Init
 * Description   : Initialize FlexCAN module.
 * This function will reset FlexCAN module, set maximum number of message
 * buffers, initialize all message buffers as inactive, enable RX FIFO
 * if needed, mask all mask bits, and disable all MB interrupts.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_Init(FLEXCAN_Type * base)
{
    uint32 timeStart = OsIf_GetCounter(CAN_SERVICE_TIMEOUT_TYPE);
    uint32 timeElapsed = 0U;
    uint32 uS2Ticks = OsIf_MicrosToTicks(CAN_TIMEOUT_DURATION, CAN_SERVICE_TIMEOUT_TYPE);
    Flexcan_Ip_StatusType returnResult = FLEXCAN_STATUS_SUCCESS;

    /* Start critical section: implementation depends on integrator */
    SchM_Enter_Can_CAN_EXCLUSIVE_AREA_07();
    /* Reset the FLEXCAN */
    base->MCR = (base->MCR & ~FLEXCAN_MCR_SOFTRST_MASK) | FLEXCAN_MCR_SOFTRST(1U);
    /* End critical section: implementation depends on integrator */
    SchM_Exit_Can_CAN_EXCLUSIVE_AREA_07();
    /* Wait for reset cycle to complete */
    while (((base->MCR & FLEXCAN_MCR_SOFTRST_MASK) >> FLEXCAN_MCR_SOFTRST_SHIFT) != 0U)
    {
        timeElapsed += OsIf_GetElapsed(&timeStart, CAN_SERVICE_TIMEOUT_TYPE);
        if (timeElapsed >= uS2Ticks)
        {
            returnResult = FLEXCAN_STATUS_TIMEOUT;
            break;
        }
    }
    if(returnResult == FLEXCAN_STATUS_SUCCESS)
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_07();
        /* Avoid Abort Transmission, use Inactive MB */
        base->MCR = (base->MCR & ~FLEXCAN_MCR_AEN_MASK) | FLEXCAN_MCR_AEN(1U);
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_07();
        /* Clear FlexCAN memory */
        FlexCAN_ClearRAM(base);
        /* Rx global mask*/
        (base->RXMGMASK) = (uint32)(FLEXCAN_RXMGMASK_MG_MASK);
        /* Rx reg 14 mask*/
        (base->RX14MASK) =  (uint32)(FLEXCAN_RX14MASK_RX14M_MASK);
        /* Rx reg 15 mask*/
        (base->RX15MASK) = (uint32)(FLEXCAN_RX15MASK_RX15M_MASK);
        /* Disable all MB interrupts */
        (base->IMASK1) = 0x0;
        /* Clear all MB interrupt flags */
        (base->IFLAG1) = FLEXCAN_IMASK1_BUF31TO0M_MASK;
#if FEATURE_CAN_MAX_MB_NUM > 32U
        if (FlexCAN_GetMaxMbNum(base) > 32U)
        {
            (base->IMASK2) = 0x0;
            (base->IFLAG2) = FLEXCAN_IMASK2_BUF63TO32M_MASK;
        }
#endif
#if FEATURE_CAN_MAX_MB_NUM > 64U
        if (FlexCAN_GetMaxMbNum(base) > 64U)
        {
            (base->IMASK3) = 0x0;
            (base->IFLAG3) = FLEXCAN_IMASK3_BUF95TO64M_MASK;
        }
#endif
#if FEATURE_CAN_MAX_MB_NUM > 96U
        if (FlexCAN_GetMaxMbNum(base) > 96U)
        {
            (base->IMASK4) = 0x0;
            (base->IFLAG4) = FLEXCAN_IMASK4_BUF127TO96M_MASK;
        }
#endif
        /* Clear all error interrupt flags */
        (base->ESR1) = FLEXCAN_ALL_INT;
        /* clear registers which are not effected by soft reset */
        base->CTRL1 = FLEXCAN_CTRL1_DEFAULT_VALUE_U32;
        base->CTRL2 = FLEXCAN_CTRL2_DEFAULT_VALUE_U32;
        base->CBT   = FLEXCAN_CBT_DEFAULT_VALUE_U32;
        /* TBC: add define to guard all parts relates to enhanced cbt */
        base->EPRS  = FLEXCAN_EPRS_DEFAULT_VALUE_U32;
        base->ENCBT = FLEXCAN_ENCBT_DEFAULT_VALUE_U32;
        base->EDCBT = FLEXCAN_EDCBT_DEFAULT_VALUE_U32;
        base->ETDC  = FLEXCAN_ETDC_DEFAULT_VALUE_U32;
    #if (FEATURE_CAN_HAS_FD == STD_ON)
        base->FDCBT = FLEXCAN_FDCBT_DEFAULT_VALUE_U32;
        base->FDCTRL = FLEXCAN_FDCTRL_DEFAULT_VALUE_U32;
    #endif /* (FEATURE_CAN_HAS_FD == STD_ON) */
    }
    return returnResult;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_EnableRxFifo
 * Description   : Enable Rx FIFO feature.
 * This function will enable the Rx FIFO feature.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_EnableRxFifo(FLEXCAN_Type * base,
                                         uint32 numOfFilters)
{
    uint32 i;
    uint16 noOfMbx = (uint16)FlexCAN_GetMaxMbNum(base);
    Flexcan_Ip_StatusType stat = FLEXCAN_STATUS_SUCCESS;
    /* RxFIFO cannot be enabled if FD is enabled */
    if (((base->MCR & FLEXCAN_MCR_FDEN_MASK) >> FLEXCAN_MCR_FDEN_SHIFT) != 0U)
    {
        stat = FLEXCAN_STATUS_ERROR;
    }
    if (stat == FLEXCAN_STATUS_SUCCESS)
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_08();
        /* Enable RX FIFO */
        base->MCR = (base->MCR & ~FLEXCAN_MCR_RFEN_MASK) | FLEXCAN_MCR_RFEN(1U);
        /* Set the number of the RX FIFO filters needed */
        base->CTRL2 = (base->CTRL2 & ~FLEXCAN_CTRL2_RFFN_MASK) | ((numOfFilters << FLEXCAN_CTRL2_RFFN_SHIFT) & FLEXCAN_CTRL2_RFFN_MASK);
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_08();
        /* RX FIFO global mask, take in consideration all filter fields*/
        (base->RXFGMASK) = FLEXCAN_RXFGMASK_FGM_MASK;

        for (i = 0U; i < noOfMbx; i++)
        {
            /* RX individual mask */
            base->RXIMR[i] = (FLEXCAN_RXIMR_MI_MASK << CAN_ID_EXT_SHIFT) & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK);
        }
    }
    return stat;
}

#if (FEATURE_CAN_HAS_FD == STD_ON)
/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_SetPayloadSize
 * Description   : Sets the payload size of the MBs.
 *
 *END**************************************************************************/
void FlexCAN_SetPayloadSize(FLEXCAN_Type * base,
                            const Flexcan_Ip_PayloadSizeType * payloadSize)
{
    uint32 tmp;
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
    DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock0 == FLEXCAN_PAYLOAD_SIZE_8));
    #if (FEATURE_CAN_MBDSR_COUNT > 1U)
    DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock1 == FLEXCAN_PAYLOAD_SIZE_8));
    #endif
    #if (FEATURE_CAN_MBDSR_COUNT > 2U)
    DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock2 == FLEXCAN_PAYLOAD_SIZE_8));
    #endif
    #if (FEATURE_CAN_MBDSR_COUNT > 3U)
    DevAssert(FlexCAN_IsFDEnabled(base) || (payloadSize->payloadBlock3 == FLEXCAN_PAYLOAD_SIZE_8));
    #endif
#endif
    /* If FD is not enabled, only 8 bytes payload is supported */
    if (FlexCAN_IsFDEnabled(base))
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_09();
        tmp = base->FDCTRL;
        tmp &= ~(FLEXCAN_FDCTRL_MBDSR0_MASK);
        tmp |= ((uint32)payloadSize->payloadBlock0) << FLEXCAN_FDCTRL_MBDSR0_SHIFT;
#if (FEATURE_CAN_MBDSR_COUNT > 1U)
        tmp &= ~(FLEXCAN_FDCTRL_MBDSR1_MASK);
        tmp |= ((uint32)payloadSize->payloadBlock1) << FLEXCAN_FDCTRL_MBDSR1_SHIFT;
#endif
#if (FEATURE_CAN_MBDSR_COUNT > 2U)
        tmp &= ~(FLEXCAN_FDCTRL_MBDSR2_MASK);
        tmp |= ((uint32)payloadSize->payloadBlock2) << FLEXCAN_FDCTRL_MBDSR2_SHIFT;
#endif
#if (FEATURE_CAN_MBDSR_COUNT > 3U)
        tmp &= ~(FLEXCAN_FDCTRL_MBDSR3_MASK);
        tmp |= ((uint32)payloadSize->payloadBlock3) << FLEXCAN_FDCTRL_MBDSR3_SHIFT;
#endif
        base->FDCTRL = tmp;
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_09();
    }
}

#endif /* End FEATURE_CAN_HAS_FD */

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_GetPayloadSize
 * Description   : Returns the payload size of the MBs (in bytes).
 *
 *END**************************************************************************/
uint8 FlexCAN_GetPayloadSize(const FLEXCAN_Type * base, uint8 mbdsrIdx)
{
    uint32 payloadSize;
    switch (mbdsrIdx)
    {
    case 0 : {  payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR0_MASK) >> FLEXCAN_FDCTRL_MBDSR0_SHIFT); } break;
#if (FEATURE_CAN_MBDSR_COUNT > 1U)
    case 1 : {  payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR1_MASK) >> FLEXCAN_FDCTRL_MBDSR1_SHIFT); } break;
#endif
#if (FEATURE_CAN_MBDSR_COUNT > 2U)
    case 2 : {  payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR2_MASK) >> FLEXCAN_FDCTRL_MBDSR2_SHIFT); } break;
#endif
#if (FEATURE_CAN_MBDSR_COUNT > 3U)
    case 3 : {  payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR3_MASK) >> FLEXCAN_FDCTRL_MBDSR3_SHIFT); } break;
#endif
    default :{  payloadSize = 8UL << ((base->FDCTRL & FLEXCAN_FDCTRL_MBDSR0_MASK) >> FLEXCAN_FDCTRL_MBDSR0_SHIFT); } break;
    }

    return (uint8)payloadSize;
}



uint8 FlexCAN_GetMbPayloadSize(const FLEXCAN_Type * base, uint32 maxMsgBuffNum)
{
    uint8 arbitration_field_size = 8U;
    uint32 ramBlockSize = 512U;
    uint8 can_real_payload = 8U;
    uint8 maxMbBlockNum = 0U;
    uint8 i=0U;
    uint8 mb_size = 0U;
    for(i=0; i< (uint8)FEATURE_CAN_MBDSR_COUNT; i++)
    {
        /* Check that the number of MBs is supported based on the payload size*/
#if (FEATURE_CAN_HAS_FD == STD_ON)
        can_real_payload = FlexCAN_GetPayloadSize(base, i);
#endif /* Else can_real_payload will remain as 8 payload size */
        mb_size = (uint8)(can_real_payload + arbitration_field_size);
        maxMbBlockNum += (uint8)(ramBlockSize / mb_size);
        if (maxMbBlockNum > maxMsgBuffNum)
        {
            break;
        }
    }
#if (STD_ON == FEATURE_CAN_HAS_EXPANDABLE_MEMORY)
    /* exceeded normal ram block */
    if ((uint8)FEATURE_CAN_MBDSR_COUNT == i)
    {
        can_real_payload = 64U;
    }
 #endif

    return can_real_payload;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_LockRxMsgBuff
 * Description   : Lock the RX message buffer.
 * This function will lock the RX message buffer.
 *
 *END**************************************************************************/
void FlexCAN_LockRxMsgBuff(const FLEXCAN_Type * base,
                           uint32 msgBuffIdx)
{
    volatile const uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);

    /* Lock the mailbox by reading it */
    (void)*flexcan_mb;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_SetMsgBuffIntCmd
 * Description   : Enable/Disable the corresponding Message Buffer interrupt.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_SetMsgBuffIntCmd(FLEXCAN_Type * base,
                                  uint8 u8Instance,
                                  uint32 msgBuffIdx,
                                  boolean enable,
                                  boolean bIsIntActive)
{
    uint32 temp;
    Flexcan_Ip_StatusType stat = FLEXCAN_STATUS_SUCCESS;

        /* Enable the corresponding message buffer Interrupt */
        temp = 1UL << (msgBuffIdx % 32U);
        if (msgBuffIdx < 32U)
        {
            if (enable)
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][0U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][0U]) | (temp));
                if (bIsIntActive == TRUE)
                {
                    base->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
                }
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
            else
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][0U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][0U]) & ~(temp));
                base->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
        }
#if FEATURE_CAN_MAX_MB_NUM > 32U
        if ((msgBuffIdx >= 32U) && (msgBuffIdx < 64U))
        {
            if (enable)
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][1U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][1U]) | (temp));
                if (bIsIntActive == TRUE)
                {
                    base->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
                }
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
            else
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][1U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][1U]) & ~(temp));
                base->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
        }
#endif /* if FEATURE_CAN_MAX_MB_NUM > 32U */
#if FEATURE_CAN_MAX_MB_NUM > 64U
        if ((msgBuffIdx >= 64U) && (msgBuffIdx < 96U))
        {
            if (enable)
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][2U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][2U]) | (temp));
                if (bIsIntActive == TRUE)
                {
                    base->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
                }
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
            else
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][2U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][2U]) & ~(temp));
                base->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
        }
#endif /* if FEATURE_CAN_MAX_MB_NUM > 64U */
#if FEATURE_CAN_MAX_MB_NUM > 96U
        if (msgBuffIdx >= 96U)
        {
            if (enable)
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][3U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][3U]) | (temp));
                if (bIsIntActive == TRUE)
                {
                    base->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
                }
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
            else
            {
                /* Start critical section: implementation depends on integrator */
                SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
                g_FlexCAN_u32ImaskBuff[u8Instance][3U] = ((g_FlexCAN_u32ImaskBuff[u8Instance][3U]) & ~(temp));
                base->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
                /* End critical section: implementation depends on integrator */
                SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
            }
        }
#endif /* if FEATURE_CAN_MAX_MB_NUM > 96U */

    return stat;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_ClearMsgBuffIntCmd
 * Description   : Disable the corresponding Message Buffer interrupt only if interrupts are active
 *
 *END**************************************************************************/
void FLEXCAN_ClearMsgBuffIntCmd(FLEXCAN_Type * pBase,
                                  uint8 u8Instance,
                                  uint32 mb_idx,
                                  boolean bIsIntActive)
{
    uint32 temp = (1UL << (mb_idx % 32U));
 /* Stop the running transfer. */
    if (mb_idx < 32U)
    {
          /* Start critical section: implementation depends on integrator */
          SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
          g_FlexCAN_u32ImaskBuff[u8Instance][0U] = (pBase->IMASK1 & (~temp));
          if (bIsIntActive == TRUE)
          {
              pBase->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
          }
          /* End critical section: implementation depends on integrator */
          SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
    }
#if FEATURE_CAN_MAX_MB_NUM > 32U
    if ((mb_idx >= 32U) && (mb_idx < 64U))
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
        g_FlexCAN_u32ImaskBuff[u8Instance][1U] = (pBase->IMASK2 & (~temp));
        if (bIsIntActive == TRUE)
        {
            pBase->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
        }
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
    }
#endif
#if FEATURE_CAN_MAX_MB_NUM > 64U
    if ((mb_idx >= 64U) && (mb_idx < 96U))
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
        g_FlexCAN_u32ImaskBuff[u8Instance][2U] = (pBase->IMASK3 & (~temp));
        if (bIsIntActive == TRUE)
        {
            pBase->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
        }
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
    }
#endif /* FEATURE_CAN_MAX_MB_NUM > 64U */
#if FEATURE_CAN_MAX_MB_NUM > 96U
    if (mb_idx >= 96U)
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_18();
        g_FlexCAN_u32ImaskBuff[u8Instance][3U] = (pBase->IMASK4 & (~temp));
        if (bIsIntActive == TRUE)
        {
            pBase->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
        }
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_18();
    }
#endif /* #if FEATURE_CAN_MAX_MB_NUM > 96U */
}


void FlexCAN_DisableInterrupts(FLEXCAN_Type * pBase)
{
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
    uint32 u32MaxMbCrtlNum = FlexCAN_GetMaxMbNum(pBase);
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */

    pBase->IMASK1 = 0U;
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
    if (u32MaxMbCrtlNum > 32U)
    {
        pBase->IMASK2 = 0U;
    }
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */
#if (FEATURE_CAN_MAX_MB_NUM > 64U)
    if (u32MaxMbCrtlNum > 64U)
    {
        pBase->IMASK3 = 0U;
    }
#endif /* (FEATURE_CAN_MAX_MB_NUM > 64U) */
#if (FEATURE_CAN_MAX_MB_NUM > 96U)
    if (u32MaxMbCrtlNum > 96U)
    {
        pBase->IMASK4 = 0U;
    }
#endif /* (FEATURE_CAN_MAX_MB_NUM > 96U) */
}

void FlexCAN_EnableInterrupts(FLEXCAN_Type * pBase, uint8 u8Instance)
{
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
    uint32 u32MaxMbCrtlNum = FlexCAN_GetMaxMbNum(pBase);
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */

    pBase->IMASK1 = g_FlexCAN_u32ImaskBuff[u8Instance][0U];
#if (FEATURE_CAN_MAX_MB_NUM > 32U)
    if (u32MaxMbCrtlNum > 32U)
    {
        pBase->IMASK2 = g_FlexCAN_u32ImaskBuff[u8Instance][1U];
    }
#endif /* (FEATURE_CAN_MAX_MB_NUM > 32U) */
#if (FEATURE_CAN_MAX_MB_NUM > 64U)
    if (u32MaxMbCrtlNum > 64U)
    {
        pBase->IMASK3 = g_FlexCAN_u32ImaskBuff[u8Instance][2U];
    }
#endif /* (FEATURE_CAN_MAX_MB_NUM > 64U) */
#if (FEATURE_CAN_MAX_MB_NUM > 96U)
    if (u32MaxMbCrtlNum > 96U)
    {
        pBase->IMASK4 = g_FlexCAN_u32ImaskBuff[u8Instance][3U];
    }
#endif /* (FEATURE_CAN_MAX_MB_NUM > 96U) */
}
/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_SetRxMsgBuff
 * Description   : Configure a message buffer for receiving.
 * This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
 * the function will make sure if the MB requested is not occupied by RX FIFO
 * and ID filter table. Then this function will configure the message buffer as
 * required for receiving.
 *
 *END**************************************************************************/
void FlexCAN_SetRxMsgBuff(const FLEXCAN_Type * base,
                              uint32 msgBuffIdx,
                              const Flexcan_Ip_MsbuffCodeStatusType * cs,
                              uint32 msgId)
{
    volatile uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
    volatile uint32 * flexcan_mb_id = &flexcan_mb[1];

#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
    DevAssert(cs != NULL_PTR);
#endif


    /* Clean up the arbitration field area */
    *flexcan_mb = 0;
    *flexcan_mb_id = 0;

    /* Set the ID according the format structure */
    if (cs->msgIdType == FLEXCAN_MSG_ID_EXT)
    {
        /* Set IDE */
        *flexcan_mb |= CAN_CS_IDE_MASK;

        /* Clear SRR bit */
        *flexcan_mb &= ~CAN_CS_SRR_MASK;

        /* ID [28-0] */
        *flexcan_mb_id &= ~(CAN_ID_STD_MASK | CAN_ID_EXT_MASK);
        *flexcan_mb_id |= (msgId & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK));
    }

    if (cs->msgIdType == FLEXCAN_MSG_ID_STD)
    {
        /* Make sure IDE and SRR are not set */
        *flexcan_mb &= ~(CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);

        /* ID[28-18] */
        *flexcan_mb_id &= ~CAN_ID_STD_MASK;
        *flexcan_mb_id |= (msgId << CAN_ID_STD_SHIFT) & CAN_ID_STD_MASK;
    }

    /* Set MB CODE */
    if (cs->code != (uint32)FLEXCAN_RX_NOT_USED)
    {
        *flexcan_mb &= ~CAN_CS_CODE_MASK;
        *flexcan_mb |= (cs->code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_GetMsgBuffTimestamp
 * Description   : Get a message buffer timestamp value.
 *
 *END**************************************************************************/
uint32 FlexCAN_GetMsgBuffTimestamp(const FLEXCAN_Type * base, uint32 msgBuffIdx)
{
    uint32 timestamp = 0U;
    volatile const uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);

#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
    if (FLEXCAN_IsHRTimeStampEnabled(base))
    {
        /* Extract the Time Stamp */
        timestamp = (uint32)base->HR_TIME_STAMP[msgBuffIdx];
    }
    else
#endif /* EATURE_CAN_HAS_HR_TIMER */
    {
        timestamp = (uint32)((*flexcan_mb & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
    }
    return timestamp;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_GetMsgBuff
 * Description   : Get a message buffer field values.
 * This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
 * the function will make sure if the MB requested is not occupied by RX FIFO
 * and ID filter table. Then this function will get the message buffer field
 * values and copy the MB data field into user's buffer.
 *
 *END**************************************************************************/
void FlexCAN_GetMsgBuff(const FLEXCAN_Type * base,
                        uint32 msgBuffIdx,
                        Flexcan_Ip_MsgBuffType * msgBuff)
{

    uint8 i;
    volatile const uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
    volatile const uint32 * flexcan_mb_id   = &flexcan_mb[1];
    volatile const uint8 * flexcan_mb_data = (volatile const uint8 *)(&flexcan_mb[2]);
    volatile const uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
    uint32 * msgBuff_data_32 = (uint32 *)(msgBuff->data);
    uint32 mbWord;

    uint8 flexcan_mb_dlc_value = (uint8)(((*flexcan_mb) & CAN_CS_DLC_MASK) >> 16);
    uint8 payload_size = FlexCAN_ComputePayloadSize(flexcan_mb_dlc_value);


    DevAssert(msgBuff != NULL_PTR);


#if (FEATURE_CAN_HAS_FD == STD_ON)
    /* Payload Size is based on MBDSR for 1 MBDSR corresponds 32 * 8Bytes MBs  */
    if (payload_size > FlexCAN_GetMbPayloadSize(base, msgBuffIdx))
    {
        payload_size = FlexCAN_GetMbPayloadSize(base, msgBuffIdx);
    }
#endif /* FEATURE_CAN_HAS_FD */

    msgBuff->dataLen = payload_size;
    /* Get a MB field values */
    msgBuff->cs = *flexcan_mb;
    if ((msgBuff->cs & CAN_CS_IDE_MASK) != 0U)
    {
        msgBuff->msgId = (*flexcan_mb_id);
    }
    else
    {
        msgBuff->msgId = (*flexcan_mb_id) >> CAN_ID_STD_SHIFT;
    }


#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
    if (FLEXCAN_IsHRTimeStampEnabled(base))
    {
        /* Extract the Time Stamp */
        msgBuff->time_stamp = (uint32)base->HR_TIME_STAMP[msgBuffIdx];
    }
    else
#endif /* EATURE_CAN_HAS_HR_TIMER */
    {
        msgBuff->time_stamp = (uint32)((msgBuff->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
    }

#if (defined (CPU_S32K116) || defined (CPU_S32K118))
    /* Check if the buffer address is aligned */
    if (((uint32)msgBuff_data_32 & 0x3U) != 0U)
    {
        /* Copy MB data field into user's buffer */
        for (i = 0U; i < (payload_size & ~3U); i += 4U)
        {
            mbWord = flexcan_mb_data_32[i >> 2U];
            uint8 index;
            uint32 x;
            const uint8 * p;
            FlexcanSwapBytesInWord(mbWord, x);
            p = (uint8 *)&x;
            for (index = 0; index < 4U; index++)
            {
                msgBuff->data[i + index] = p[index];
            }
        }
    }
    else
    {
        for (i = 0U; i < (payload_size & ~3U); i += 4U)
        {
            mbWord = flexcan_mb_data_32[i >> 2U];
            FlexcanSwapBytesInWord(mbWord, msgBuff_data_32[i >> 2U]);
        }
    }

#else  /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
    for (i = 0U; i < (payload_size & ~3U); i += 4U)
    {
        mbWord = flexcan_mb_data_32[i >> 2U];
        FlexcanSwapBytesInWord((mbWord), (msgBuff_data_32[i >> 2U]));
    }

#endif /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
    for ( ; i < payload_size; i++)
    {   /* Max allowed value for index is 63 */
        msgBuff->data[i] = flexcan_mb_data[FlexcanSwapBytesInWordIndex(i)];
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_SetTxMsgBuff
 * Description   : Configure a message buffer for transmission.
 * This function will first check if RX FIFO is enabled. If RX FIFO is enabled,
 * the function will make sure if the MB requested is not occupied by RX FIFO
 * and ID filter table. Then this function will copy user's buffer into the
 * message buffer data area and configure the message buffer as required for
 * transmission.
 *
 *END**************************************************************************/
void FlexCAN_SetTxMsgBuff(const FLEXCAN_Type * base,
                              uint32 msgBuffIdx,
                              const Flexcan_Ip_MsbuffCodeStatusType * cs,
                              uint32 msgId,
                              const uint8 * msgData,
                              const boolean isRemote)
{
    uint32 flexcan_mb_config = 0;
    uint32 databyte;
    uint8 dlc_value;
    uint8 payload_size;
    volatile uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
    volatile uint32 * flexcan_mb_id   = &flexcan_mb[1];
    volatile uint8 * flexcan_mb_data = (volatile uint8*)(&flexcan_mb[2]);
    volatile uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
    const uint32 * msgData_32 = (const uint32*)msgData;

    #if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
        DevAssert(cs != NULL_PTR);
    #endif

        /* Clean up the arbitration field area and set TxMB Inactive */
        *flexcan_mb = (uint32)((((uint32)FLEXCAN_TX_INACTIVE & (uint32)0x1F) << (uint8)CAN_CS_CODE_SHIFT) & (uint32)CAN_CS_CODE_MASK);
        *flexcan_mb_id = 0;
#if (FEATURE_CAN_HAS_FD == STD_ON)
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
        /* Check if the Payload Size is smaller than the payload configured */
        DevAssert((uint8)cs->dataLen <= FlexCAN_GetMbPayloadSize(base, msgBuffIdx));
#endif
#else
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
        DevAssert((uint8)cs->dataLen <= 8U);
#endif
#endif
        /* Compute the value of the DLC field */
        dlc_value = FlexCAN_ComputeDLCValue((uint8)cs->dataLen);
        /* Copy user's buffer into the message buffer data area */
        if (msgData != NULL_PTR)
        {
            for (databyte = 0; databyte < (cs->dataLen & ~3U); databyte += 4U)
            {
                FlexcanSwapBytesInWord((msgData_32[databyte >> 2U]), (flexcan_mb_data_32[databyte >> 2U]));
            }
            for ( ; databyte < cs->dataLen; databyte++)
            {
                flexcan_mb_data[FlexcanSwapBytesInWordIndex(databyte)] =  msgData[databyte];
            }
        #if (FEATURE_CAN_HAS_FD == STD_ON)
            payload_size = FlexCAN_ComputePayloadSize(dlc_value);
            /* Add padding, if needed */
            for (databyte = cs->dataLen; databyte < payload_size; databyte++)
            {
                flexcan_mb_data[FlexcanSwapBytesInWordIndex(databyte)] = cs->fd_padding;
            }
        #endif /* FEATURE_CAN_HAS_FD */
        }
        /* Set the ID according the format structure */
        if (cs->msgIdType == FLEXCAN_MSG_ID_EXT)
        {
            /* ID [28-0] */
            *flexcan_mb_id &= ~(CAN_ID_STD_MASK | CAN_ID_EXT_MASK);
            *flexcan_mb_id |= (msgId & (CAN_ID_STD_MASK | CAN_ID_EXT_MASK));
            /* Set IDE and SRR bit*/
            flexcan_mb_config |= (CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);
        }
        if (cs->msgIdType == FLEXCAN_MSG_ID_STD)
        {
            /* ID[28-18] */
            *flexcan_mb_id &= ~CAN_ID_STD_MASK;
            *flexcan_mb_id |= (msgId << CAN_ID_STD_SHIFT) & CAN_ID_STD_MASK;
            /* make sure IDE and SRR are not set */
            flexcan_mb_config &= ~(CAN_CS_IDE_MASK | CAN_CS_SRR_MASK);
        }
        /* Set the length of data in bytes */
        flexcan_mb_config &= ~CAN_CS_DLC_MASK;
        flexcan_mb_config |= ((uint32)dlc_value << CAN_CS_DLC_SHIFT) & CAN_CS_DLC_MASK;
        /* Set MB CODE */
        if (cs->code != (uint32)FLEXCAN_TX_NOT_USED)
        {
            if (cs->code == (uint32)FLEXCAN_TX_REMOTE)
            {
                /* Set RTR bit */
                flexcan_mb_config |= CAN_CS_RTR_MASK;
            }
            else
            {
                if (isRemote == TRUE)
                {
                    /* Set RTR bit */
                    flexcan_mb_config |= CAN_CS_RTR_MASK;
                }
            }
            /* Reset the code */
            flexcan_mb_config &= ~CAN_CS_CODE_MASK;
            /* Set the code */
            if (cs->fd_enable)
            {
                flexcan_mb_config |= ((cs->code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK) | CAN_MB_EDL_MASK;
                /* In case of FD frame not supported RTR */
                flexcan_mb_config &= ~CAN_CS_RTR_MASK;
            }
            else
            {
                flexcan_mb_config |= (cs->code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK;
            }

            if (cs->enable_brs)
            {
                flexcan_mb_config |= CAN_MB_BRS_MASK;
            }
            *flexcan_mb |= flexcan_mb_config;
        }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_SetMaxMsgBuffNum
 * Description   : Set the number of the last Message Buffers.
 * This function will define the number of the last Message Buffers
 *
 *END***************************************************************************/
Flexcan_Ip_StatusType FlexCAN_SetMaxMsgBuffNum(
    FLEXCAN_Type * base,
    uint32 maxMsgBuffNum)
{
    uint8 msgBuffIdx;
    uint32 databyte;
    const volatile uint32 * RAM = (uint32*)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
#if (STD_ON == FEATURE_CAN_HAS_EXPANDABLE_MEMORY)
    const volatile uint32 * RAM_EXPANDED = (uint32*)((uint32)base + (uint32)FEATURE_CAN_EXP_RAM_OFFSET);
#endif /* FEATURE_CAN_HAS_EXPANDABLE_MEMORY */
    const volatile uint32 * valEndMbPointer = NULL_PTR;
    volatile uint32 *flexcan_mb = NULL_PTR;
    volatile uint32 *flexcan_mb_id   = NULL_PTR ;
    volatile uint8  *flexcan_mb_data = NULL_PTR;
    uint8 arbitration_field_size = 8U;
    uint8 can_real_payload = FlexCAN_GetMbPayloadSize(base, maxMsgBuffNum - (uint32)1U);
    uint32 valEndMb = 0U;
    uint32 valEndRam = 0U;
    Flexcan_Ip_StatusType status = FLEXCAN_STATUS_SUCCESS;
    #if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
        DevAssert(maxMsgBuffNum>0U);
    #endif

    valEndMbPointer = FlexCAN_GetMsgBuffRegion(base, (maxMsgBuffNum - (uint32)1U));

    valEndMb = (uint32)valEndMbPointer + can_real_payload + arbitration_field_size;

#if (STD_ON == FEATURE_CAN_HAS_EXPANDABLE_MEMORY)
    if (FlexCAN_IsExpandableMemoryAvailable(base))
    {
        valEndRam = (uint32)&RAM_EXPANDED[CAN_RAM1n_COUNT];
    }
    else
    {
        valEndRam = (uint32)&RAM[CAN_RAMn_COUNT];
    }
#else
    valEndRam = (uint32)&RAM[CAN_RAMn_COUNT];
#endif /* FEATURE_CAN_HAS_EXPANDABLE_MEMORY */

    if ((valEndMb > valEndRam) || (maxMsgBuffNum > FlexCAN_GetMaxMbNum(base)))
    {
        status = FLEXCAN_STATUS_BUFF_OUT_OF_RANGE;
    }


    if (status == FLEXCAN_STATUS_SUCCESS)
    {
        /* Start critical section: implementation depends on integrator */
        SchM_Enter_Can_CAN_EXCLUSIVE_AREA_11();
        /* Set the maximum number of MBs*/
        base->MCR = (base->MCR & ~FLEXCAN_MCR_MAXMB_MASK) | (((maxMsgBuffNum-1U) << FLEXCAN_MCR_MAXMB_SHIFT) & FLEXCAN_MCR_MAXMB_MASK);
        if (!(((base->MCR & FLEXCAN_MCR_RFEN_MASK) >> FLEXCAN_MCR_RFEN_SHIFT) != 0U))
        {
            /* Initialize all message buffers as inactive */
            for (msgBuffIdx = 0; msgBuffIdx < maxMsgBuffNum; msgBuffIdx++)
            {
                flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
                flexcan_mb_id   = &flexcan_mb[1];
                flexcan_mb_data = (volatile uint8*)(&flexcan_mb[2]);
                *flexcan_mb = 0x0U;
                *flexcan_mb_id = 0x0U;
                can_real_payload = FlexCAN_GetMbPayloadSize(base, msgBuffIdx);
                for (databyte = 0; databyte < can_real_payload; databyte++)
                {
                   flexcan_mb_data[databyte] = 0x0U;
                }
            }
        }
        /* End critical section: implementation depends on integrator */
        SchM_Exit_Can_CAN_EXCLUSIVE_AREA_11();
    }
    return status;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_SetOperationMode
 * Description   : Enable a FlexCAN operation mode.
 * This function will enable one of the modes listed in flexcan_operation_modes_t.
 *
 *END**************************************************************************/
void FlexCAN_SetOperationMode(FLEXCAN_Type * base,
                                               Flexcan_Ip_ModesType mode)
{
    switch (mode)
    {
        case FLEXCAN_NORMAL_MODE:
            /* Start critical section: implementation depends on integrator */
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_12();
            base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LOM_MASK) | FLEXCAN_CTRL1_LOM(0U);
            base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LPB_MASK) | FLEXCAN_CTRL1_LPB(0U);
            /* End critical section: implementation depends on integrator */
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_12();
            break;
        case FLEXCAN_LISTEN_ONLY_MODE:
            /* Start critical section: implementation depends on integrator */
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_12();
            base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LOM_MASK) | FLEXCAN_CTRL1_LOM(1U);
            /* End critical section: implementation depends on integrator */
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_12();
            break;
        case FLEXCAN_LOOPBACK_MODE:
            /* Start critical section: implementation depends on integrator */
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_12();
            base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LPB_MASK) | FLEXCAN_CTRL1_LPB(1U);
            base->CTRL1 = (base->CTRL1 & ~FLEXCAN_CTRL1_LOM_MASK) | FLEXCAN_CTRL1_LOM(0U);
            /* Enable Self Reception */
            FlexCAN_SetSelfReception(base, TRUE);
            /* End critical section: implementation depends on integrator */
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_12();
            break;
        default:
            /* Should not get here */
            break;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_SetRxFifoFilter
 * Description   : Configure RX FIFO ID filter table elements.
 *
 *END**************************************************************************/
void FlexCAN_SetRxFifoFilter(FLEXCAN_Type * base,
                             Flexcan_Ip_RxFifoIdElementFormatType idFormat,
                             const Flexcan_Ip_IdTableType * idFilterTable)
{

    /* Set RX FIFO ID filter table elements*/
    uint32 i, j, numOfFilters;
    uint32 val1 = 0UL, val2 = 0UL, val = 0UL;
    volatile uint32 * filterTable = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET + ((uint32)RxFifoFilterTableOffset * 4U));


    #if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
        DevAssert((idFilterTable != NULL_PTR) || (FLEXCAN_RX_FIFO_ID_FORMAT_D == idFormat));
    #endif

    numOfFilters = (((base->CTRL2) & FLEXCAN_CTRL2_RFFN_MASK) >> FLEXCAN_CTRL2_RFFN_SHIFT);
    switch (idFormat)
    {
        case (FLEXCAN_RX_FIFO_ID_FORMAT_A):
            /* Start critical section: implementation depends on integrator */
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
            /* One full ID (standard and extended) per ID Filter Table element.*/
            (base->MCR) =
                (((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
                 ((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_A)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
            /* End critical section: implementation depends on integrator */
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
            for (i = 0U; i < RXFIFO_FILTER_ELEM_NUM(numOfFilters); i++)
            {
                val = 0UL;

                if (idFilterTable[i].isRemoteFrame)
                {
                    val = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT;
                }

                if (idFilterTable[i].isExtendedFrame)
                {
                    val |= FlexCanRxFifoAcceptExtFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT;
                    filterTable[i] = val + ((idFilterTable[i].id <<
                                             FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_SHIFT) &
                                             FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_MASK);
                }
                else
                {
                    filterTable[i] = val + ((idFilterTable[i].id <<
                                             FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_SHIFT) &
                                             FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_MASK);
                }
            }
            break;
        case (FLEXCAN_RX_FIFO_ID_FORMAT_B):
            /* Two full standard IDs or two partial 14-bit (standard and extended) IDs*/
            /* per ID Filter Table element.*/
            /* Start critical section: implementation depends on integrator */
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
            (base->MCR) =
                (((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
                 ((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_B)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
            /* End critical section: implementation depends on integrator */
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
            j = 0U;
            for (i = 0U; i < RXFIFO_FILTER_ELEM_NUM(numOfFilters); i++)
            {
                val1 = 0U;
                val2 = 0U;

                if (idFilterTable[j].isRemoteFrame)
                {
                    val1 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT;
                }

                if (idFilterTable[j + 1U].isRemoteFrame)
                {
                    val2 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_RTR_SHIFT;
                }

                if (idFilterTable[j].isExtendedFrame)
                {
                    val1 |= FlexCanRxFifoAcceptExtFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT;

                    filterTable[i] = val1 + (((idFilterTable[j].id &
                                               FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK) >>
                                               FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_CMP_SHIFT) <<
                                               FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT1);
                }
                else
                {
                    filterTable[i] = val1 + ((idFilterTable[j].id &
                                              FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) <<
                                              FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT1);
                }

                if (idFilterTable[j + 1U].isExtendedFrame)
                {
                    val2 |= FlexCanRxFifoAcceptExtFrame << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_IDE_SHIFT;

                    filterTable[i] |= val2 + (((idFilterTable[j + 1U].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT2);
                }
                else
                {
                    filterTable[i] |= val2 + ((idFilterTable[j + 1U].id &
                                               FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) <<
                                               FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT2);
                }

                j = j + 2U;
            }
            break;
        case (FLEXCAN_RX_FIFO_ID_FORMAT_C):
            /* Four partial 8-bit Standard IDs per ID Filter Table element.*/
            /* Start critical section: implementation depends on integrator */
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
            (base->MCR) =
                (((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
                 ((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_C)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
            /* End critical section: implementation depends on integrator */
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
            j = 0U;
            for (i = 0U; i < RXFIFO_FILTER_ELEM_NUM(numOfFilters); i++)
            {
                if (idFilterTable[j].isExtendedFrame)
                {
                    filterTable[i] = val1 + (((idFilterTable[j].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1);
                }
                else
                {
                    filterTable[i] = val1 + (((idFilterTable[j].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1);
                }

                if (idFilterTable[j + 1U].isExtendedFrame)
                {
                    filterTable[i] |= val1 + (((idFilterTable[j + 1U].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT2);
                }
                else
                {
                    filterTable[i] |= val1 + (((idFilterTable[j + 1U].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT2);
                }

                if (idFilterTable[j + 2U].isExtendedFrame)
                {
                    filterTable[i] |= val1 + (((idFilterTable[j + 2U].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT3);
                }
                else
                {
                    filterTable[i] |= val1 + (((idFilterTable[j + 2U].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT3);
                }

                if (idFilterTable[j + 3U].isExtendedFrame)
                {
                    filterTable[i] |= val1 + (((idFilterTable[j + 3U].id &
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_MASK) >>
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_EXT_CMP_SHIFT) <<
                                                FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT4);
                }
                else
                {
                    filterTable[i] |= val1 +
                                      (((idFilterTable[j + 3U].id & FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_MASK) >>
                                        FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_STD_CMP_SHIFT) <<
                        FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT4);
                }

                j = j + 4U;
            }
            break;
        case (FLEXCAN_RX_FIFO_ID_FORMAT_D):
            /* All frames rejected.*/
            /* Start critical section: implementation depends on integrator */
            SchM_Enter_Can_CAN_EXCLUSIVE_AREA_13();
            (base->MCR) =
                (((base->MCR) & ~(FLEXCAN_MCR_IDAM_MASK)) |
                 ((((uint32)(((uint32)(FLEXCAN_RX_FIFO_ID_FORMAT_D)) << FLEXCAN_MCR_IDAM_SHIFT)) & FLEXCAN_MCR_IDAM_MASK)));
            /* End critical section: implementation depends on integrator */
            SchM_Exit_Can_CAN_EXCLUSIVE_AREA_13();
            break;
        default:
            /* Should not get here */
            break;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_ReadRxFifo
 * Description   : Read Rx FIFO data.
 * This function will copy MB[0] data field into user's buffer.
 *
 *END**************************************************************************/
void FlexCAN_ReadRxFifo(const FLEXCAN_Type * base,
                        Flexcan_Ip_MsgBuffType * rxFifo)
{

    uint32 databyte;
    uint32 mbWord;
    #if (defined (CPU_S32K116) || defined (CPU_S32K118))
    uint32 x;
    uint8 index;
    const uint8 * p;
    #endif

    volatile const uint32 * flexcan_mb = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_RAM_OFFSET);
    volatile const uint32 * flexcan_mb_id = &flexcan_mb[1];
    volatile const uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
    uint32 * msgData_32 = (uint32 *)(rxFifo->data);
    uint8 flexcan_mb_dlc_value = (uint8)(((*flexcan_mb) & CAN_CS_DLC_MASK) >> 16);
    uint8 can_real_payload = FlexCAN_ComputePayloadSize(flexcan_mb_dlc_value);

    #if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
        DevAssert(rxFifo != NULL_PTR);
    #endif
    /*
       Check if the length of received data packet bigger than the maximum length accepted,
       then processing flow shall continue with the maximum length defined by configuration.
       Legacy FIFO just support in normal mode.
    */
    /* no need to check if FD enabled or not because this function just is invoked when legacy fifo enabled only ! */
    if(can_real_payload > 8U)
    {
        can_real_payload = 8U;
    }

    rxFifo->dataLen = can_real_payload;
    rxFifo->cs = *flexcan_mb;
    if ((rxFifo->cs & CAN_CS_IDE_MASK) != 0U)
    {
        rxFifo->msgId = *flexcan_mb_id;
    }
    else
    {
        rxFifo->msgId = (*flexcan_mb_id) >> CAN_ID_STD_SHIFT;
    }
    /* Extract the IDHIT */
    rxFifo->id_hit = (uint8)base->RXFIR;
    /* Extract the Time Stamp */
    rxFifo->time_stamp = (uint32)((rxFifo->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
#if (defined (CPU_S32K116) || defined (CPU_S32K118))
    /* Check if the buffer address is aligned */
    if (((uint32)msgData_32 & 0x3U) != 0U)
    {
        /* Copy MB[0] data field into user's buffer */
        for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
        {

            mbWord = flexcan_mb_data_32[databyte >> 2U];

            FlexcanSwapBytesInWord(mbWord, x);
            p = (uint8 *)&x;
            for (index = 0U; index < 4U; index++)
            {
                rxFifo->data[databyte + index] = p[index];
            }
        }
    }
    else
    {
        /* Copy MB[0] data field into user's buffer */
        for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
        {
            mbWord = flexcan_mb_data_32[databyte >> 2U];
            FlexcanSwapBytesInWord(mbWord, msgData_32[databyte >> 2U]);
        }
    }
#else  /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
      /* Copy MB[0] data field into user's buffer */
    for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
    {
        mbWord = flexcan_mb_data_32[databyte >> 2U];
        FlexcanSwapBytesInWord((mbWord), (msgData_32[databyte >> 2U]));
    }
#endif /* if (defined (CPU_S32K116) || defined (CPU_S32K118)) */
}
#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)
/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_ReadEnhancedRxFifo
 * Description   : Read Enhanced Rx FIFO data.
 * This function will copy Enhanced Rx FIFO data output into user's buffer.
 *
 *END**************************************************************************/
void FlexCAN_ReadEnhancedRxFifo(const FLEXCAN_Type * base,
                                Flexcan_Ip_MsgBuffType * rxFifo)
{
    uint32 databyte;
    uint32 mbWord;
    uint8 idhit_offset;
    volatile const uint32 * flexcan_mb = (uint32 *)((uint32)base + (uint32)FEATURE_CAN_ENHANCED_FIFO_RAM_OFFSET);
    volatile const uint32 * flexcan_mb_id = &flexcan_mb[1];
    volatile const uint32 * flexcan_mb_data_32 = &flexcan_mb[2];
    uint32 * msgData_32 = NULL_PTR;

    /* Check if the buffer address is aligned */

    /* Compute payload size */
    uint8 flexcan_mb_dlc_value = (uint8)(((*flexcan_mb) & CAN_CS_DLC_MASK) >> CAN_CS_DLC_SHIFT);
    uint8 can_real_payload = FlexCAN_ComputePayloadSize(flexcan_mb_dlc_value);

#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
    DevAssert(rxFifo != NULL_PTR);
#endif

    msgData_32 = (uint32 *)(rxFifo->data);
    rxFifo->dataLen = can_real_payload;
    rxFifo->cs = *flexcan_mb;

    if ((rxFifo->cs & CAN_CS_IDE_MASK) != 0U)
    {
        rxFifo->msgId = *flexcan_mb_id;
    }
    else
    {
        rxFifo->msgId = (*flexcan_mb_id) >> CAN_ID_STD_SHIFT;
    }

    if ((rxFifo->cs & CAN_CS_RTR_MASK) != 0U)
    {
        can_real_payload = 0U;
    }

    idhit_offset = (can_real_payload >> 2U) + (((can_real_payload % 4U) != 0U) ? 1U : 0U);

    /* Extract the IDHIT */
    rxFifo->id_hit = (uint8)(((flexcan_mb_data_32[idhit_offset]) & CAN_ENHANCED_IDHIT_MASK) >> CAN_ENHANCED_IDHIT_SHIFT);
#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
    /* Extract the Time Stamp */
    if (FLEXCAN_IsHRTimeStampEnabled(base))
    {
        rxFifo->time_stamp = (uint32)(flexcan_mb_data_32[idhit_offset + 1U]);
    }
    else
#endif
    {
        rxFifo->time_stamp = (uint32)((rxFifo->cs & CAN_CS_TIME_STAMP_MASK) >> CAN_CS_TIME_STAMP_SHIFT);
    }

    /* Copy EnhancedRxFIFO data field into user's buffer */
    for (databyte = 0U; databyte < can_real_payload; databyte += 4U)
    {
        mbWord = flexcan_mb_data_32[databyte >> 2U];
        FlexcanSwapBytesInWord((mbWord), (msgData_32[databyte >> 2U]));
    }
}
#endif /* FEATURE_CAN_HAS_ENHANCED_RX_FIFO */

#if (FEATURE_CAN_BUSOFF_ERROR_INTERRUPT_UNIFIED == STD_OFF)
/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_ClearErrIntStatusFlag
 * Description   : Clear all error interrupt status.
 *
 *END**************************************************************************/
void FlexCAN_ClearErrIntStatusFlag(FLEXCAN_Type * base)
{
    if ((base->ESR1 & FLEXCAN_ALL_INT) != 0U)
    {
        (base->ESR1) = ERROR_INT;
    }
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_ClearBusOffIntStatusFlag
 * Description   : Clear all busOff and Tx/Rx Warning interrupt status.
 *
 *END**************************************************************************/
void FlexCAN_ClearBusOffIntStatusFlag(FLEXCAN_Type * base)
{
    if ((base->ESR1 & BUS_OFF_INT) != 0U)
    {
        base->ESR1 = BUS_OFF_INT;
    }
}
#endif /* (FEATURE_CAN_BUSOFF_ERROR_INTERRUPT_UNIFIED == STD_OFF) */
/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_GetErrStatusFlag.
 * Description   : Get error interrupt status.
 *
 *END**************************************************************************/
boolean FlexCAN_GetErrStatusFlag(uint8 u8Instance)
{
    static FLEXCAN_Type * const flexcanBase[] = FLEXCAN_BASE_PTRS;
    boolean bErrStatus = (boolean)FALSE;

    if (((flexcanBase[u8Instance])->ESR1 & FLEXCAN_ESR1_ERRINT_MASK) != 0U)
    {
        bErrStatus = (boolean)TRUE;
    }
    return bErrStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_GetBusOffStatusFlag.
 * Description   : Get busOff interrupt status.
 *
 *END**************************************************************************/
boolean FlexCAN_GetBusOffStatusFlag(uint8 u8Instance)
{
    static FLEXCAN_Type * const flexcanBase[] = FLEXCAN_BASE_PTRS;
    boolean bBOffStatus = (boolean)FALSE;

    if ((flexcanBase[u8Instance]->ESR1 & FLEXCAN_ESR1_BOFFINT_MASK) != 0U)
    {
        bBOffStatus = (boolean)TRUE;
    }
    return bBOffStatus;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_AbortTxMsgBuff
 * Description   : Writes the abort code into the CODE field of the requested
 * Tx message buffer.
 *
 *END**************************************************************************/
void FlexCAN_AbortTxMsgBuff(const FLEXCAN_Type * base,
                            uint32 msgBuffIdx)
{
    uint32 flexcan_mb_config = 0;
    uint32 code = FLEXCAN_TX_ABORT;

    volatile uint32 * flexcan_mb = FlexCAN_GetMsgBuffRegion(base, msgBuffIdx);
    flexcan_mb_config = *flexcan_mb;

    /* Reset the code */
    flexcan_mb_config &= (~CAN_CS_CODE_MASK);

    flexcan_mb_config |= (code << CAN_CS_CODE_SHIFT) & CAN_CS_CODE_MASK;

    *flexcan_mb = flexcan_mb_config;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_GetRxFifoMask
 * Description   : Calculate the Global Mask as format ID type in FIFO Mode.
 * Based on the ID format type and Mask Type will calculate the and set accordingly
 * the Rx FIFO Individual\Global Mask register.
 *
 *END**************************************************************************/
uint32 FlexCAN_GetRxFifoMask(Flexcan_Ip_MsgBuffIdType id_type,
                             Flexcan_Ip_RxFifoIdElementFormatType formatType,
                             uint32 mask)
{
    uint32 val = 0;

    switch (formatType)
    {
        case (FLEXCAN_RX_FIFO_ID_FORMAT_A):
            /* Set RTR bit encoded as bit 31 and IDE bit encoded as bit 30 in mask */
            val = mask & ((1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT) | (1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT));
            if (id_type == FLEXCAN_MSG_ID_STD)
            {
                /* Set standard global mask for RX FIFO and IDE will be 1 and check the FIFO filter ide */
                val |= ((mask << FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_SHIFT) & FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_STD_MASK);
            }
            else if (id_type == FLEXCAN_MSG_ID_EXT)
            {
                /* Set extended global mask for RX FIFO and IDE will be 0 and don't check the FIFO filter ide */
                val |= ((mask << FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_SHIFT) & FLEXCAN_RX_FIFO_ID_FILTER_FORMATA_EXT_MASK);
            }
            else
            {
                /* Should not get here */
            }

            break;
        case (FLEXCAN_RX_FIFO_ID_FORMAT_B):
            /* Set RTR bit encoded as bit 31 and IDE bit encoded as bit 30 in mask */
            val = mask & ((1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_RTR_SHIFT) | (1UL << FLEXCAN_RX_FIFO_ID_FILTER_FORMATAB_IDE_SHIFT));
            if (id_type == FLEXCAN_MSG_ID_STD)
            {
                /* Set standard global mask for RX FIFO  */
                val |= ((mask & FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_MASK) << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_STD_SHIFT1);
            }
            else if (id_type == FLEXCAN_MSG_ID_EXT)
            {
                /* Set extended global mask for RX FIFO  */
                val |= ((mask & FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_MASK1) << FLEXCAN_RX_FIFO_ID_FILTER_FORMATB_EXT_SHIFT1);
            }
            else
            {
                /* Should not get here */
            }

            break;
        case (FLEXCAN_RX_FIFO_ID_FORMAT_C):
            if ((id_type == FLEXCAN_MSG_ID_EXT) || (id_type == FLEXCAN_MSG_ID_STD))
            {
                val |= ((mask & FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_MASK) << FLEXCAN_RX_FIFO_ID_FILTER_FORMATC_SHIFT1);
            }
            else
            {
                /* Should not get here */
            }

            break;
        case (FLEXCAN_RX_FIFO_ID_FORMAT_D):
            /* Format not supported.*/
            break;
        default:
            /* Should not get here */
            break;
    }    /* End Switch */

    return val;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_IsMbOutOfRange
 * Description   : Check if the mb index is out of range or not.
 *
 *END**************************************************************************/
boolean FlexCAN_IsMbOutOfRange
(
    const FLEXCAN_Type * pBase,
    uint8 u8MbIndex,
    boolean bIsLegacyFifoEn,
    uint32 u32MaxMbNum
)
{
    boolean returnValue = (boolean)FALSE;
    uint32 u32NumOfFiFoElement = 0U;
    uint32 u32NumOfMbOccupiedByFiFo = 0U;

    if (u8MbIndex >= (uint8)u32MaxMbNum)
    {
       returnValue = (boolean)TRUE;
    }
    /* Check if RX FIFO is enabled*/
    else if ((boolean)TRUE == bIsLegacyFifoEn)
    {
        /* Get the number of RX FIFO Filters*/
        u32NumOfFiFoElement = (((pBase->CTRL2) & FLEXCAN_CTRL2_RFFN_MASK) >> FLEXCAN_CTRL2_RFFN_SHIFT);
        /* Get the number if MBs occupied by RX FIFO and ID filter table*/
        /* the Rx FIFO occupies the memory space originally reserved for MB0-5*/
        /* Every number of RFFN means 8 number of RX FIFO filters*/
        /* and every 4 number of RX FIFO filters occupied one MB*/
        u32NumOfMbOccupiedByFiFo = 5U + ((((u32NumOfFiFoElement) + 1U) * 8U) / 4U);
        if (u8MbIndex <= u32NumOfMbOccupiedByFiFo)
        {
            returnValue = (boolean)TRUE;
        }
    }
    else
    {
        returnValue = (boolean)FALSE;
    }

    return returnValue;
}

#if (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON)

/*FUNCTION**********************************************************************
 *
 * Function Name : FLEXCAN_IsEnhancedRxFifoAvailable
 * Description   : Checks if FlexCAN has Enhanced Rx FIFO.
 * This function is private.
 *
 *END**************************************************************************/
boolean FlexCAN_IsEnhancedRxFifoAvailable(const FLEXCAN_Type * base)
{
    uint32 i=0U;
    static FLEXCAN_Type * const flexcanBase[] = CAN_BASE_PTRS_HAS_ENHANCED_RX_FIFO;
    boolean returnValue = FALSE;
    for (i = 0U; i < FEATURE_CAN_ENHANCED_RX_FIFO_NUM; i++)
    {
        if (base == flexcanBase[i])
        {
            returnValue = TRUE;
            break;
        }
    }

    return returnValue;
}


/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_EnableEnhancedRxFifo
 * Description   : Enable Enhanced Rx FIFO feature.
 * This function will enable the Enhanced Rx FIFO feature.
 *
 *END**************************************************************************/
Flexcan_Ip_StatusType FlexCAN_EnableEnhancedRxFifo(FLEXCAN_Type * base,
                                      uint32 numOfStdIDFilters,
                                      uint32 numOfExtIDFilters,
                                      uint32 numOfWatermark)
{
    Flexcan_Ip_StatusType stat = FLEXCAN_STATUS_SUCCESS;
    uint32 numOfEnhancedFilters = 0U;

    if (FlexCAN_IsEnhancedRxFifoAvailable(base))
    {

        /* numOfEnhancedFilters equals (numOfStdIDFilters/2) + numOfExtIDFilters - 1u */
        numOfEnhancedFilters = (numOfStdIDFilters >> 1u) + numOfExtIDFilters - 1u;

        if ((numOfStdIDFilters == 0U) && (numOfExtIDFilters == 0U))
        {
            stat = FLEXCAN_STATUS_ERROR;
        }
        /* If the no of Std Filters is odd */
        if ((numOfStdIDFilters & 1U) == 1U)
        {
             stat = FLEXCAN_STATUS_ERROR;
        }
        /*Enhanced RX FIFO and Legacy RX FIFO cannot be enabled at the same time.*/
        if ((base->MCR & FLEXCAN_MCR_RFEN_MASK) == FLEXCAN_MCR_RFEN_MASK)
        {
            stat = FLEXCAN_STATUS_ERROR;
        }

        if (stat == FLEXCAN_STATUS_SUCCESS)
        {
            /* Enable Enhanced Rx FIFO */
            base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_ERFEN_MASK) | FLEXCAN_ERFCR_ERFEN(1U);
            /* Reset Enhanced Rx FIFO engine */
            base->ERFSR = (base->ERFSR & ~FLEXCAN_ERFSR_ERFCLR_MASK) | FLEXCAN_ERFSR_ERFCLR(1U);
            /* Clear the status bits of the Enhanced RX FIFO */
            base->ERFSR = base->ERFSR & ~(FLEXCAN_ERFSR_ERFUFW_MASK | FLEXCAN_ERFSR_ERFOVF_MASK | FLEXCAN_ERFSR_ERFWMI_MASK | FLEXCAN_ERFSR_ERFDA_MASK);
            /* Set the total number of enhanced Rx FIFO filter elements */
            base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_NFE_MASK) | ((numOfEnhancedFilters << FLEXCAN_ERFCR_NFE_SHIFT) & FLEXCAN_ERFCR_NFE_MASK);
            /* Set the number of extended ID filter elements */
            base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_NEXIF_MASK) | ((numOfExtIDFilters << FLEXCAN_ERFCR_NEXIF_SHIFT) & FLEXCAN_ERFCR_NEXIF_MASK);
            /* Set the Enhanced Rx FIFO watermark */
            base->ERFCR = (base->ERFCR & ~FLEXCAN_ERFCR_ERFWM_MASK) | ((numOfWatermark << FLEXCAN_ERFCR_ERFWM_SHIFT) & FLEXCAN_ERFCR_ERFWM_MASK);
        }
    }
    else
    {
        stat = FLEXCAN_STATUS_ERROR;
    }

    return stat;
}

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_SetEnhancedRxFifoFilter
 * Description   : Configure Enhanced RX FIFO ID filter table elements.
 *
 *END**************************************************************************/
void FlexCAN_SetEnhancedRxFifoFilter(FLEXCAN_Type * base,
                                     const Flexcan_Ip_EnhancedIdTableType * idFilterTable)
{
    /* Set Enhanced RX FIFO ID filter table elements*/
    uint32 i, j, n, numOfEnhancedFilter, numOfExtIDFilter, numOfStdIDFilter;
    uint32 val2 = 0U, val1 = 0U, val = 0U;

    volatile uint32 * filterExtIDTable = NULL_PTR;
    volatile uint32 * filterStdIDTable = NULL_PTR;

    numOfEnhancedFilter = (((base->ERFCR) & FLEXCAN_ERFCR_NFE_MASK) >> FLEXCAN_ERFCR_NFE_SHIFT);
    numOfExtIDFilter = (((base->ERFCR) & FLEXCAN_ERFCR_NEXIF_MASK) >> FLEXCAN_ERFCR_NEXIF_SHIFT);
    numOfStdIDFilter = 2U * (numOfEnhancedFilter - numOfExtIDFilter + 1U);
    filterExtIDTable = &base->ERFFEL[EnhancedRxFifoFilterTableBase];
    filterStdIDTable = &base->ERFFEL[numOfExtIDFilter * 2U];
    j = 0U;
    n = 0U;
    for (i = 0U; i < (numOfExtIDFilter + numOfStdIDFilter); i++)
    {
        if (!(idFilterTable[i].isExtendedFrame))
        {
            val = 0U;
            if (idFilterTable[i].rtr2)
            {
                val = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_RTR2_SHIFT;
            }

            if (idFilterTable[i].rtr1)
            {
                val |= FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_RTR1_SHIFT;
            }

            filterStdIDTable[j] =
                ((idFilterTable[i].id2 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_SHIFT2) |
                ((idFilterTable[i].id1 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_STD_SHIFT1) | val;
            switch (idFilterTable[i].filterType)
            {
                case FLEXCAN_ENHANCED_RX_FIFO_ONE_ID_FILTER :
                {
                    filterStdIDTable[j] |= FlexCanEnhancedRxFifoOneIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
                }break;

                case FLEXCAN_ENHANCED_RX_FIFO_RANGE_ID_FILTER :
                {
                    filterStdIDTable[j] |= FlexCanEnhancedRxFifoRangerIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
                }break;

                case FLEXCAN_ENHANCED_RX_FIFO_TWO_ID_FILTER :
                {
                    filterStdIDTable[j] |= FlexCanEnhancedRxFifoTwoIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
                }break;
                default:
                {
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
                    DevAssert((boolean)FALSE);
                    /* Should not get here */
#endif
                }break;
            }

            j++;
        }
        else
        {
            val2 = 0U;
            val1 = 0U;
            if (idFilterTable[i].rtr2)
            {
                val2 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_RTR_SHIFT;
            }

            if (idFilterTable[i].rtr1)
            {
                val1 = FlexCanRxFifoAcceptRemoteFrame << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_RTR_SHIFT;
            }
            filterExtIDTable[n] = ((idFilterTable[i].id2 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_SHIFT) |
                                    val2;

            filterExtIDTable[n + 1U] = ((idFilterTable[i].id1 & FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_MASK) << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_EXT_SHIFT) |
                                        val1;
            switch (idFilterTable[i].filterType)
            {
                case FLEXCAN_ENHANCED_RX_FIFO_ONE_ID_FILTER :
                {
                    filterExtIDTable[n] |= FlexCanEnhancedRxFifoOneIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
                }break;
                case FLEXCAN_ENHANCED_RX_FIFO_RANGE_ID_FILTER :
                {
                    filterExtIDTable[n] |= FlexCanEnhancedRxFifoRangerIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
                }break;
                case FLEXCAN_ENHANCED_RX_FIFO_TWO_ID_FILTER :
                {
                    filterExtIDTable[n] |= FlexCanEnhancedRxFifoTwoIDFilter << FLEXCAN_ENHANCED_RX_FIFO_ID_FILTER_FSCH_SHIFT;
                }break;
                default :
                {
#if (FLEXCAN_DEV_ERROR_DETECT == STD_ON)
                    DevAssert((boolean)FALSE);
                    /* Should not get here */
#endif
                }break;
            }
            n = n + 2U;
        }
    }
}

#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_ClearOutputEnhanceFIFO
 * Description   : Clear output of enhance fifo.
 *
 *END**************************************************************************/
void FlexCAN_ClearOutputEnhanceFIFO(FLEXCAN_Type * base)
{
    volatile uint32 * Ram = (uint32 *)((uint32)base);
    uint32 lastword_offset = ((uint32)0x204C) / ((uint32)4U); /* fixed, because DMALW is always = 19 */
    uint8 u8TimeOut = 0;

    /* If Enhanced Rx FIFO has Pending Request that generated error,
     * the EnhancedRxFIFO need to be empty to activate DMA */
    if (FlexCAN_GetEnhancedRxFIFOStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE) == (uint8)1U)
    {
        /* Enter CAN in freeze Mode to allow Enhanced Rx FIFO Clear */
        FlexCAN_EnterFreezeMode(base);
        FlexCAN_ClearEnhancedFIFO(base);

        do
        {
            if ((uint32)FLEXCAN_MCR_DMA_MASK == (base->MCR & ((uint32)FLEXCAN_MCR_DMA_MASK)))
            {
                /* Read Enhanced Output to clear DMA pending request */
                (void)Ram[lastword_offset];
            }
            else
            {
                FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE);
            }
            u8TimeOut++;
        }
        while ((FlexCAN_GetEnhancedRxFIFOStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE) == (uint8)1U) && (u8TimeOut <= ((uint8)64U))); /* avoid blocking */

        FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_OVERFLOW);
        FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_WATERMARK);
        FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_FRAME_AVAILABLE);
        FlexCAN_ClearEnhancedRxFifoIntStatusFlag(base, CAN_ENHANCED_RXFIFO_UNDERFLOW);

        /* Return CAN to normal Mode */
        FlexCAN_ExitFreezeMode(base);
    }
}
#endif /* (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON) */
#endif /* (FEATURE_CAN_HAS_ENHANCED_RX_FIFO == STD_ON) */
#if (FEATURE_CAN_HAS_DMA_ENABLE == STD_ON)
/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_ClearOutputLegacyFIFO
 * Description   : Clear output of legacy fifo.
 *
 *END**************************************************************************/
void FlexCAN_ClearOutputLegacyFIFO(FLEXCAN_Type * base)
{
    volatile uint32 * Ram = (uint32 *)((uint32)base);
    uint32 lastword_offset = ((uint32)0x8C) / ((uint32)4U); /* fixed, dma last word */
    uint8 i = 0;

    /* Check if FIFO has Pending Request that generated error,
    * the RxFIFO need to be empty to activate DMA */
    if (FlexCAN_GetBuffStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE) == (uint8)1U)
    {
        /* Enter CAN in freeze Mode to allow FIFO Clear */
        FlexCAN_EnterFreezeMode(base);
        FlexCAN_ClearFIFO(base);
        do
        {
            if ((uint32)FLEXCAN_MCR_DMA_MASK == (base->MCR & ((uint32)FLEXCAN_MCR_DMA_MASK)))
            {
                /* Read Offset 0x8C to clear DMA pending request */
                (void)Ram[lastword_offset];
            }
            else
            {
                FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE);
            }
            i++;
        }
        while ((FlexCAN_GetBuffStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE) == (uint8)1U) && (i <= (uint8)12U)); /* avoid blocking */
        FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_FRAME_AVAILABLE);
        FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_WARNING);
        FlexCAN_ClearMsgBuffIntStatusFlag(base, CAN_LEGACY_RXFIFO_OVERFLOW);

        /* Return CAN to normal Mode */
        FlexCAN_ExitFreezeMode(base);
    }
}
#endif /* FEATURE_CAN_HAS_DMA_ENABLE */

#if (FEATURE_CAN_HAS_HR_TIMER == STD_ON)
void FlexCAN_ConfigTimestamp(FLEXCAN_Type * base, Flexcan_Ip_TimeStampConfigType * config)
{
    uint32 temp = 0U;
    temp = FLEXCAN_CTRL2_TIMER_SRC(config->timeStampSurce);
    temp |= FLEXCAN_CTRL2_MBTSBASE(config->msgBuffTimeStampType);
    temp |= FLEXCAN_CTRL2_TSTAMPCAP(config->hrConfigType);

    base->CTRL2 &= ~(FLEXCAN_CTRL2_TIMER_SRC_MASK | FLEXCAN_CTRL2_MBTSBASE_MASK | FLEXCAN_CTRL2_TSTAMPCAP_MASK);
    base->CTRL2 |= temp;

    if (config->hrConfigType != FLEXCAN_TIMESTAMPCAPTURE_DISABLE)
    {
        FlexCAN_ConfigTimestampModule(config);
    }
}
#endif /* (FEATURE_CAN_HAS_HR_TIMER == STD_ON) */

/*FUNCTION**********************************************************************
 *
 * Function Name : FlexCAN_ConfigCtrlOptions
 * Description   : configure controller depending on options
 * note: should be call after FD configuration.
 *
 *END**************************************************************************/
void FlexCAN_ConfigCtrlOptions(FLEXCAN_Type * pBase, uint32 u32Options)
{
#if (FEATURE_CAN_SWITCHINGISOMODE == STD_ON)
    /* If the FD feature is enabled, in order to be ISO-compliant. */
    if ((u32Options & CAN_FD_ISO_U32) != 0U)
    {
        FlexCAN_SetIsoCan(pBase, (boolean)TRUE);
    }
    else
    {
        /* This maybe don't have sense if the Deinit returns the state of registers at init values */
        FlexCAN_SetIsoCan(pBase, (boolean)FALSE);
    }
#endif /*(FEATURE_CAN_SWITCHINGISOMODE == STD_ON) */
    /* Set Entire Frame Arbitration Field Comparison. */
    if ((u32Options & CAN_EACEN_U32) != 0U)
    {
        FlexCAN_SetEntireFrameArbitrationFieldComparison(pBase, (boolean)TRUE);
    }
    else
    {
        FlexCAN_SetEntireFrameArbitrationFieldComparison(pBase, (boolean)FALSE);
    }
#if (FEATURE_CAN_PROTOCOLEXCEPTION == STD_ON)
    /* Set protocol Exception */
    if ((u32Options & CAN_PROTOCOL_EXCEPTION_U32) != 0U)
    {
        FlexCAN_SetProtocolException(pBase, (boolean)TRUE);
    }
    else
    {
        FlexCAN_SetProtocolException(pBase, (boolean)FALSE);
    }
#endif /* Endif  (FEATURE_CAN_PROTOCOLEXCEPTION == STD_ON)  */
    /* Set CAN Bit Sampling */
    if (((u32Options & CAN_THREE_SAMPLES_U32) != 0U) && ((pBase->MCR & FLEXCAN_MCR_FDEN_MASK) == 0U))
    {
        FlexCAN_CanBitSampling(pBase, (boolean)TRUE);
    }
    else
    {
        FlexCAN_CanBitSampling(pBase, (boolean)FALSE);
    }

    /* Set AutoBusOff Recovery */
    if ((u32Options & CAN_BUSOFF_RECOVERY_U32) != 0U)
    {
        FlexCAN_SetBusOffAutorecovery(pBase, (boolean)TRUE);
    }
    else
    {
        FlexCAN_SetBusOffAutorecovery(pBase, (boolean)FALSE);
    }
#if (FEATURE_CAN_EDGEFILTER == STD_ON)
    /* Set Edge Filter */
    if ((u32Options & CAN_EDGE_FILTER_U32) != 0U)
    {
        FlexCAN_SetEdgeFilter(pBase, (boolean)TRUE);
    }
    else
    {
        FlexCAN_SetEdgeFilter(pBase, (boolean)FALSE);
    }
#endif /* End of (FEATURE_CAN_EDGEFILTER == STD_ON)  */
}

#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"

/** @} */
