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

/* ========================================================================== */
/*                             Include Files                                  */
/* ========================================================================== */

#include "mcan.h"
#define CAN_START_SEC_CODE
#include "Can_MemMap.h"
#include "hw_types.h"
#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"
/* Includes for MCAL */
#include "string.h"
#include "Can_Priv.h"
#include "EcuM_Cbk.h"
#include "Can_Cfg.h"

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

/**
 * \brief  Macro for standard Message ID filter.
 */
#define MCANSS_STD_ID_FILTER_SIZE_WORDS                          (1U)

/**
 * \brief  Macro for extended Message ID filter.
 */
#define MCANSS_EXT_ID_FILTER_SIZE_WORDS                          (2U)

/**
 * \brief  Macro for Interrupt Line enable mask.
 */
#define MCANSS_INTR_LINE_EN_MASK   ((MCAN_ILE_EINT0_MASK | MCAN_ILE_EINT1_MASK))

/**
 * \brief  Mask and shift for Tx Buffers elements.
 */
#define MCANSS_TX_BUFFER_ELEM_ID_SHIFT                           (0U)
#define MCANSS_TX_BUFFER_ELEM_ID_MASK                            (0x1FFFFFFFU)
#define MCANSS_TX_BUFFER_ELEM_RTR_SHIFT                          (29U)
#define MCANSS_TX_BUFFER_ELEM_RTR_MASK                           (0x20000000U)
#define MCANSS_TX_BUFFER_ELEM_XTD_SHIFT                          (30U)
#define MCANSS_TX_BUFFER_ELEM_XTD_MASK                           (0x40000000U)
#define MCANSS_TX_BUFFER_ELEM_ESI_SHIFT                          (31U)
#define MCANSS_TX_BUFFER_ELEM_ESI_MASK                           (0x80000000U)
#define MCANSS_TX_BUFFER_ELEM_DLC_SHIFT                          (16U)
#define MCANSS_TX_BUFFER_ELEM_DLC_MASK                           (0x000F0000U)
#define MCANSS_TX_BUFFER_ELEM_BRS_SHIFT                          (20U)
#define MCANSS_TX_BUFFER_ELEM_BRS_MASK                           (0x00100000U)
#define MCANSS_TX_BUFFER_ELEM_FDF_SHIFT                          (21U)
#define MCANSS_TX_BUFFER_ELEM_FDF_MASK                           (0x00200000U)
#define MCANSS_TX_BUFFER_ELEM_EFC_SHIFT                          (23U)
#define MCANSS_TX_BUFFER_ELEM_EFC_MASK                           (0x00800000U)
#define MCANSS_TX_BUFFER_ELEM_MM_SHIFT                           (24U)
#define MCANSS_TX_BUFFER_ELEM_MM_MASK                            (0xFF000000U)

/**
 * \brief  Mask and shift for Rx Buffers elements.
 */
#define MCANSS_RX_BUFFER_ELEM_ID_SHIFT                           (0U)
#define MCANSS_RX_BUFFER_ELEM_ID_MASK                            (0x1FFFFFFFU)
#define MCANSS_RX_BUFFER_ELEM_RTR_SHIFT                          (29U)
#define MCANSS_RX_BUFFER_ELEM_RTR_MASK                           (0x20000000U)
#define MCANSS_RX_BUFFER_ELEM_XTD_SHIFT                          (30U)
#define MCANSS_RX_BUFFER_ELEM_XTD_MASK                           (0x40000000U)
#define MCANSS_RX_BUFFER_ELEM_ESI_SHIFT                          (31U)
#define MCANSS_RX_BUFFER_ELEM_ESI_MASK                           (0x80000000U)
#define MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT                         (0U)
#define MCANSS_RX_BUFFER_ELEM_RXTS_MASK                          (0x0000FFFFU)
#define MCANSS_RX_BUFFER_ELEM_DLC_SHIFT                          (16U)
#define MCANSS_RX_BUFFER_ELEM_DLC_MASK                           (0x000F0000U)
#define MCANSS_RX_BUFFER_ELEM_BRS_SHIFT                          (20U)
#define MCANSS_RX_BUFFER_ELEM_BRS_MASK                           (0x00100000U)
#define MCANSS_RX_BUFFER_ELEM_FDF_SHIFT                          (21U)
#define MCANSS_RX_BUFFER_ELEM_FDF_MASK                           (0x00200000U)
#define MCANSS_RX_BUFFER_ELEM_FIDX_SHIFT                         (24U)
#define MCANSS_RX_BUFFER_ELEM_FIDX_MASK                          (0x7F000000U)
#define MCANSS_RX_BUFFER_ELEM_ANMF_SHIFT                         (31U)
#define MCANSS_RX_BUFFER_ELEM_ANMF_MASK                          (0x80000000U)

/**
 * \brief  Mask and shift for Standard Message ID Filter Elements.
 */
#define MCANSS_STD_ID_FILTER_SFID2_SHIFT                         (0U)
#define MCANSS_STD_ID_FILTER_SFID2_MASK                          (0x000003FFU)
#define MCANSS_STD_ID_FILTER_SFID1_SHIFT                         (16U)
#define MCANSS_STD_ID_FILTER_SFID1_MASK                          (0x03FF0000U)
#define MCANSS_STD_ID_FILTER_SFEC_SHIFT                          (27U)
#define MCANSS_STD_ID_FILTER_SFEC_MASK                           (0x38000000U)
#define MCANSS_STD_ID_FILTER_SFT_SHIFT                           (30U)
#define MCANSS_STD_ID_FILTER_SFT_MASK                            (0xC0000000U)

/**
 * \brief  Extended Message ID Filter Element.
 */
#define MCANSS_EXT_ID_FILTER_EFID2_SHIFT                        (0U)
#define MCANSS_EXT_ID_FILTER_EFID2_MASK                         (0x1FFFFFFFU)
#define MCANSS_EXT_ID_FILTER_EFID1_SHIFT                        (0U)
#define MCANSS_EXT_ID_FILTER_EFID1_MASK                         (0x1FFFFFFFU)
#define MCANSS_EXT_ID_FILTER_EFEC_SHIFT                         (29U)
#define MCANSS_EXT_ID_FILTER_EFEC_MASK                          (0xE0000000U)
#define MCANSS_EXT_ID_FILTER_EFT_SHIFT                          (30U)
#define MCANSS_EXT_ID_FILTER_EFT_MASK                           (0xC0000000U)

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

/* None */

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

/**
 * \brief   This API will unblock write access to write protected registers.
 *
 * \param   baseAddr        Base Address of the MCAN Registers.
 *
 * \return  None.
 */
static void MCAN_writeProtectedRegAccessUnlock(uint32_t baseAddr);

/**
 * \brief   This API will block write access to write protected registers.
 *
 * \param   baseAddr        Base Address of the MCAN Registers.
 *
 * \return  None.
 */
static void MCAN_writeProtectedRegAccessLock(uint32_t baseAddr);

/**
 * \brief   This API will load the register from ECC memory bank.
 *
 * \param   baseAddr        Base Address of the MCAN Registers.
 * \param   regOffset       Offset of the register to read.
 *
 * \return  None.
 */
static void MCAN_eccLoadRegister(uint32_t baseAddr, uint32_t regOffSet);

/**
 * \brief   This API will read the message object from Message RAM.
 *
 * \param   baseAddr        Base Address of the MCAN Registers.
 * \param   elemAddr        Address of the message object.
 * \param   elem            Message Object.
 *                          Refer struct #MCAN_RxBufElement.
 *
 * \return  None.
 */
static void MCAN_readMsg(uint32_t           baseAddr,
                         uint32_t           elemAddr,
                         MCAN_RxBufElement *elem);

/**
 * \brief   This API will write the message object to Message RAM.
 *
 * \param   baseAddr        Base Address of the MCAN Registers.
 * \param   elemAddr        Address of the message object.
 * \param   elem            Message Object.
 *                          Refer struct #MCAN_TxBufElement.
 *
 * \return  None.
 */
static void MCAN_writeMsg(uint32_t                 baseAddr,
                          uint32_t                 elemAddr,
                          const MCAN_TxBufElement *elem);

/**
 * \brief   This API will return payload depending on 'data_length'  field.
 *
 * \param   data_length             Data Length Code.
 *
 * \return  data size       Size of the payload.
 */
static uint32_t MCAN_getDataSize(uint32_t data_length);

/**
 * \brief   This API will return message object size.
 *
 * \param   data_length             Data Length Code.
 *
 * \return  message object size
 *                          Size of the message object stored in Message RAM.
 */
static uint32_t MCAN_getMsgObjSize(uint32_t elemSize);

/* ========================================================================== */
/*                            Global Variables                                */
/* ========================================================================== */

/* None */

/* ========================================================================== */
/*                          Function Definitions                              */
/* ========================================================================== */
/* Memory mapping, done via MemMap.h: Code */
#define CAN_START_SEC_CODE
#include "Can_MemMap.h"
void MCAN_reset(uint32_t baseAddr)
{

    HW_WR_FIELD32(baseAddr + MCAN_MCANSS_CTRL,
                  MCAN_MCANSS_CTRL_RESET,
                  0x1U);

}

uint32_t MCAN_isInReset(uint32_t baseAddr)
{
    return((uint32_t)HW_RD_FIELD32(baseAddr + MCAN_MCANSS_STAT,
                          MCAN_MCANSS_STAT_RESET));
}

uint32_t MCAN_isMemInitDone(uint32_t baseAddr)
{
  uint32_t memInit;
  uint32_t state;
  memInit = HW_RD_FIELD32((baseAddr)+MCAN_MCANSS_STAT,
    MCAN_MCANSS_STAT_MEM_INIT_DONE);
  if (1U == memInit)
  {
    state = (uint32_t)TRUE;
  }
  else
  {
    state = (uint32_t)FALSE;
  }
  return state;
}

void MCAN_setOpMode(uint32_t baseAddr, uint32_t mode)
{
    HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_INIT, mode);
}

uint32_t MCAN_getOpMode(uint32_t baseAddr)
{
    return (HW_RD_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_INIT));
}

int32_t MCAN_init(uint32_t baseAddr, const MCAN_InitParams *initParams)
{
    int32_t  status;
    uint32_t regVal;
    /* Configure MCAN wakeup and clock stop controls */
    regVal = HW_RD_REG32(baseAddr + MCAN_MCANSS_CTRL);
    HW_SET_FIELD32(regVal,
                   MCAN_MCANSS_CTRL_WAKEUPREQEN,
                   initParams->wkupReqEnable);
    HW_SET_FIELD32(regVal,
                   MCAN_MCANSS_CTRL_AUTOWAKEUP,
                   initParams->autoWkupEnable);

    HW_SET_FIELD32(regVal,
                   MCAN_MCANSS_CTRL_EMUEN,
                   initParams->emulationEnable);
    HW_SET_FIELD32(regVal,
                   MCAN_MCANSS_CTRL_EMUFACK,
                   initParams->emulationFAck);
    HW_SET_FIELD32(regVal,
                   MCAN_MCANSS_CTRL_CLKFACK,
                   initParams->clkStopFAck);

    HW_WR_REG32(baseAddr + MCAN_MCANSS_CTRL, regVal);

    MCAN_writeProtectedRegAccessUnlock(baseAddr);

    /* Configure MCAN mode(FD vs Classic CAN operation) and controls */
    regVal = HW_RD_REG32(baseAddr + MCAN_CCCR);
    HW_SET_FIELD32(regVal,
                   MCAN_CCCR_FDOE,
                   initParams->fdMode);
    HW_SET_FIELD32(regVal,
                   MCAN_CCCR_BRSE,
                   initParams->brsEnable);
    HW_SET_FIELD32(regVal,
                   MCAN_CCCR_TXP,
                   initParams->txpEnable);
    HW_SET_FIELD32(regVal,
                   MCAN_CCCR_EFBI,
                   initParams->efbi);
    HW_SET_FIELD32(regVal,
                   MCAN_CCCR_PXHD,
                   initParams->pxhddisable);
    HW_SET_FIELD32(regVal,
                   MCAN_CCCR_DAR,
                   initParams->darEnable);
    HW_WR_REG32(baseAddr + MCAN_CCCR, regVal);

    if ((MCAN_TDCR_TDCF_MAX >= initParams->tdcConfig.tdcf) &&
        (MCAN_TDCR_TDCO_MAX >= initParams->tdcConfig.tdco) &&
        (MCAN_RWD_WDC_MAX >= initParams->wdcPreload))
    {
        /* Configure Transceiver Delay Compensation */
        HW_WR_FIELD32(baseAddr + MCAN_TDCR,
                      MCAN_TDCR_TDCF,
                      initParams->tdcConfig.tdcf);
        HW_WR_FIELD32(baseAddr + MCAN_TDCR,
                      MCAN_TDCR_TDCO,
                      initParams->tdcConfig.tdco);
        /* Configure MSG RAM watchdog counter preload value */
        HW_WR_FIELD32(baseAddr + MCAN_RWD,
                      MCAN_RWD_WDC,
                      initParams->wdcPreload);
        /* Enable/Disable Transceiver Delay Compensation */
        HW_WR_FIELD32(baseAddr + MCAN_DBTP,
                      MCAN_DBTP_TDC,
                      initParams->tdcEnable);
        status = STW_SOK;
    }
    else
    {
        status = STW_EFAIL;
    }

    MCAN_writeProtectedRegAccessLock(baseAddr);

    return status;
}

int32_t MCAN_config(uint32_t baseAddr, const MCAN_ConfigParams *configParams)
{
    int32_t status;

    MCAN_writeProtectedRegAccessUnlock(baseAddr);

    /* Configure MCAN control registers */
    HW_WR_FIELD32(baseAddr + MCAN_CCCR,
                  MCAN_CCCR_MON,
                  configParams->monEnable);
    HW_WR_FIELD32(baseAddr + MCAN_CCCR,
                  MCAN_CCCR_ASM,
                  configParams->asmEnable);
    /* Configure Global Filter */
    HW_WR_FIELD32(baseAddr + MCAN_GFC,
                  MCAN_GFC_RRFE,
                  configParams->filterConfig.rrfe);
    HW_WR_FIELD32(baseAddr + MCAN_GFC,
                  MCAN_GFC_RRFS,
                  configParams->filterConfig.rrfs);
    HW_WR_FIELD32(baseAddr + MCAN_GFC,
                  MCAN_GFC_ANFE,
                  configParams->filterConfig.anfe);
    HW_WR_FIELD32(baseAddr + MCAN_GFC,
                  MCAN_GFC_ANFS,
                  configParams->filterConfig.anfs);

    if ((MCAN_TSCC_TCP_MAX >= configParams->tsPrescalar) &&
        (MCAN_TOCC_TOP_MAX >= configParams->timeoutPreload))
    {
        /* Configure Time-stamp counter */
        HW_WR_FIELD32(baseAddr + MCAN_TSCC,
                      MCAN_TSCC_TSS,
                      configParams->tsSelect);
        HW_WR_FIELD32(baseAddr + MCAN_TSCC,
                      MCAN_TSCC_TCP,
                      (configParams->tsPrescalar - 1U));
        /* Configure Time-out counter */
        HW_WR_FIELD32(baseAddr + MCAN_TOCC,
                      MCAN_TOCC_TOS,
                      configParams->timeoutSelect);
        HW_WR_FIELD32(baseAddr + MCAN_TOCC,
                      MCAN_TOCC_TOP,
                      configParams->timeoutPreload);
        /* Enable Time-out counter */
        HW_WR_FIELD32(baseAddr + MCAN_TOCC,
                      MCAN_TOCC_ETOC,
                      configParams->timeoutCntEnable);
        status = STW_SOK;
    }
    else
    {
        status = STW_EFAIL;
    }

    MCAN_writeProtectedRegAccessLock(baseAddr);

    return status;
}

void MCAN_eccConfig(uint32_t                    baseAddr,
                    const MCAN_ECCConfigParams *configParams)
{
  uint32_t regVal;

    baseAddr = (baseAddr&(~MCAN_RAM_OFFSET))>>4;
    regVal = HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_CONTROL);
    HW_SET_FIELD32(regVal,
                   MCAN_ECC_AGGR_CONTROL_ECC_CHECK,
                   configParams->enableChk);
    HW_SET_FIELD32(regVal,
                   MCAN_ECC_AGGR_CONTROL_ECC_ENABLE,
                   configParams->enable);
    HW_SET_FIELD32(regVal,
                   MCAN_ECC_AGGR_CONTROL_ENABLE_RMW,
                   configParams->enableRdModWr);
    HW_WR_REG32(baseAddr + MCAN_ECC_AGGR_CONTROL, regVal);

}

int32_t MCAN_setBitTime(uint32_t                    baseAddr,
                        const MCAN_BitTimingParams *configParams)
{
    int32_t status;

    MCAN_writeProtectedRegAccessUnlock(baseAddr);

    if ((MCAN_NBTP_NSJW_MAX >= configParams->nomSynchJumpWidth) &&
        (MCAN_NBTP_NTSEG2_MAX >= configParams->nomTimeSeg2) &&
        (MCAN_NBTP_NTSEG1_MAX >= configParams->nomTimeSeg1) &&
        (MCAN_NBTP_NBRP_MAX >= configParams->nomRatePrescalar))
    {
        HW_WR_FIELD32(baseAddr + MCAN_NBTP,
                      MCAN_NBTP_NSJW,
                      configParams->nomSynchJumpWidth);
        HW_WR_FIELD32(baseAddr + MCAN_NBTP,
                      MCAN_NBTP_NTSEG2,
                      configParams->nomTimeSeg2);
        HW_WR_FIELD32(baseAddr + MCAN_NBTP,
                      MCAN_NBTP_NTSEG1,
                      configParams->nomTimeSeg1);
        HW_WR_FIELD32(baseAddr + MCAN_NBTP,
                      MCAN_NBTP_NBRP,
                      configParams->nomRatePrescalar);
        status = STW_SOK;
    }
    else
    {
        status = STW_EFAIL;
    }
    if (STW_SOK == status)
    {
        if ((MCAN_DBTP_DSJW_MAX >= configParams->dataSynchJumpWidth) &&
            (MCAN_DBTP_DTSEG2_MAX >= configParams->dataTimeSeg2) &&
            (MCAN_DBTP_DTSEG1_MAX >= configParams->dataTimeSeg1) &&
            (MCAN_DBTP_DBRP_MAX >= configParams->dataRatePrescalar))
        {
            HW_WR_FIELD32(baseAddr + MCAN_DBTP,
                          MCAN_DBTP_DSJW,
                          configParams->dataSynchJumpWidth);
            HW_WR_FIELD32(baseAddr + MCAN_DBTP,
                          MCAN_DBTP_DTSEG2,
                          configParams->dataTimeSeg2);
            HW_WR_FIELD32(baseAddr + MCAN_DBTP,
                          MCAN_DBTP_DTSEG1,
                          configParams->dataTimeSeg1);
            HW_WR_FIELD32(baseAddr + MCAN_DBTP,
                          MCAN_DBTP_DBRP,
                          configParams->dataRatePrescalar);
            status = STW_SOK;
        }
        else
        {
            status = STW_EFAIL;
        }
    }

    MCAN_writeProtectedRegAccessLock(baseAddr);
    return status;
}

int32_t MCAN_msgRAMConfig(uint32_t                       baseAddr,
                          const MCAN_MsgRAMConfigParams *msgRAMConfigParams)
{
    int32_t  status;
    uint32_t elemNum = 0U;

    MCAN_writeProtectedRegAccessUnlock(baseAddr);

    /* Configure Message Filters section */
    if (0U != msgRAMConfigParams->lss)
    {
        HW_WR_FIELD32(baseAddr + MCAN_SIDFC,
                      MCAN_SIDFC_FLSSA,
                      (msgRAMConfigParams->flssa >> 2U));
        HW_WR_FIELD32(baseAddr + MCAN_SIDFC,
                      MCAN_SIDFC_LSS,
                      msgRAMConfigParams->lss);
    }
    if (0U != msgRAMConfigParams->lse)
    {
        HW_WR_FIELD32(baseAddr + MCAN_XIDFC,
                      MCAN_XIDFC_FLESA,
                      (msgRAMConfigParams->flesa >> 2U));
        HW_WR_FIELD32(baseAddr + MCAN_XIDFC,
                      MCAN_XIDFC_LSE,
                      msgRAMConfigParams->lse);
    }
    /* Configure Rx FIFO 0 section */
    if (0U != msgRAMConfigParams->rxFIFO0size)
    {
        HW_WR_FIELD32(baseAddr + MCAN_RXF0C,
                      MCAN_RXF0C_F0SA,
                      (msgRAMConfigParams->rxFIFO0startAddr >> 2U));
        HW_WR_FIELD32(baseAddr + MCAN_RXF0C,
                      MCAN_RXF0C_F0S,
                      msgRAMConfigParams->rxFIFO0size);
        HW_WR_FIELD32(baseAddr + MCAN_RXF0C,
                      MCAN_RXF0C_F0WM,
                      msgRAMConfigParams->rxFIFO0waterMark);
        HW_WR_FIELD32(baseAddr + MCAN_RXF0C,
                      MCAN_RXF0C_F0OM,
                      msgRAMConfigParams->rxFIFO0OpMode);
        /* Configure Rx FIFO0 elements size */
        HW_WR_FIELD32(baseAddr + MCAN_RXESC,
                      MCAN_RXESC_F0DS,
                      msgRAMConfigParams->rxFIFO0ElemSize);
    }
    /* Configure Rx FIFO 1 section */
    if (0U != msgRAMConfigParams->rxFIFO1size)
    {
        HW_WR_FIELD32((baseAddr) + MCAN_RXF1C,
                      MCAN_RXF1C_F1SA,
                      (msgRAMConfigParams->rxFIFO1startAddr >> 2U));
        HW_WR_FIELD32((baseAddr) + MCAN_RXF1C,
                      MCAN_RXF1C_F1S,
                      msgRAMConfigParams->rxFIFO1size);
        HW_WR_FIELD32((baseAddr) + MCAN_RXF1C,
                      MCAN_RXF1C_F1WM,
                      msgRAMConfigParams->rxFIFO1waterMark);
        HW_WR_FIELD32((baseAddr) + MCAN_RXF1C,
                      MCAN_RXF1C_F1OM,
                      msgRAMConfigParams->rxFIFO1OpMode);
        /* Configure Rx FIFO1 elements size */
        HW_WR_FIELD32((baseAddr) + MCAN_RXESC,
                      MCAN_RXESC_F1DS,
                      msgRAMConfigParams->rxFIFO1ElemSize);
    }
    /* Configure Rx Buffer Start Address */
    HW_WR_FIELD32(baseAddr + MCAN_RXBC,
                  MCAN_RXBC_RBSA,
                  (msgRAMConfigParams->rxBufStartAddr >> 2U));
    /* Configure Rx Buffer elements size */
    HW_WR_FIELD32(baseAddr + MCAN_RXESC,
                  MCAN_RXESC_RBDS,
                  msgRAMConfigParams->rxBufElemSize);
    /* Configure Tx Event FIFO section */
    if (0U != msgRAMConfigParams->txEventFIFOSize)
    {
        HW_WR_FIELD32((baseAddr) + MCAN_TXEFC,
                      MCAN_TXEFC_EFSA,
                      (msgRAMConfigParams->txEventFIFOStartAddr >> 2U));
        HW_WR_FIELD32((baseAddr) + MCAN_TXEFC,
                      MCAN_TXEFC_EFS,
                      msgRAMConfigParams->txEventFIFOSize);
        HW_WR_FIELD32((baseAddr) + MCAN_TXEFC,
                      MCAN_TXEFC_EFWM,
                      msgRAMConfigParams->txEventFIFOWaterMark);
    }
    /* Configure Tx Buffer and FIFO/Q section */
    elemNum = msgRAMConfigParams->txBufNum + msgRAMConfigParams->txFIFOSize;
    if ((MCAN_TX_MB_MAX_NUM >= elemNum) &&
        ((0U != msgRAMConfigParams->txBufNum) ||
         (0U != msgRAMConfigParams->txFIFOSize)))
    {
        HW_WR_FIELD32(baseAddr + MCAN_TXBC,
                      MCAN_TXBC_TBSA,
                      (msgRAMConfigParams->txStartAddr >> 2U));
        HW_WR_FIELD32(baseAddr + MCAN_TXBC,
                      MCAN_TXBC_NDTB,
                      msgRAMConfigParams->txBufNum);
        HW_WR_FIELD32(baseAddr + MCAN_TXBC,
                      MCAN_TXBC_TFQS,
                      msgRAMConfigParams->txFIFOSize);
        HW_WR_FIELD32(baseAddr + MCAN_TXBC,
                      MCAN_TXBC_TFQM,
                      msgRAMConfigParams->txBufMode);
        /* Configure Tx Buffer/FIFO0/FIFO1 elements size */
        HW_WR_FIELD32(baseAddr + MCAN_TXESC,
                      MCAN_TXESC_TBDS,
                      msgRAMConfigParams->txBufElemSize);
        status = STW_SOK;
    }
    else
    {
        status = STW_EFAIL;
    }

    MCAN_writeProtectedRegAccessLock(baseAddr);

    return status;
}

void MCAN_writeMsgRam(uint32_t                 baseAddr,
                      uint32_t                 memType,
                      uint32_t                 bufNum,
                      const MCAN_TxBufElement *elem)
{
    uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
    uint32_t idx       = 0U;

    if (memType == (uint32_t)MCAN_MEM_TYPE_BUF)
    {
        idx       = bufNum;
    }
    else
    {
        idx       = HW_RD_FIELD32(baseAddr + MCAN_TXFQS, 
                                  MCAN_TXFQS_TFQPI);
    }
        startAddr = HW_RD_FIELD32(baseAddr + MCAN_TXBC,
                                  MCAN_TXBC_TBSA);
        elemSize = HW_RD_FIELD32(baseAddr + MCAN_TXESC,
                             MCAN_TXESC_TBDS);
    startAddr = (uint32_t) (startAddr << 2U);
    elemSize  = MCAN_getMsgObjSize(elemSize);
    elemSize *= 4U;
    elemAddr  = startAddr + (elemSize * idx);
    /* elemAddr += MCAN_MCAN_MSG_MEM; */
    MCAN_writeMsg(baseAddr, elemAddr, elem);
}

int32_t MCAN_txBufAddReq(uint32_t baseAddr, uint32_t bufNum)
{
    int32_t  status;
    uint32_t regVal;
    MCAN_writeProtectedRegAccessUnlock(baseAddr);
    if (MCAN_TX_MB_MAX_NUM > bufNum)
    {
        regVal  = HW_RD_REG32(baseAddr + MCAN_TXBAR);
        regVal |= ((uint32_t) 1U << bufNum);
        HW_WR_REG32(baseAddr + MCAN_TXBAR, regVal);
        
        regVal = HW_RD_REG32(baseAddr + MCAN_TXBAR);
        regVal |= ((uint32_t)1U << bufNum);
        HW_WR_REG32(baseAddr + MCAN_TXBAR, regVal);
        status = STW_SOK;
    }
    else
    {
        status = STW_EFAIL;
    }
    MCAN_writeProtectedRegAccessLock(baseAddr);
    return status;
}

void  MCAN_getNewDataStatus(uint32_t              baseAddr,
                            MCAN_RxNewDataStatus *newDataStatus)
{
    newDataStatus->statusLow  = HW_RD_REG32(baseAddr + MCAN_NDAT1);
    newDataStatus->statusHigh = HW_RD_REG32(baseAddr + MCAN_NDAT2);
}

void  MCAN_clearNewDataStatus(uint32_t                    baseAddr,
                              const MCAN_RxNewDataStatus *newDataStatus)
{
    HW_WR_REG32(baseAddr + MCAN_NDAT1, newDataStatus->statusLow);
    HW_WR_REG32(baseAddr + MCAN_NDAT2, newDataStatus->statusHigh);
}

void MCAN_readMsgRam(uint32_t           baseAddr,
                     uint32_t           memType,
                     uint32_t           bufNum,
                     MCAN_RxBufElement *elem)
{
    uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
    uint32_t idx = 0U;


    if (memType == (uint32_t)MCAN_MEM_TYPE_BUF)
    {
        startAddr = HW_RD_FIELD32(baseAddr + MCAN_RXBC,
                                  MCAN_RXBC_RBSA);
        elemSize = HW_RD_FIELD32(baseAddr + MCAN_RXESC,
                                 MCAN_RXESC_RBDS);
        idx       = bufNum;
    }
    else
    {
        startAddr = HW_RD_FIELD32(baseAddr + MCAN_RXF0C,
                                  MCAN_RXF0C_F0SA);
        elemSize = HW_RD_FIELD32(baseAddr + MCAN_RXESC,
                                 MCAN_RXESC_F0DS);
        idx = HW_RD_FIELD32(baseAddr + MCAN_RXF0S,
                            MCAN_RXF0S_F0GI);
    }
    startAddr = (uint32_t) (startAddr << 2U);
    elemSize  = MCAN_getMsgObjSize(elemSize);
    elemSize *= 4U;
    elemAddr  = startAddr + (elemSize * idx);
    /* elemAddr += MCAN_MCAN_MSG_MEM; */
    MCAN_readMsg(baseAddr, elemAddr, elem);
}

void MCAN_addStdMsgIDFilter(uint32_t                          baseAddr,
                            uint32_t                          filtNum,
                            const MCAN_StdMsgIDFilterElement *elem)
{
    uint32_t startAddr, elemAddr, regVal;

    startAddr = HW_RD_FIELD32(baseAddr + MCAN_SIDFC,
                              MCAN_SIDFC_FLSSA);
    startAddr = (uint32_t) (startAddr << 2U);
    elemAddr  = startAddr + (filtNum * MCANSS_STD_ID_FILTER_SIZE_WORDS * 4U);
    /* elemAddr += MCAN_MCAN_MSG_MEM; */

    regVal  = 0U;
    regVal |= (uint32_t) (elem->sfid2 << MCANSS_STD_ID_FILTER_SFID2_SHIFT);
    regVal |= (uint32_t) (elem->sfid1 << MCANSS_STD_ID_FILTER_SFID1_SHIFT);
    regVal |= (uint32_t) (elem->sfec << MCANSS_STD_ID_FILTER_SFEC_SHIFT);
    regVal |= (uint32_t) (elem->sft << MCANSS_STD_ID_FILTER_SFT_SHIFT);
    HW_WR_REG32(baseAddr + elemAddr, regVal);
}

void MCAN_addExtMsgIDFilter(uint32_t                          baseAddr,
                            uint32_t                          filtNum,
                            const MCAN_ExtMsgIDFilterElement *elem)
{
    uint32_t startAddr, elemAddr, regVal;

    startAddr = HW_RD_FIELD32(baseAddr + MCAN_XIDFC,
                              MCAN_XIDFC_FLESA);
    startAddr = (uint32_t) (startAddr << 2U);
    elemAddr  = startAddr + (filtNum * MCANSS_EXT_ID_FILTER_SIZE_WORDS * 4U);
    /* elemAddr += MCAN_MCAN_MSG_MEM; */

    regVal  = 0U;
    regVal |= (uint32_t) (elem->efid1 << MCANSS_EXT_ID_FILTER_EFID1_SHIFT);
    regVal |= (uint32_t) (elem->efec << MCANSS_EXT_ID_FILTER_EFEC_SHIFT);
    HW_WR_REG32(baseAddr + elemAddr, regVal);

    elemAddr += 4U;
    regVal    = 0U;
    regVal   |= (uint32_t) (elem->efid2 << MCANSS_EXT_ID_FILTER_EFID2_SHIFT);
    regVal   |= (uint32_t) (elem->eft << MCANSS_EXT_ID_FILTER_EFT_SHIFT);
    HW_WR_REG32(baseAddr + elemAddr, regVal);
}

void MCAN_lpbkModeEnable(uint32_t baseAddr,
                         uint32_t lpbkMode,
                         uint32_t enable)
{
    MCAN_writeProtectedRegAccessUnlock(baseAddr);

    if ((uint32_t)TRUE == enable)
    {
        HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_TEST, 0x1U);
        HW_WR_FIELD32(baseAddr + MCAN_TEST,
                      MCAN_TEST_LBCK,
                      enable);
        if (lpbkMode == (uint32_t)MCAN_LPBK_MODE_INTERNAL)
        {
            HW_WR_FIELD32(baseAddr + MCAN_CCCR,
                          MCAN_CCCR_MON,
                          0x1U);
        }
    }
    else
    {
        HW_WR_FIELD32(baseAddr + MCAN_TEST,
                      MCAN_TEST_LBCK,
                      enable);
        HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_TEST, 0x0U);
        if (lpbkMode == (uint32_t)MCAN_LPBK_MODE_INTERNAL)
        {
            HW_WR_FIELD32(baseAddr + MCAN_CCCR,
                          MCAN_CCCR_MON,
                          0x0U);
        }
    }
    MCAN_writeProtectedRegAccessLock(baseAddr);
}

void  MCAN_getProtocolStatus(uint32_t             baseAddr,
                             MCAN_ProtocolStatus *protStatus)
{
    uint32_t regVal;

    regVal = HW_RD_REG32(baseAddr + MCAN_PSR);
    protStatus->lastErrCode   = HW_GET_FIELD(regVal, MCAN_PSR_LEC);
    protStatus->act           = HW_GET_FIELD(regVal, MCAN_PSR_ACT);
    protStatus->errPassive    = HW_GET_FIELD(regVal, MCAN_PSR_EP);
    protStatus->warningStatus = HW_GET_FIELD(regVal, MCAN_PSR_EW);
    protStatus->busOffStatus  = HW_GET_FIELD(regVal, MCAN_PSR_BO);
    protStatus->dlec          = HW_GET_FIELD(regVal, MCAN_PSR_DLEC);
    protStatus->resi          = HW_GET_FIELD(regVal, MCAN_PSR_RESI);
    protStatus->rbrs          = HW_GET_FIELD(regVal, MCAN_PSR_RBRS);
    protStatus->rfdf          = HW_GET_FIELD(regVal, MCAN_PSR_RFDF);
    protStatus->pxe           = HW_GET_FIELD(regVal, MCAN_PSR_PXE);
    protStatus->tdcv          = HW_GET_FIELD(regVal, MCAN_PSR_TDCV);
}

void MCAN_enableIntr(uint32_t baseAddr, uint32_t intrMask, uint32_t enable)
{
    uint32_t regVal;

    if ((uint32_t)TRUE == enable)
    {
        regVal  = HW_RD_REG32(baseAddr + MCAN_IE);
        regVal |= intrMask;
        HW_WR_REG32(baseAddr + MCAN_IE, regVal);
    }
    else
    {
        regVal  = HW_RD_REG32(baseAddr + MCAN_IE);
        regVal &= ~intrMask;
        HW_WR_REG32(baseAddr + MCAN_IE, regVal);
    }
}

void MCAN_selectIntrLine(uint32_t baseAddr,
                         uint32_t intrMask,
                         uint32_t lineNum)
{
    uint32_t regVal;

    if ( lineNum == (uint32_t)MCAN_INTR_LINE_NUM_0)
    {
        regVal  = HW_RD_REG32(baseAddr + MCAN_ILS);
        regVal &= ~intrMask;
        HW_WR_REG32(baseAddr + MCAN_ILS, regVal);
    }
    else
    {
        regVal  = HW_RD_REG32(baseAddr + MCAN_ILS);
        regVal |= intrMask;
        HW_WR_REG32(baseAddr + MCAN_ILS, regVal);
    }
}

void MCAN_enableIntrLine(uint32_t baseAddr,
                         uint32_t lineNum,
                         uint32_t enable)
{
    uint32_t regVal, intrLine;

    intrLine = lineNum;
    intrLine &= MCANSS_INTR_LINE_EN_MASK;
    regVal   = HW_RD_REG32(baseAddr + MCAN_ILE);
    regVal  &= ~((uint32_t) 0x1U << intrLine);
    regVal  |= (uint32_t) (enable << intrLine);
    HW_WR_REG32(baseAddr + MCAN_ILE, regVal);
}

uint32_t MCAN_getIntrStatus(uint32_t baseAddr)
{
    return (HW_RD_REG32(baseAddr + MCAN_IR));
}
void MCAN_clearIntrStatus(uint32_t baseAddr, uint32_t intrMask)
{
    HW_WR_REG32(baseAddr + MCAN_IR, intrMask);
}

void MCAN_getRxFIFOStatus(uint32_t           baseAddr,
                          MCAN_RxFIFOStatus *fifoStatus)
{
    uint32_t regVal;

    regVal = HW_RD_REG32(baseAddr + MCAN_RXF0S);
    fifoStatus->fillLvl  = HW_GET_FIELD(regVal, MCAN_RXF0S_F0FL);
    fifoStatus->getIdx   = HW_GET_FIELD(regVal, MCAN_RXF0S_F0GI);
    fifoStatus->putIdx   = HW_GET_FIELD(regVal, MCAN_RXF0S_F0PI);
    fifoStatus->fifoFull = HW_GET_FIELD(regVal, MCAN_RXF0S_F0F);
    fifoStatus->msgLost  = HW_GET_FIELD(regVal, MCAN_RXF0S_RF0L);
}

int32_t MCAN_writeRxFIFOAck(uint32_t baseAddr, uint32_t idx)
{
    int32_t  status;
    uint32_t size;
    size = HW_RD_FIELD32(baseAddr + MCAN_RXF0C,
                         MCAN_RXF0C_F0S);
    if (size >= idx)
    {
        HW_WR_FIELD32(baseAddr + MCAN_RXF0A,
                      MCAN_RXF0A_F0AI,
                      idx);
        status = STW_SOK;
    }
    else
    {
        status = STW_EFAIL;
    }

    return status;
}

uint32_t MCAN_getTxBufReqPend(uint32_t baseAddr)
{
    return (HW_RD_REG32(baseAddr + MCAN_TXBRP));
}

int32_t MCAN_txBufCancellationReq(
    uint32_t baseAddr, uint32_t buffNum)
{
    int32_t  status;
    uint32_t regVal;

    if (MCAN_TX_MB_MAX_NUM > buffNum)
    {
        regVal  = HW_RD_REG32(baseAddr + MCAN_TXBCR);
        regVal |= ((uint32_t) 1U << buffNum);
        HW_WR_REG32(baseAddr + MCAN_TXBCR, regVal);
        status = STW_SOK;
    }
    else
    {
        status = STW_EFAIL;
    }
    return status;
}

uint32_t MCAN_getTxBufTransmissionStatus(uint32_t baseAddr)
{
    return (HW_RD_REG32(baseAddr + MCAN_TXBTO));
}

uint32_t MCAN_txBufCancellationStatus(uint32_t baseAddr)
{
    return (HW_RD_REG32(baseAddr + MCAN_TXBCF));
}

void MCAN_txBufTransIntrEnable(uint32_t baseAddr, uint32_t bufNum)
{
    uint32_t regVal;

            regVal  = HW_RD_REG32(baseAddr + MCAN_TXBTIE);
            regVal |= ((uint32_t) 1U << bufNum);
            HW_WR_REG32(baseAddr + MCAN_TXBTIE, regVal);

}

void MCAN_addClockStopRequest(uint32_t baseAddr, uint32_t enable)
{
    if ((uint32_t)TRUE == enable)
    {
        HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CSR, 0x1U);
    }
    else
    {
        HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CSR, 0x0U);
    }
}

void MCAN_eccGetErrorStatus(uint32_t           baseAddr,
                            MCAN_ECCErrStatus *eccErr)
{
    baseAddr = (baseAddr&(~MCAN_RAM_OFFSET))>>4;
    eccErr->secErr = HW_RD_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_STATUS_REG0,
                                   MCAN_ECC_AGGR_SEC_STATUS_REG0_MSGMEM_PEND);
    eccErr->dedErr = HW_RD_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_STATUS_REG0,
                                   MCAN_ECC_AGGR_DED_STATUS_REG0_MSGMEM_PEND);
}

void MCAN_eccClearErrorStatus(uint32_t baseAddr, MCAN_ECCErrType errType)
{
    baseAddr = (baseAddr&(~MCAN_RAM_OFFSET))>>4;
    MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_STATUS1);
    if (errType == MCAN_ECC_ERR_TYPE_SEC)
    {
        HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_ERROR_STATUS1,
                      MCAN_ECC_AGGR_ERROR_STATUS1_CLR_ECC_SEC,
                      0x1U);
    }
    else
    {
        HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_ERROR_STATUS1,
                      MCAN_ECC_AGGR_ERROR_STATUS1_CLR_ECC_DED,
                      0x1U);
    }
    MCAN_eccLoadRegister(baseAddr, MCAN_ECC_AGGR_ERROR_STATUS1);
}

void MCAN_eccWriteEOI(uint32_t baseAddr, MCAN_ECCErrType errType)
{
    baseAddr = (baseAddr&(~MCAN_RAM_OFFSET))>>4;
    if (errType == MCAN_ECC_ERR_TYPE_SEC)
    {
        HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_EOI_REG,
                      MCAN_ECC_AGGR_SEC_EOI_REG_WR,
                      0x1U);
    }
    else
    {
        HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_EOI_REG,
                      MCAN_ECC_AGGR_DED_EOI_REG_WR,
                      0x1U);
    }
    HW_WR_FIELD32(baseAddr + MCAN_ECC_EOI,
                  MCAN_ECC_EOI,
                  0x1U);
}

void MCAN_eccEnableIntr(uint32_t baseAddr, MCAN_ECCErrType errType, 
                        uint32_t enable)
{
    baseAddr = (baseAddr&(~MCAN_RAM_OFFSET))>>4;
    if ((uint32_t)TRUE == enable)
    {
        if (errType == MCAN_ECC_ERR_TYPE_SEC)
        {
            HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_ENABLE_SET_REG0,
                          MCAN_ECC_AGGR_SEC_ENABLE_SET_REG0_MSGMEM,
                          0x1U);
        }
        else
        {
            HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_ENABLE_SET_REG0,
                          MCAN_ECC_AGGR_DED_ENABLE_SET_REG0_MSGMEM,
                          0x1U);
        }
    }
    else
    {
        if (errType == MCAN_ECC_ERR_TYPE_SEC)
        {
            HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_SEC_ENABLE_CLR_REG0,
                          MCAN_ECC_AGGR_SEC_ENABLE_CLR_REG0_MSGMEM,
                          0x1U);
        }
        else
        {
            HW_WR_FIELD32(baseAddr + MCAN_ECC_AGGR_DED_ENABLE_CLR_REG0,
                          MCAN_ECC_AGGR_DED_ENABLE_CLR_REG0_MSGMEM,
                          0x1U);
        }
    }
}

/* ========================================================================== */
/*                          Advance Functions                                 */
/* ========================================================================== */

uint32_t MCAN_getClkStopAck(uint32_t baseAddr)
{
    return (HW_RD_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CSA));
}

void MCAN_getBitTime(uint32_t              baseAddr,
                     MCAN_BitTimingParams *configParams)
{
    configParams->nomSynchJumpWidth = HW_RD_FIELD32(baseAddr + MCAN_NBTP,
                                                    MCAN_NBTP_NSJW);
    configParams->nomTimeSeg2 = HW_RD_FIELD32(baseAddr + MCAN_NBTP,
                                              MCAN_NBTP_NTSEG2);
    configParams->nomTimeSeg1 = HW_RD_FIELD32(baseAddr + MCAN_NBTP,
                                              MCAN_NBTP_NTSEG1);
    configParams->nomRatePrescalar = HW_RD_FIELD32(baseAddr + MCAN_NBTP,
                                                   MCAN_NBTP_NBRP);

    configParams->dataSynchJumpWidth = HW_RD_FIELD32(baseAddr + MCAN_DBTP,
                                                     MCAN_DBTP_DSJW);
    configParams->dataTimeSeg2 = HW_RD_FIELD32(baseAddr + MCAN_DBTP,
                                               MCAN_DBTP_DTSEG2);
    configParams->dataTimeSeg1 = HW_RD_FIELD32(baseAddr + MCAN_DBTP,
                                               MCAN_DBTP_DTSEG1);
    configParams->dataRatePrescalar = HW_RD_FIELD32(baseAddr + MCAN_DBTP,
                                                    MCAN_DBTP_DBRP);
}


/* ========================================================================== */
/*                          Internal Functions                                */
/* ========================================================================== */
static void MCAN_writeProtectedRegAccessUnlock(uint32_t baseAddr)
{
    HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CCE, 0x1U);
}
static void MCAN_writeProtectedRegAccessLock(uint32_t baseAddr)
{
    HW_WR_FIELD32(baseAddr + MCAN_CCCR, MCAN_CCCR_CCE, 0x0U);
}

static void MCAN_eccLoadRegister(uint32_t baseAddr, uint32_t regOffSet)
{
    uint32_t regVal = 0U, offset;
    TickType    startCount = 0U, tempCount, elaspsedCount = 0U;
    boolean     timeOut = (boolean)FALSE;

    offset  = regOffSet & 0xFFU;
    regVal |= ((uint32_t)MCANSS_MSG_RAM_NUM << MCAN_ECC_AGGR_VECTOR_SHIFT);
    regVal |= (offset << MCAN_ECC_AGGR_VECTOR_RD_SVBUS_ADDRESS_SHIFT);
    regVal |= ((uint32_t)1U << MCAN_ECC_AGGR_VECTOR_RD_SVBUS_SHIFT);
    HW_WR_REG32(baseAddr + MCAN_ECC_AGGR_VECTOR, regVal);

    (void)GetCounterValue(CAN_CFG_OS_COUNTER_ID, &startCount);    
    {
        /* Below API can change start time, so use temp variable */
        tempCount = startCount;
        /* Wait for register from register bank to load into front register */
        do
        {
            (void)GetElapsedValue(
                         CAN_CFG_OS_COUNTER_ID,
                         &tempCount,
                         &elaspsedCount);
            if (elaspsedCount >= (uint32_t)CAN_CFG_TIMEOUT_DURATION)
            {
                /* timeout */
                timeOut = (boolean)TRUE;
                break;
            }
        } while (MCAN_ECC_AGGR_VECTOR_RD_SVBUS_DONE_MASK !=
           (HW_RD_REG32(baseAddr + MCAN_ECC_AGGR_VECTOR) &
            MCAN_ECC_AGGR_VECTOR_RD_SVBUS_DONE_MASK));
    }
    if (timeOut == (boolean)TRUE)
    {
      (void)Dem_SetEventStatus(
            CAN_E_HARDWARE_ERROR, DEM_EVENT_STATUS_FAILED);
    }
}

static void MCAN_readMsg(uint32_t           baseAddr,
                         uint32_t           elemAddr,
                         MCAN_RxBufElement *elem)
{
    uint32_t regVal = 0U, loopCnt = 0U, addrOffset;

    addrOffset = elemAddr;
    regVal   = HW_RD_REG32(baseAddr + addrOffset);
    elem->id = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_ID_MASK)
                           >> MCANSS_RX_BUFFER_ELEM_ID_SHIFT);
    elem->rtr = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_RTR_MASK)
                            >> MCANSS_RX_BUFFER_ELEM_RTR_SHIFT);
    elem->xtd = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_XTD_MASK)
                            >> MCANSS_RX_BUFFER_ELEM_XTD_SHIFT);
    elem->esi = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_ESI_MASK)
                            >> MCANSS_RX_BUFFER_ELEM_ESI_SHIFT);

    addrOffset  += 4U;
    regVal     = HW_RD_REG32(baseAddr + addrOffset);
    elem->rxts = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_RXTS_MASK)
                             >> MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT);
    elem->data_length = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_DLC_MASK)
                            >> MCANSS_RX_BUFFER_ELEM_DLC_SHIFT);
    elem->brs = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_BRS_MASK)
                            >> MCANSS_RX_BUFFER_ELEM_BRS_SHIFT);
    elem->fdf = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_FDF_MASK)
                            >> MCANSS_RX_BUFFER_ELEM_FDF_SHIFT);
    elem->fidx = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_FIDX_MASK)
                             >> MCANSS_RX_BUFFER_ELEM_FIDX_SHIFT);
    elem->anmf = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_ANMF_MASK)
                             >> MCANSS_RX_BUFFER_ELEM_ANMF_SHIFT);
    addrOffset += 4U;

    loopCnt = 0U;
    /* Reading words from message RAM and forming payload bytes out of it */
    while ((4U <= (MCAN_getDataSize(elem->data_length) - loopCnt)) &&
           (0U != (MCAN_getDataSize(elem->data_length) - loopCnt)))
    {
        regVal = HW_RD_REG32(baseAddr + addrOffset);
        elem->data[loopCnt]       = (uint8_t)(regVal & 0x000000FFU);
        elem->data[(loopCnt + 1U)] = (uint8_t)((regVal & 0x0000FF00U) >> 8U);
        elem->data[(loopCnt + 2U)] = (uint8_t)((regVal & 0x00FF0000U) >> 16U);
        elem->data[(loopCnt + 3U)] = (uint8_t)((regVal & 0xFF000000U) >> 24U);
        addrOffset += 4U;
        loopCnt  += 4U;
    }
    /* Reading remaining bytes from message RAM */
    if (0U < (MCAN_getDataSize(elem->data_length) - loopCnt))
    {
        regVal = HW_RD_REG32(baseAddr + addrOffset);
        elem->data[loopCnt]       = (uint8_t)(regVal & 0x000000FFU);
        elem->data[(loopCnt + 1U)] = (uint8_t)((regVal & 0x0000FF00U) >> 8U);
        elem->data[(loopCnt + 2U)] = (uint8_t)((regVal & 0x00FF0000U) >> 16U);
    }
}
static void MCAN_writeMsg(uint32_t                 baseAddr,
                          uint32_t                 elemAddr,
                          const MCAN_TxBufElement *elem)
{
    uint32_t regVal = 0U, loopCnt = 0U, addrOffset;

    addrOffset = elemAddr;
    regVal  = 0U;
    regVal |= (((uint32_t) (elem->id << MCANSS_TX_BUFFER_ELEM_ID_SHIFT)) |
               ((uint32_t) (elem->rtr << MCANSS_TX_BUFFER_ELEM_RTR_SHIFT)) |
               ((uint32_t) (elem->xtd << MCANSS_TX_BUFFER_ELEM_XTD_SHIFT)) |
               ((uint32_t) (elem->esi << MCANSS_TX_BUFFER_ELEM_ESI_SHIFT)));
    HW_WR_REG32(baseAddr + addrOffset, regVal);
    addrOffset += 4U;

    regVal  = 0U;
    regVal |= 
           ((uint32_t) (elem->data_length << MCANSS_TX_BUFFER_ELEM_DLC_SHIFT)) |
           ((uint32_t) (elem->brs << MCANSS_TX_BUFFER_ELEM_BRS_SHIFT)) |
           ((uint32_t) (elem->fdf << MCANSS_TX_BUFFER_ELEM_FDF_SHIFT)) |
           ((uint32_t) (elem->efc << MCANSS_TX_BUFFER_ELEM_EFC_SHIFT)) |
           ((uint32_t) (elem->mm << MCANSS_TX_BUFFER_ELEM_MM_SHIFT));
HW_WR_REG32(baseAddr + addrOffset, regVal);
    addrOffset += 4U;

    loopCnt = 0U;
    /* Framing words out of the payload bytes and writing it to message RAM */
    while ((4U <= (MCAN_getDataSize(elem->data_length) - loopCnt)) &&
           (0U != (MCAN_getDataSize(elem->data_length) - loopCnt)))
    {
        regVal  = 0U;
        regVal |= ((uint32_t)elem->data[loopCnt] |
                   ((uint32_t)elem->data[(loopCnt + 1U)] << 8U) |
                   ((uint32_t)elem->data[(loopCnt + 2U)] << 16U) |
                   ((uint32_t)elem->data[(loopCnt + 3U)] << 24U));
        HW_WR_REG32(baseAddr + addrOffset, regVal);
        addrOffset += 4U;
        loopCnt  += 4U;
    }
    /* Framing a word out of remaining payload bytes and writing it to
     * message RAM */
    if (0U < (MCAN_getDataSize(elem->data_length) - loopCnt))
    {
        regVal  = 0U;
        regVal |= ((uint32_t)elem->data[loopCnt] |
                   ((uint32_t)elem->data[(loopCnt + 1U)] << 8U) |
                   ((uint32_t)elem->data[(loopCnt + 2U)] << 16U) |
                   ((uint32_t)elem->data[(loopCnt + 3U)] << 24U));
        HW_WR_REG32(baseAddr + addrOffset, regVal);
    }
}

static uint32_t MCAN_getDataSize(uint32_t data_length)
{
    uint32_t dataSize[16] = {0U,  1U,  2U,  3U,  4U,  5U,  6U, 7U, 8U,
                             12U, 16U, 20U, 24U, 32U, 48U, 64U};

    return (dataSize[data_length]);
}

static uint32_t MCAN_getMsgObjSize(uint32_t elemSize)
{
    uint32_t objSize[8] = {4U, 5U, 6U, 7U, 8U, 10U, 14U, 18U};

    return (objSize[elemSize]);
}


int32_t MCAN_setExtIDAndMask(uint32_t baseAddr, uint32_t idMask)
{
  int32_t status;

  if (MCAN_XIDAM_EIDM_MAX >= idMask)
  {
    MCAN_writeProtectedRegAccessUnlock(baseAddr);

    HW_WR_FIELD32((baseAddr) + MCAN_XIDAM,
      MCAN_XIDAM_EIDM,
      idMask);

    MCAN_writeProtectedRegAccessLock(baseAddr);
    status = STW_SOK;
  }
  else
  {
    status = STW_EFAIL;
  }
  return status;
}


/* Memory mapping, done via MemMap.h: Code */
#define CAN_STOP_SEC_CODE
#include "Can_MemMap.h"