This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

TMS320F28388D: Interrupt on receive is triggered only the first time

Part Number: TMS320F28388D

Tool/software:

raw 133 - mcan.c
raw 1438 - application.c

#include "f28x_project.h"
#include "application.h"
#include "board.h"
#include "device.h"
#include "mcan.h"


TestDescriptor testDescriptor;


int main(void)
{
    Device_init();
    //
    // Allocate MCAN (a shared peripheral) to CPU1 (C28x)
    //
    SysCtl_allocateSharedPeripheral();
    //
    // Configure the divisor for the MCAN bit-clock
    //
    //SysCtl_setMCANClk();


    //
    // Board peripheral/module configuration
    //
    Board_init();

    XINT1_enable();
    MCANIntrsEnable(true);
    //
    // Initialize message to transmit and receive.
    //
    MCAN_TxDataFrame_init(&testDescriptor.txMsg[0], 4);
    MCAN_RxDataFrameInit(testDescriptor.rxMsg);
    //
    // Write Tx Message to the Message RAM.
    //
    MCAN_writeMsgRam(MCAN_MEM_TYPE_BUF, 1U, &testDescriptor.txMsg[0]);
    //
    // 4-Enable Transmission interrupt.
    //
    //MCAN_txBufTransIntrEnable(1U,1U);

#if LOOPBACK_MODE
    //
    // Add request for transmission.
    //
    MCAN_txBufAddReq(1U);

    while(testDescriptor.isrIntr1Flag)
    {
    }

        //
           // Read Message RAM.
           //
           MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 0U, MCAN_RX_FIFO_NUM_1,
                           &testDescriptor.rxMsg[0]);

           //
           // Get the New Data Status.
           //
           MCAN_getNewDataStatus(&testDescriptor.newData);

           //
           // Check that received data matches sent data.
           // Device will halt here during debug if data doesn't match.
           //
           if((testDescriptor.txMsg[0].data[0] != testDescriptor.rxMsg[0].data[0]) ||
              (testDescriptor.txMsg[0].data[1] != testDescriptor.rxMsg[0].data[1]) ||
              (testDescriptor.txMsg[0].data[2] != testDescriptor.rxMsg[0].data[2]) ||
              (testDescriptor.txMsg[0].data[3] != testDescriptor.rxMsg[0].data[3]))
           {
               //
               // Device will halt here if transmitted and received data are
               // not same.
               //
               ESTOP0;
           }
           else
           {
               //
               // Increment message count if message is received.
               //
               testDescriptor.msgCount++;
           }
#endif

       while(1)
       {

#if CLASSIC_TRANSMIT
            if (testDescriptor.enable)
            {
                testDescriptor.enable = false;

                // Add request for all transmission.
                //
                MCAN_txBufAddReq(1U);

                //
                // Wait till all the messages are transmitted.
                //
                while(MCAN_getTxBufReqPend() == 0)
                {
                }
                testDescriptor.msgCount++;
            }
#endif
            // Turn on LED
            //
            GPIO_WritePin(99, 0);

            //
            // Delay for a bit.
            //
            DELAY_US(500000);

            //
            // Turn off LED
            //
            GPIO_WritePin(99, 1);

            //
            // Delay for a bit.
            //
            DELAY_US(500000);

       }
}
/***************************mcan.c*************************************/


#include <stdint.h>
#include <stdbool.h>
#include <string.h>
#include "mcan.h"
#include "mcan_defines.h"
#include "mcanss.h"
#include "hardware.h"
#include "application.h"






void MCAN_init_config()
{
    int i;
    MCAN_RevisionId revId;
    MCAN_InitParams initParams;
    MCAN_ConfigParams configParams;
    MCAN_MsgRAMConfigParams    msgRAMConfigParams;
    MCAN_StdMsgIDFilterElement stdFiltelem[MCAN_STD_ID_FILTER_NUM];
    MCAN_BitTimingParams       bitTimes;

    //
    //  Initializing all structs to zero to prevent stray values
    //
    memset(&initParams, 0, sizeof(initParams));
    memset(&configParams, 0, sizeof(configParams));
    memset(&msgRAMConfigParams, 0, sizeof(msgRAMConfigParams));
    memset(&stdFiltelem, 0, sizeof(stdFiltelem));
    memset(&bitTimes, 0, sizeof(bitTimes));

    //
    // Initialize MCAN Init parameters.
    //

    initParams.fdMode            = 0x0U;    // FD operation enabled - disabled
    initParams.brsEnable         = 0x0U;    // Bit rate switching for - disabled
                                            // transmissions enabled.
    initParams.txpEnable         = 0x0U;    // Transmit pause disabled.
    initParams.efbi              = 0x0U;    // Edge filtering disabled.
    initParams.pxhddisable       = 0x0U;    // Protocol exception handling enabled
    initParams.darEnable         = 0x0U;    // Enable Automatic retransmission of
                                            // messages not transmitted successfully
    initParams.wkupReqEnable     = 0x1U;    // Wakeup request is enabled.
    initParams.autoWkupEnable    = 0x1U;    // Auto-Wakeup is enabled.
    initParams.debugSuspendEnable= 0x1U;    // Emulation/Debug Suspend is enabled.
    initParams.tdcEnable         = 0x1U;    // Transmitter Delay Compensation is
                                            // enabled.
    initParams.wdcPreload        = 0xFFU;   // Start value of the Message RAM
                                            // Watchdog Counter preload.

    //
    // Transmitter Delay Compensation parameters.
    //
    initParams.tdcConfig.tdcf    = 0xAU;
    initParams.tdcConfig.tdco    = 0x6U;

    //
    // Initialize MCAN Config parameters.
    //
    configParams.monEnable         = 0x0U;          // Bus Monitoring Mode is disabled
    configParams.asmEnable         = 0x0U;          // Normal CAN operation.
    configParams.tsPrescalar       = 0xFU;          // Prescaler Value.
    configParams.tsSelect          = 0x0U;          // Timestamp counter value.
    configParams.timeoutSelect     = MCAN_TIMEOUT_SELECT_CONT;
    // Time-out counter source select.
    configParams.timeoutPreload    = 0xFFFFU;       // Start value of the Timeout
                                                    // Counter.
    configParams.timeoutCntEnable  = 0x0U;          // Time-out Counter is disabled.
    configParams.filterConfig.rrfs = 0x1U;          // Reject all remote frames with
                                                    // 29-bit extended IDs.
    configParams.filterConfig.rrfe = 0x1U;          // Reject all remote frames with
                                                    // 11-bit standard IDs.
    configParams.filterConfig.anfe = 0x1U;          // Accept in Rx FIFO 1.
    configParams.filterConfig.anfs = 0x1U;          // Accept in Rx FIFO 1.

    //
    // Initialize Message RAM Sections Configuration Parameters.
    //
    msgRAMConfigParams.flssa                = MCAN_STD_ID_FILT_START_ADDR;
    // Standard ID Filter List Start Address.
    msgRAMConfigParams.lss                  = MCAN_STD_ID_FILTER_NUM;
    // List Size: Standard ID.
    msgRAMConfigParams.flesa                = MCAN_EXT_ID_FILT_START_ADDR;
    // Extended ID Filter List Start Address.
    msgRAMConfigParams.lse                  = MCAN_EXT_ID_FILTER_NUM;
    // List Size: Extended ID.
    msgRAMConfigParams.txStartAddr          = MCAN_TX_BUFF_START_ADDR;
    // Tx Buffers Start Address.
    msgRAMConfigParams.txBufNum             = MCAN_TX_BUFF_SIZE;
    // Number of Dedicated Transmit Buffers.
    msgRAMConfigParams.txFIFOSize           = 0U; // No Tx FIFO/Queue.
    msgRAMConfigParams.txBufMode            = 0U; //Tx FIFO operation
    msgRAMConfigParams.txBufElemSize        = MCAN_TX_BUFF_ELEM_SIZE;
    // Tx Buffer Element Size.
    msgRAMConfigParams.txEventFIFOStartAddr = MCAN_TX_EVENT_START_ADDR;
    // Tx Event FIFO Start Address.
    msgRAMConfigParams.txEventFIFOSize      = MCAN_TX_BUFF_SIZE;
    // Event FIFO Size.
    msgRAMConfigParams.txEventFIFOWaterMark = 5U;
    // Level for Tx Event FIFO watermark interrupt.
    msgRAMConfigParams.rxFIFO0startAddr     = MCAN_FIFO_0_START_ADDR;
    // Rx FIFO0 Start Address.
    msgRAMConfigParams.rxFIFO0size          = MCAN_FIFO_0_NUM;
    // Number of Rx FIFO elements.
    msgRAMConfigParams.rxFIFO0waterMark     = 5U; // Rx FIFO0 Watermark.
    msgRAMConfigParams.rxFIFO0OpMode        = 0U; // FIFO blocking mode.
    msgRAMConfigParams.rxFIFO1startAddr     = MCAN_FIFO_1_START_ADDR;
    // Rx FIFO1 Start Address.
    msgRAMConfigParams.rxFIFO1size          = MCAN_FIFO_1_NUM;
    // Number of Rx FIFO elements.
    msgRAMConfigParams.rxFIFO1waterMark     = 5U; // Level for Rx FIFO 1
                                                 // watermark interrupt.
    msgRAMConfigParams.rxFIFO1OpMode        = 0U; // FIFO blocking mode.
    msgRAMConfigParams.rxBufStartAddr       = MCAN_RX_BUFF_START_ADDR;
    // Rx Buffer Start Address.
    msgRAMConfigParams.rxBufElemSize        = MCAN_RX_BUFF_ELEM_SIZE;
    // Rx Buffer Element Size.
    msgRAMConfigParams.rxFIFO0ElemSize      = MCAN_FIFO_0_ELEM_SIZE;
    // Rx FIFO0 Element Size.
    msgRAMConfigParams.rxFIFO1ElemSize      = MCAN_FIFO_1_ELEM_SIZE;
    // Rx FIFO1 Element Size.


    //Standard ID filters initialize
    //Configure Standard ID filter element 0
    MCAN_StdIDFilterConfiguration(&stdFiltelem[0], 0, 4, 7, 0 );
    //Configure Standard ID filter element 1
    MCAN_StdIDFilterConfiguration(&stdFiltelem[1], 1, 5, 7, 0 );
    //Configure Standard ID filter element 2
    MCAN_StdIDFilterConfiguration(&stdFiltelem[2], 2, 6, 7, 0 );
    //Configure Standard ID filter element 3
    MCAN_StdIDFilterConfiguration(&stdFiltelem[3], 3, 7, 7, 0 );


    //
    // Initialize bit timings - source clock 10 MHz
    //
    bitTimes.nomRatePrescalar   = 0x0U;     // Nominal Baud Rate Pre-scaler.
    bitTimes.nomTimeSeg1        = 0x9U;     // Nominal Time segment before SP
    bitTimes.nomTimeSeg2        = 0x8U;     // Nominal Time segment after SP
    bitTimes.nomSynchJumpWidth  = 0x8U;     // Nominal SJW

    bitTimes.dataRatePrescalar  = 0x1U;     // Data Baud Rate Pre-scaler.
    bitTimes.dataTimeSeg1       = 0x9U;     // Data Time segment before SP
    bitTimes.dataTimeSeg2       = 0x8U;     // Data Time segment after SP
    bitTimes.dataSynchJumpWidth = 0x8U;     // Data SJW

    //
    // Get MCANSS Revision ID.
    //
    MCAN_getRevisionId(&revId);

    //
    // Wait for Memory initialization to be completed.
    //
    while(false == MCAN_isMemInitDone());

    //
    // Put MCAN in SW initialization mode.
    //
    MCAN_setOpMode(MCAN_OPERATION_MODE_SW_INIT);

    //
    // Wait till MCAN is not initialized.
    //
    while (MCAN_OPERATION_MODE_SW_INIT != McanaRegs.MCAN_CCCR.bit.INIT);

    //
    // Initialize MCAN module.
    //
    MCAN_init(&initParams);

    //
    // Configure MCAN module.
    //
    MCAN_config(&configParams);

    //
    // Configure Bit timings.
    //
    MCAN_setBitTime(&bitTimes);

    //
    // Configure Message RAM Sections
    //
    MCAN_msgRAMConfig(&msgRAMConfigParams);

    //
    // Configure Standard ID filter element
    //
#if !EXT_ID_FILTER
    for (i = 0; i<MCAN_STD_ID_FILTER_NUM; i++)
    MCAN_addStdMsgIDFilter(i, &stdFiltelem[i]);

#else
    //
    // Configure Extended ID filter element
    //
    MCAN_addExtMsgIDFilter(0U, &extFiltelem);

    //
    // Set Extended ID Mask for acceptance filtering of received frames
    // (Mask disabled when all bits are set to 1)
    //
    MCAN_setExtIDAndMask(MCAN_EXT_ID_AND_MASK);
#endif

#if LOOPBACK_MODE
    //
    // Enable internal/external loopback mode
    //
    MCAN_lpbkModeEnable(MCAN_LPBK_MODE_EXTERNAL, true);
#endif
    //
    // Take MCAN out of the SW initialization mode
    //
    MCAN_setOpMode(MCAN_OPERATION_MODE_NORMAL);

    while (MCAN_OPERATION_MODE_NORMAL != McanaRegs.MCAN_CCCR.bit.INIT);
}

/**
 * \brief   This API is used get the MCAN revision ID.
 *
 *
 * \param   revId           Contains Revision ID of MCAN module.
 *                          Refer struct #MCAN_RevisionId.
 *
 * \return  None.
 */
static void MCAN_getRevisionId(MCAN_RevisionId *revId)
{
        revId->minor  = McanaSsRegs.MCANSS_PID.bit.MINOR;       //Minor Revision of the MCAN Subsystem
        revId->major  = McanaSsRegs.MCANSS_PID.bit.MAJOR;       //Major Revision of the MCAN Subsystem
        revId->modId  = McanaSsRegs.MCANSS_PID.bit.MODULE_ID;   //Module Identification Number
        revId->scheme = McanaSsRegs.MCANSS_PID.bit.SCHEME;      //PID Register Scheme

        revId->day     = McanaRegs.MCAN_CREL.bit.DAY;           //Time Stamp Day. Two digits, BCD-coded
        revId->mon     = McanaRegs.MCAN_CREL.bit.MON;           //Time Stamp Month. Two digits, BCD-coded
        revId->year    = McanaRegs.MCAN_CREL.bit.YEAR;          //Time Stamp Year. One digit, BCD-coded
        revId->subStep = McanaRegs.MCAN_CREL.bit.SUBSTEP;       //Sub-Step of Core Release. One digit, BCD-coded
        revId->step    = McanaRegs.MCAN_CREL.bit.STEP;          //Step of Core Release. One digit, BCD-coded
        revId->rel     = McanaRegs.MCAN_CREL.bit.REL;           //Core Release. One digit, BCD-coded
}
/**
 * \brief   This function checks if the memory initialization is done for
 *          MCAN module.
 *
 *
 *
 * \retval  state           Returns TRUE if memory initialization is done.
 *                          Else returns FALSE.*/

static bool MCAN_isMemInitDone()
{
    uint32_t memInit;
    bool state = false;

    memInit = McanaSsRegs.MCANSS_STAT.bit.MEM_INIT_DONE;

    if(1U == memInit)
    {
        state = true;
    }
    return state;
}
/**
 * \brief   This API will set MCAN module mode of operation.
 *
 *
 * \param   mode            Mode of operation.
 *                          Refer enum #MCAN_OperationMode.
 *
 * \return  None.
 */
static void MCAN_setOpMode(uint32_t mode)
{
    McanaRegs.MCAN_CCCR.bit.INIT = mode;
}
/**
 * \brief   This API will initialize MCAN module.
 *
 * \param   initParams      Initialization parameters.
 *                          Refer struct #MCAN_InitParams.
 *
 * \return  status          Initialization status.
 */
static bool MCAN_init(const MCAN_InitParams *initParams)
{
    bool  status;

    /* Configure MCAN wakeup and clock stop controls */
    McanaSsRegs.MCANSS_CTRL.bit.WAKEUPREQEN = initParams->wkupReqEnable;
    McanaSsRegs.MCANSS_CTRL.bit.AUTOWAKEUP = initParams->autoWkupEnable;
    McanaSsRegs.MCANSS_CTRL.bit.DBGSUSP_FREE = initParams->debugSuspendEnable;

    McanaRegs.MCAN_CCCR.bit.CCE = 1;
    /*Configuration Change Enable 0 The CPU has no write
    registers
    1 The CPU has write acc
    hile CCCR.INIT = '1'
    */

    /* Configure MCAN mode(FD vs Classic CAN operation) and controls */
    McanaRegs.MCAN_CCCR.bit.FDOE = initParams->fdMode;
    McanaRegs.MCAN_CCCR.bit.BRSE = initParams->brsEnable;
    McanaRegs.MCAN_CCCR.bit.TXP = initParams->txpEnable;
    McanaRegs.MCAN_CCCR.bit.EFBI = initParams->efbi;
    McanaRegs.MCAN_CCCR.bit.PXHD = initParams->pxhddisable;
    McanaRegs.MCAN_CCCR.bit.DAR = initParams->darEnable;

    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 */
        McanaRegs.MCAN_TDCR.bit.TDCF = initParams->tdcConfig.tdcf;
        McanaRegs.MCAN_TDCR.bit.TDCO = initParams->tdcConfig.tdco;
        /* Configure MSG RAM watchdog counter preload value */
        McanaRegs.MCAN_RWD.bit.WDC = initParams->wdcPreload;
        /* Enable/Disable Transceiver Delay Compensation */
        McanaRegs.MCAN_DBTP.bit.TDC = initParams->tdcEnable;

        status = true;
    }
    else
    {
        status = false;
    }

    McanaRegs.MCAN_CCCR.bit.CCE = 0;

    return status;
}
/**
 * \brief   This API will configure MCAN module.
 *
 * \param   configParams    configuration parameters.
 *                          Refer struct #MCAN_ConfigParams.
 *
 * \return  status          Configuration status.
 */
static bool MCAN_config(const MCAN_ConfigParams *configParams)
{
    bool status;

    McanaRegs.MCAN_CCCR.bit.CCE = 1;

    /* Configure MCAN control registers */
    McanaRegs.MCAN_CCCR.bit.MON = configParams->monEnable;
    McanaRegs.MCAN_CCCR.bit.ASM = configParams->asmEnable;
    /* Configure Global Filter */
    McanaRegs.MCAN_GFC.bit.RRFE = configParams->filterConfig.rrfe;
    McanaRegs.MCAN_GFC.bit.RRFS = configParams->filterConfig.rrfs;
    McanaRegs.MCAN_GFC.bit.ANFE = configParams->filterConfig.anfe;
    McanaRegs.MCAN_GFC.bit.ANFS = configParams->filterConfig.anfs;

    if((MCAN_TSCC_TCP_MAX >= configParams->tsPrescalar) &&
        (MCAN_TOCC_TOP_MAX >= configParams->timeoutPreload))
    {
        /* Configure Time-stamp counter */
        McanaRegs.MCAN_TSCC.bit.TSS = configParams->tsSelect;
        McanaRegs.MCAN_TSCC.bit.TCP = (configParams->tsPrescalar - 1U);
        /* Configure Time-out counter */
        McanaRegs.MCAN_TOCC.bit.TOS = configParams->timeoutSelect;
        McanaRegs.MCAN_TOCC.bit.TOP = configParams->timeoutPreload;
        /* Enable Time-out counter */
        McanaRegs.MCAN_TOCC.bit.ETOC = configParams->timeoutCntEnable;
        status = true;
    }
    else
    {
        status = false;
    }

    McanaRegs.MCAN_CCCR.bit.CCE = 0;

    return status;
}
/**
 * \brief   This API will configure a bit timings for MCAN module.
 *
 * \param   configParams    Configuration parameters for MCAN bit timing.
 *                          Refer struct #MCAN_BitTimingParams.
 *
 * \return  status          Bit Timings configuration status.
 */
static bool MCAN_setBitTime(const MCAN_BitTimingParams *configParams)
{
    bool status;

    McanaRegs.MCAN_CCCR.bit.CCE = 1;

    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))
    {
        McanaRegs.MCAN_NBTP.bit.NSJW = configParams->nomSynchJumpWidth;
        McanaRegs.MCAN_NBTP.bit.NTSEG2 = configParams->nomTimeSeg2;
        McanaRegs.MCAN_NBTP.bit.NTSEG1 = configParams->nomTimeSeg1;
        McanaRegs.MCAN_NBTP.bit.NBRP = configParams->nomRatePrescalar;

        status = true;
    }
    else
    {
        status = false;
    }
    if(true == 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))
        {
            McanaRegs.MCAN_DBTP.bit.DSJW = configParams->dataSynchJumpWidth;
            McanaRegs.MCAN_DBTP.bit.DTSEG2 = configParams->dataTimeSeg2;
            McanaRegs.MCAN_DBTP.bit.DTSEG1 = configParams->dataTimeSeg1;
            McanaRegs.MCAN_DBTP.bit.DBRP =  configParams->dataRatePrescalar;


            status = true;
        }
        else
        {
            status = false;
        }
    }

    McanaRegs.MCAN_CCCR.bit.CCE = 0;
    return status;
}
/**
 * \brief   This API will configure Different sections of Message RAM.
 *
 * \param   msgRAMConfigParams
 *                          Message RAM Configuration parameters.
 *                          Refer struct #MCAN_MsgRAMConfigParams.
 *
 * \return  status          Configuration Status.
 */
static bool MCAN_msgRAMConfig(const MCAN_MsgRAMConfigParams *msgRAMConfigParams)
{
    bool  status;
    uint32_t elemNum = 0U;

    McanaRegs.MCAN_CCCR.bit.CCE = 1;

    /* Configure Message Filters section */
    if(0U != msgRAMConfigParams->lss)
    {
        McanaRegs.MCAN_SIDFC.bit.FLSSA = (msgRAMConfigParams->flssa >> 2U);
        McanaRegs.MCAN_SIDFC.bit.LSS =    msgRAMConfigParams->lss;
    }
    if(0U != msgRAMConfigParams->lse)
    {
        McanaRegs.MCAN_XIDFC.bit.FLESA = (msgRAMConfigParams->flesa >> 2U);
        McanaRegs.MCAN_XIDFC.bit.LSE =    msgRAMConfigParams->lse;
    }
    /* Configure Rx FIFO 0 section */
    if(0U != msgRAMConfigParams->rxFIFO0size)
    {
        McanaRegs.MCAN_RXF0C.bit.F0SA = (msgRAMConfigParams->rxFIFO0startAddr >> 2U);
        McanaRegs.MCAN_RXF0C.bit.F0S =   msgRAMConfigParams->rxFIFO0size;
        McanaRegs.MCAN_RXF0C.bit.F0WM =  msgRAMConfigParams->rxFIFO0waterMark;
        McanaRegs.MCAN_RXF0C.bit.F0OM =  msgRAMConfigParams->rxFIFO0OpMode;
        /* Configure Rx FIFO0 elements size */
        McanaRegs.MCAN_RXESC.bit.F0DS =  msgRAMConfigParams->rxFIFO0ElemSize;
    }
    /* Configure Rx FIFO 1 section */
    if(0U != msgRAMConfigParams->rxFIFO1size)
    {
        McanaRegs.MCAN_RXF1C.bit.F1SA = (msgRAMConfigParams->rxFIFO1startAddr >> 2U);
        McanaRegs.MCAN_RXF1C.bit.F1S =   msgRAMConfigParams->rxFIFO1size;
        McanaRegs.MCAN_RXF1C.bit.F1WM =  msgRAMConfigParams->rxFIFO1waterMark;
        McanaRegs.MCAN_RXF1C.bit.F1OM =  msgRAMConfigParams->rxFIFO1OpMode;
        /* Configure Rx FIFO0 elements size */
        McanaRegs.MCAN_RXESC.bit.F1DS =  msgRAMConfigParams->rxFIFO1ElemSize;
    }

    /* Configure Rx Buffer Start Address */
    McanaRegs.MCAN_RXBC.bit.RBSA = (msgRAMConfigParams->rxBufStartAddr >> 2U);
    /* Configure Rx Buffer elements size */
    McanaRegs.MCAN_RXESC.bit.RBDS = msgRAMConfigParams->rxBufElemSize;
    /* Configure Tx Event FIFO section */
    if(0U != msgRAMConfigParams->txEventFIFOSize)
    {
        McanaRegs.MCAN_TXEFC.bit.EFSA = (msgRAMConfigParams->txEventFIFOStartAddr >> 2U);
        McanaRegs.MCAN_TXEFC.bit.EFS =   msgRAMConfigParams->txEventFIFOSize;
        McanaRegs.MCAN_TXEFC.bit.EFWM =  msgRAMConfigParams->txEventFIFOWaterMark;
    }
    /* Configure Tx Buffer and FIFO/Q section */
    elemNum = msgRAMConfigParams->txBufNum + msgRAMConfigParams->txFIFOSize;
    if((MCANSS_TX_BUFFER_MAX >= elemNum) &&
        ((0U != msgRAMConfigParams->txBufNum) ||
         (0U != msgRAMConfigParams->txFIFOSize)))
    {
        McanaRegs.MCAN_TXBC.bit.TBSA =  (msgRAMConfigParams->txStartAddr >> 2U);
        McanaRegs.MCAN_TXBC.bit.NDTB =   msgRAMConfigParams->txBufNum;
        McanaRegs.MCAN_TXBC.bit.TFQS =   msgRAMConfigParams->txFIFOSize;
        McanaRegs.MCAN_TXBC.bit.TFQM =   msgRAMConfigParams->txBufMode;

        /* Configure Tx Buffer/FIFO0/FIFO1 elements size */
        McanaRegs.MCAN_TXESC.bit.TBDS =   msgRAMConfigParams->txBufElemSize;

        status = true;
    }
    else
    {
        status = false;
    }

    McanaRegs.MCAN_CCCR.bit.CCE = 0;

    return status;
}
/**
 * \brief   This API is used to add Standard Message ID Filter Element.
 *
 * \param   filtNum         Filter number.
 * \param   elem            Filter Object.
 *                          Refer struct #MCAN_StdMsgIDFilterElement.
 *
 * \return  None.
 */
#if !EXT_ID_FILTER
static void MCAN_addStdMsgIDFilter(uint32_t filtNum, const MCAN_StdMsgIDFilterElement *elem)
{
    uint32_t startAddr, elemAddr, regVal, newAddr;

    startAddr = McanaRegs.MCAN_SIDFC.bit.FLSSA;

    startAddr = (uint32_t) (startAddr << 2U);
    elemAddr  = startAddr + (filtNum * MCANSS_STD_ID_FILTER_SIZE_WORDS * 4U);
    elemAddr += MCAN_STD_ID_FILT_START_ADDR;

    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);

    newAddr = MCANA_MSG_RAM_BASE + elemAddr;

    HW_WR_REG32(newAddr, regVal);
}
#endif
/**
 * \brief   This API will enable/disable Loop Back Test Mode for
 *          MCAN module.
 *
 * \param   lpbkMode        Loopback mode for MCAN.
 *                          Refer #enum MCAN_LpbkMode.
 * \param   enable          Loop Back Mode is enabled if it is TRUE.
 *                          Loop Back Mode is disabled  if it is FALSE.
 *
 * \return  None.
 * \note    This API can be called only when MCAN is in Software
 *          Initialization mode of operation.
 */
static void MCAN_lpbkModeEnable(uint32_t lpbkMode,uint32_t enable)
{
    McanaRegs.MCAN_CCCR.bit.CCE = 1;

    if(true == enable)
    {
        McanaRegs.MCAN_CCCR.bit.TEST = 1;
        McanaRegs.MCAN_TEST.bit.LBCK = enable;

        if((uint32_t)MCAN_LPBK_MODE_INTERNAL == lpbkMode)
        {
            McanaRegs.MCAN_CCCR.bit.MON = 1;
        }
    }
    else
    {
        McanaRegs.MCAN_TEST.bit.LBCK = enable;
        McanaRegs.MCAN_CCCR.bit.TEST = 0;

        if((uint32_t)MCAN_LPBK_MODE_INTERNAL == lpbkMode)
        {
            McanaRegs.MCAN_CCCR.bit.MON = 0;
        }
    }
    McanaRegs.MCAN_CCCR.bit.CCE = 0;
}
/**
 * \brief   This API is used to write Tx message to message RAM.
 *
 * \param   memType         Part of message ram to which given message to write.
 *                          Refer enum #MCAN_MemType.
 * \param   bufNum          Buffer  number where message to write.
 *                          This parameter will ignored if memType is FIFO/Q.
 * \param   elem            Message Object.
 *                          Refer struct #MCAN_TxBufElement.
 *
 * \return  None.
 */
void MCAN_writeMsgRam(uint32_t memType, uint32_t bufNum, const MCAN_TxBufElement *elem)
{
    uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
    uint32_t idx       = 0U, enableMod = 0U;

    if((uint32_t)MCAN_MEM_TYPE_BUF == memType)
    {
        idx       = bufNum;
        enableMod = 1U;
    }
    if((uint32_t)MCAN_MEM_TYPE_FIFO == memType)
    {
        idx       = McanaRegs.MCAN_TXFQS.bit.TFQP;
    /*
    * Tx FIFO/Queue Put Index. Tx FIFO/Queue write index pointer, range
    0 to 31.
    Note: In case of mixed configurations where dedicated Tx Buffers are
    combined with a Tx FIFO or a Tx Queue, the Put and Get Indices
    indicate the number of the Tx Buffer starting with the first dedicated
    Tx Buffers. Example: For a configuration of 12 dedicated Tx Buffers
    and a Tx FIFO of 20 Buffers a Put Index of 15 points to the fourth
    buffer of the Tx FIFO.
         * */
        enableMod = 1U;
    }
    if(1U == enableMod)
    {
        startAddr = McanaRegs.MCAN_TXBC.bit.TBSA;

        elemSize = McanaRegs.MCAN_TXESC.bit.TBDS;

        startAddr = (uint32_t) (startAddr << 2U);
        elemSize  = MCAN_getMsgObjSize(elemSize);
        elemSize *= 4U;
        elemAddr  = startAddr + (elemSize * idx);
        elemAddr += MCAN_MCAN_MSG_MEM;
        MCAN_writeMsg(elemAddr, elem);
    }
}
/**
 * \brief   This API will write the message object to Message RAM.
 *
 * \param   elemAddr        Address of the message object.
 * \param   elem            Message Object.
 *                          Refer struct #MCAN_TxBufElement.
 *
 * \return  None.
 */
static void MCAN_writeMsg(uint32_t elemAddr, const MCAN_TxBufElement *elem)
{
    uint32_t regVal = 0, loopCnt = 0U;

    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(MCANA_MSG_RAM_BASE+elemAddr, regVal);
    elemAddr += 4U;

    regVal  = 0U;
    regVal |= ((uint32_t) (elem->dlc << 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(MCANA_MSG_RAM_BASE+elemAddr, regVal);
    elemAddr += 4U;

    loopCnt = 0U;
    /* Framing words out of the payload bytes and writing it to message RAM */
    while((4U <= (MCAN_getDataSize(elem->dlc) - loopCnt)) &&
           (0U != (MCAN_getDataSize(elem->dlc) - loopCnt)))
    {
        ASSERT((loopCnt + 3U) < MCAN_MAX_PAYLOAD_BYTES);
        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(MCANA_MSG_RAM_BASE+elemAddr, regVal);
        elemAddr += 4U;
        loopCnt  += 4U;
    }
    /* Framing a word out of remaining payload bytes and writing it to
     * message RAM */
    if(0U < (MCAN_getDataSize(elem->dlc) - loopCnt))
    {
        ASSERT((loopCnt + 3U) < MCAN_MAX_PAYLOAD_BYTES);
        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(MCANA_MSG_RAM_BASE+elemAddr, regVal);
    }
}

static uint32_t MCAN_getDataSize(uint32_t dlc)
{
    uint32_t dataSize[16] = {0,  1,  2,  3,  4,  5,  6, 7, 8,
                             12, 16, 20, 24, 32, 48, 64};
    ASSERT(dlc < 16U);
    return(dataSize[dlc]);
}
/**
 * \brief   This API will return Tx Buffer Request Pending status.
 *
 *
 * \return  status          Tx Buffer Request Pending status.
 */
#if 0
bool MCAN_getTxBufReqPend()
{
    bool bufStatus = false;
    int i;
    uint32_t regValue = McanaRegs.MCAN_TXBRP.all;

    for (i = 0; i < 32; i++)
    {
        bufStatus |= (regValue & (1 << i));
    }

    return bufStatus;
}
#endif
/**
 * \brief   This API is used to enable/disable interrupts.
 *
 * \param   intrMask        Interrupts to enable.
 *                          Refer enum #MCAN_IntrSrc.
 * \param   enable          Interrupt is enabled if it is TRUE.
 *                          Interrupt is disabled  if it is FALSE.
 * MCAN Interrupt Enable
 * \return  None.
 */
void MCAN_enableIntr(uint32_t intrMask, uint32_t enable)
{
    uint32_t regVal;

    if(true == enable)
    {
        regVal  = McanaRegs.MCAN_IE.all;
        regVal |= intrMask;
        McanaRegs.MCAN_IE.all = regVal;
    }
    else
    {
        regVal  = McanaRegs.MCAN_IE.all;
        regVal &= ~intrMask;
        McanaRegs.MCAN_IE.all = regVal;
    }
}
/**
 * \brief   This API is used to select interrupt line.
 *
 * \param   intrMask        Interrupt Number for which interrupt
 *                          line is to be selected. Refer enum #MCAN_IntrSrc.
 * \param   lineNum         Interrupt Line to select.
 *                          Refer enum #MCAN_IntrLineNum,
 * MCAN Interrupt Line Select
 * \return  None.
 */
void MCAN_selectIntrLine(uint32_t intrMask, uint32_t lineNum)
{
    uint32_t regVal;

    if((uint32_t)MCAN_INTR_LINE_NUM_0 == lineNum)
    {
        regVal  = McanaRegs.MCAN_ILS.all;
        regVal &= ~intrMask;
        McanaRegs.MCAN_ILS.all = regVal;
    }
    else
    {
        regVal  = McanaRegs.MCAN_ILS.all;
        regVal |= intrMask;
        McanaRegs.MCAN_ILS.all = regVal;
    }
}
/**
 * \brief   This API is used to enable/disable selected interrupt line.
 *
 * \param   lineNum         Interrupt Line to select.
 *                          Refer enum #MCAN_IntrLineNum,
 * \param   enable          Interrupt Line is enabled if it is 1.
 *                          Interrupt Line is disabled  if it is 0.
 *  MCAN Interrupt Line Enable EINT0, EINT1
 * \return  None.
 */
void MCAN_enableIntrLine(uint32_t lineNum, uint32_t enable)
{
    uint32_t regVal;

    lineNum &= MCANSS_INTR_LINE_EN_MASK;
    regVal   = McanaRegs.MCAN_ILE.all;
    regVal  &= ~((uint32_t) 0x1U << lineNum);
    regVal  |= (uint32_t) (enable << lineNum);
    McanaRegs.MCAN_ILE.all = regVal;
}
/**
 * \brief   This API is used to enable/disable Tx Buffer Transmission Interrupt.
 *
 * \param   bufNum          Buffer number for which interrupt is to enable.
 * \param   enable          Interrupt is enabled if it is TRUE.
 *                          Interrupt is disabled  if it is FALSE.
 *  MCAN Tx Buffer Transmission Interrupt Enable
 * \return  status          Configuration status.
 */
bool MCAN_txBufTransIntrEnable(uint32_t bufNum, uint32_t enable)
{
    bool  status = false;
    uint32_t regVal;

    if(MCANSS_TX_BUFFER_MAX > bufNum)
    {
        if(true == enable)
        {
           regVal  = McanaRegs.MCAN_TXBTIE.all;
           regVal |= ((uint32_t) 1U << bufNum);
           McanaRegs.MCAN_TXBTIE.all = regVal;
        }
        else
        {
           regVal  = McanaRegs.MCAN_TXBTIE.all;
           regVal &= ~((uint32_t) 0x1U << bufNum);
           McanaRegs.MCAN_TXBTIE.all = regVal;
        }
        status = true;
    }
    return status;
}
/**
 * \brief   This API will set Tx Buffer Add Request.
 *
 * \param   bufNum          Tx Buffer number for which request is to be added.
 *
 *  MCAN Tx Buffer Add Request
 * \return  status          Configuration Status.
 */
bool MCAN_txBufAddReq(uint32_t bufNum)
{
    bool  status = false;
    uint32_t regVal;

    if(MCANSS_TX_BUFFER_MAX > bufNum)
    {
        regVal  = McanaRegs.MCAN_TXBAR.all;
        regVal |= ((uint32_t) 1U << bufNum);

        // For writing to TXBAR CCE bit should be '0'. This need not be
        // reverted because for other qualified writes this is locked state
        // and can't be written.
        //McanaRegs.MCAN_CCCR.bit.CCE = 0;
        McanaRegs.MCAN_TXBAR.all = regVal;

        status = true;
    }
    return status;
}
/**
 * \brief   This API is used to read received message form message RAM.
 *
 * \param   memType         Part of message ram to which given message to write.
 *                          Refer enum #MCAN_MemType.
 * \param   bufNum          Buffer  number from where message is to read.
 *                          This parameter will ignored if memType is FIFO/Q.
 *  \param  fifoNum         FIFOs number from where message is to read.
 *                          Refer enum #MCAN_RxFIFONum.
 *                          This parameter will ignored if memType is buffer.
 * \param   elem            Message Object.
 *                          Refer struct #MCAN_RxBufElement.
 *
 * \return  None.
 */
void MCAN_readMsgRam(uint32_t memType, uint32_t bufNum, uint32_t fifoNum, MCAN_RxBufElement *elem)
{
    uint32_t startAddr = 0U, elemSize = 0U, elemAddr = 0U;
       uint32_t enableMod = 0U, idx = 0U;

       if((uint32_t)MCAN_MEM_TYPE_BUF == memType)
       {
           startAddr = McanaRegs.MCAN_RXBC.bit.RBSA;
            /*Rx Buffer Start Address. Configures the start address of the Rx
            Buffers section in the Message RAM (32-bit word address).
            */
           elemSize = McanaRegs.MCAN_RXESC.bit.RBDS;
            /*
            * Rx Buffer Data Field Size
            000 8 byte data field
            001 12 byte data field
            010 16 byte data field
            011 20 byte data field
            100 24 byte data field
            101 32 byte data field
            110 48 byte data field
            111 64 byte data field
            Note: In case the data field size of an accepted CAN frame exceeds
            the data field size configured for the matching Rx Buffer or Rx FIFO,
            only the number of bytes as configured by RXESC are stored to the
            Rx Buffer resp. Rx FIFO element. The rest of the frame's data field is
            ignored.
            Qualified Write is possible only with CCCR.CCE='1' and
            CCCR.INIT='1'.
            */
           idx       = bufNum;
           enableMod = 1U;
       }
       if((uint32_t)MCAN_MEM_TYPE_FIFO == memType)
       {
           switch (fifoNum)
           {
               case MCAN_RX_FIFO_NUM_0:
                    startAddr = McanaRegs.MCAN_RXF0C.bit.F0SA;
                    /*Rx FIFO 0 Start Address. Start address of Rx FIFO 0 in Message
                    RAM (32-bit word address).
                    Qualified Write is possible only with CCCR.CCE='1' and
                    CCCR.INIT='1'.
                    */

                    elemSize = McanaRegs.MCAN_RXESC.bit.F0DS;
                    /*
                    * Rx FIFO 0 Data Field Size
                    000 8 byte data field
                    001 12 byte data field
                    010 16 byte data field
                    011 20 byte data field
                    100 24 byte data field
                    101 32 byte data field
                    110 48 byte data field
                    111 64 byte data field
                    Note: In case the data field size of an accepted CAN frame exceeds
                    the data field size configured for the matching Rx Buffer or Rx FIFO,
                    only the number of bytes as configured by RXESC are stored to the
                    Rx Buffer resp. Rx FIFO element. The rest of the frame's data field is
                    ignored.
                    Qualified Write is possible only with CCCR.CCE='1' and
                    CCCR.INIT='1'.
                    */
                    idx = McanaRegs.MCAN_RXF0S.bit.F0GI; //Rx FIFO 0 Get Index. Rx FIFO 0 read index pointer, range 0 to 63.
                    enableMod = 1U;
                    break;
               case MCAN_RX_FIFO_NUM_1:
                    startAddr = McanaRegs.MCAN_RXF1C.bit.F1SA;
                    /*Rx FIFO 0 Start Address. Start address of Rx FIFO 0 in Message
                    RAM (32-bit word address).
                    Qualified Write is possible only with CCCR.CCE='1' and
                    CCCR.INIT='1'.
                    */

                    elemSize = McanaRegs.MCAN_RXESC.bit.F1DS;
                    /*
                    * Rx FIFO 0 Data Field Size
                    000 8 byte data field
                    001 12 byte data field
                    010 16 byte data field
                    011 20 byte data field
                    100 24 byte data field
                    101 32 byte data field
                    110 48 byte data field
                    111 64 byte data field
                    Note: In case the data field size of an accepted CAN frame exceeds
                    the data field size configured for the matching Rx Buffer or Rx FIFO,
                    only the number of bytes as configured by RXESC are stored to the
                    Rx Buffer resp. Rx FIFO element. The rest of the frame's data field is
                    ignored.
                    Qualified Write is possible only with CCCR.CCE='1' and
                    CCCR.INIT='1'.
                    */
                    idx = McanaRegs.MCAN_RXF1S.bit.F1GI; //Rx FIFO 0 Get Index. Rx FIFO 0 read index pointer, range 0 to 63.
                    enableMod = 1U;
                   break;
               default:
                   /* Invalid option */
                   break;
           }
       }
       if(1U == enableMod)
       {
           startAddr = (uint32_t) (startAddr << 2U);
           elemSize  = MCAN_getMsgObjSize(elemSize);
           elemSize *= 4U;
           elemAddr  = startAddr + (elemSize * idx);
           elemAddr += MCAN_MCAN_MSG_MEM;
           MCAN_readMsg(elemAddr, elem);
       }
}
static void MCAN_readMsg(uint32_t elemAddr,MCAN_RxBufElement *elem)
{
    uint32_t regVal = 0U, loopCnt = 0U;

    regVal   = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
    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);

    elemAddr  += 4U;
    regVal     = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
    elem->rxts = (uint32_t) ((regVal & MCANSS_RX_BUFFER_ELEM_RXTS_MASK)
                             >> MCANSS_RX_BUFFER_ELEM_RXTS_SHIFT);
    elem->dlc = (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);
    elemAddr += 4U;

    loopCnt = 0U;
    /* Reading words from message RAM and forming payload bytes out of it */
    while((4U <= (MCAN_getDataSize(elem->dlc) - loopCnt)) &&
           (0U != (MCAN_getDataSize(elem->dlc) - loopCnt)))
    {
        ASSERT((loopCnt + 3U) < MCAN_MAX_PAYLOAD_BYTES);
        regVal = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
        elem->data[loopCnt]       = (uint16_t)(regVal & 0x000000FFU);
        elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U);
        elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U);
        elem->data[(loopCnt + 3U)] = (uint16_t)((regVal & 0xFF000000U) >> 24U);
        elemAddr += 4U;
        loopCnt  += 4U;
    }
    /* Reading remaining bytes from message RAM */
    if(0U < (MCAN_getDataSize(elem->dlc) - loopCnt))
    {
        ASSERT((loopCnt + 2U) < MCAN_MAX_PAYLOAD_BYTES);
        regVal = HW_RD_REG32(MCANA_MSG_RAM_BASE + elemAddr);
        elem->data[loopCnt]       = (uint16_t)(regVal & 0x000000FFU);
        elem->data[(loopCnt + 1U)] = (uint16_t)((regVal & 0x0000FF00U) >> 8U);
        elem->data[(loopCnt + 2U)] = (uint16_t)((regVal & 0x00FF0000U) >> 16U);
    }
}
/**
 * \brief   This API will return New Data Message Status.
 *
 * \param   newDataStatus   Rx Buffer new data status.
 *                          Refer struct #MCAN_RxNewDataStatus.
 *
 * \return  None.
 */
void  MCAN_getNewDataStatus(MCAN_RxNewDataStatus *newDataStatus)
{
    newDataStatus->statusLow  = McanaRegs.MCAN_NDAT1.all;
    newDataStatus->statusHigh = McanaRegs.MCAN_NDAT2.all;
}
/**
 * \brief   This API is used to add Extended Message ID Filter Element.
 *
 * \param   filtNum         Filter  number.
 * \param   elem            Filter Object.
 *                          Refer struct #MCAN_ExtMsgIDFilterElement.
 *
 * \return  None.
 */

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

       startAddr = McanaRegs.MCAN_XIDFC.bit.FLESA; //Filter List Extended Start Address.
       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(MCANA_MSG_RAM_BASE + 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(MCANA_MSG_RAM_BASE + elemAddr, regVal);
}
/**
 * \brief   This API will configure Extended ID AND Mask.
 *
 * \param   idMask          Configuration parameters for MCAN Extended Id mask.
 *                          This value is 29 bit wide.
 *
 * \return  status          Extended ID AND Mask configuration status.
 */

static bool MCAN_setExtIDAndMask(uint32_t idMask)
{
    bool status;

    if(MCAN_XIDAM_EIDM_MAX >= idMask)
    {
        McanaRegs.MCAN_CCCR.bit.CCE = 1;

        McanaRegs.MCAN_XIDAM.bit.EIDM = idMask;
        /*
        * Extended ID Mask. For acceptance filtering of extended frames the
        Extended ID AND Mask is ANDed with the Message ID of a received
        frame. Intended for masking of 29-bit IDs in SAE J1939. With the
        reset value of all bits set to one the mask is not active.
        Qualified Write is possible only with CCCR.CCE='1' and
        CCCR.INIT='1'.
        */

        McanaRegs.MCAN_CCCR.bit.CCE = 0;
        status = true;
    }
    else
    {
        status = false;
    }
    return status;
}
#endif
/**
 * \brief   This API will return interrupt status.
 *
 *
 * \return  status          Interrupt Status.
 */
uint32_t MCAN_getIntrStatus()
{
    return( McanaRegs.MCAN_IR.all);
}
/**
 * \brief   This API is used to clear the interrupt status.
 *
 * \param   intrMask        Interrupts to clear status.
 *
 * \return  None.
 */
void MCAN_clearIntrStatus(uint32_t intrMask)
{
    McanaRegs.MCAN_IR.all = intrMask;
}
/**
 * \brief   This API will write Rx FIFO Acknowledgement.
 *
 *                          Refer enum #MCAN_RxFIFONum.
 * \param   fifoNum         FIFO Number.
 * \param   idx             Rx FIFO Acknowledge Index
 *
 * \return  status          Acknowledgement Status.
 */
bool MCAN_writeRxFIFOAck(uint32_t fifoNum, uint32_t idx)
{
    bool  status = false;
    uint32_t size;

    switch (fifoNum)
    {
        case MCAN_RX_FIFO_NUM_0:
            size = McanaRegs.MCAN_RXF0C.bit.F0S;
            if(size >= idx)
            {
                McanaRegs.MCAN_RXF0A.bit.F0AI = idx;
                status = true;
            }
            break;
        case MCAN_RX_FIFO_NUM_1:
            size = McanaRegs.MCAN_RXF1C.bit.F1S;
            if(size >= idx)
            {
                McanaRegs.MCAN_RXF1A.bit.F1AI = idx;
                status = true;
            }
            break;
        default:
            break;
    }

    return status;
}
/**
 * \brief   This API is used to get interrupt line selected for each interrupt.
 *
 *
 * \return  status          Interrupt Line Select Status.
 */
uint32_t MCAN_getIntrLineSelectStatus()
{
    return(McanaRegs.MCAN_ILS.all);
}
#if 1
/**
 * \brief   This API will return Tx Buffer Request Pending status.
 *
 *
 * \return  None
 */
uint32_t MCAN_getTxBufReqPend()
{
    return(McanaRegs.MCAN_TXBRP.all);
}
#endif
/**
 * \brief   This API will return Tx Buffer Transmission Occurred status.
 *
 *
 * \return  status          Tx Buffer Transmission Occurred status.
 */
uint32_t MCAN_getTxBufTransmissionStatus()
{
    return(McanaRegs.MCAN_TXBTO.all);
}
/**
 * \brief   This API will be used for configuring the std filter's fields.
 *
 *
 * \return  status          Tx Buffer Transmission Occurred status.
 */
static void MCAN_StdIDFilterConfiguration(MCAN_StdMsgIDFilterElement *stdFiltelem,
                                        uint32_t sfid2,
                                        uint32_t sfid1,
                                        uint32_t sfec,
                                        uint32_t sft)
{
    //
      // Initialize Rx Buffer Configuration parameters.
      //
      stdFiltelem->sfid2              = sfid2;  // Standard Filter ID 2.
      /*
      SFID2[10:0]
      Standard Filter ID 2
      This bit field has a different meaning depending on the configuration of
      SFEC:
      • SFEC = 001 - 110: Second ID of standard ID filter element
      • SFEC = 111: Filter for Rx buffers
      SFID2[10:9]
      This filed is decides whether the received message is stored into an Rx
      Buffer or treated as message A, B, or C of the debug message sequence.
      • 0x0: Store message into an Rx Buffer
      • 0x1: Debug Message A
      • 0x2: Debug Message B
      • 0x3: Debug Message C
      Note: Debug feature is not supported.
      SFID2[8:6]
      This field is used to control the filter event pins at the Extension Interface.
      A one at the respective bit position enables generation of a pulse at the
      related filter event pin with the duration of one MCAN_ICKL period in case
      the filter matches.
      Note: Only two filter event pins are supported.
      SFID2[5:0] This field defines the offset to the Rx Buffer Start Address
      MCAN_RXBC.RBSA field for storage of a matching message
      */
      stdFiltelem->sfid1              = sfid1;  // Standard Filter ID 1.-------DISABLE
      /*
      When filtering for Rx buffers this field defines the ID of a standard message
      to be stored. The received identifiers must match exactly, no masking
      mechanism is used.
      */
      stdFiltelem->sfec               = sfec;  // Store into Rx Buffer
      /*
      * All enabled filter elements are used for acceptance filtering of standard
      frames. Acceptance filtering stops at the first matching enabled filter
      element or when the end of the filter list is reached. If SFEC = 100, 101, or
      110 match sets interrupt flag MCAN_IR.HPM and, if enabled, an interrupt
      is generated. In this case, the MCAN_HPMS register is updated with the
      status of the priority match.
      • 0x0: Disable filter element
      • 0x1: Store in Rx FIFO 0 if filter matches
      • 0x2: Store in Rx FIFO 1 if filter matches
      • 0x3: Reject ID if filter matches
      • 0x4: Set priority if filter matches
      • 0x5: Set priority and store in FIFO 0 if filter matches
      • 0x6: Set priority and store in FIFO 1 if filter matches
      • 0x7: Store into Rx Buffer , configuration of SFT[1:0] ignored
      */
      stdFiltelem->sft                = sft;  // Range filter from SFID1 to SFID2
      /*
      * Standard Filter Type
      • 0x0: Range filter from SFID1 to SFID2 (SFID2 ≥ SFID1)
      • 0x1: Dual ID filter for SFID1 or SFID2
      • 0x2: Classic filter: SFID1 = filter; SFID2 = mask
      • 0x3: Filter element disabled
      */
}
/**
 * \brief   This API clear New Data Message Status.
 *
 * \param   newDataStatus
 *                          Rx Buffer new data status.
 *                          Refer struct #MCAN_RxNewDataStatus.

 * \return  None.
 */
void  MCAN_clearNewDataStatus(const MCAN_RxNewDataStatus *newDataStatus)
{
    McanaRegs.MCAN_NDAT1.all =newDataStatus->statusLow;
    McanaRegs.MCAN_NDAT2.all =newDataStatus->statusHigh;
}
/*************************application.c********************/
/*
 * application.c
 *
 *  Created on: 16 gen 2025
 *      Author: d.marsili
 */
#include "application.h"
#include "mcan.h"
#include "mcan_defines.h"
#include "f2838x_examples.h"


void MCAN_TxDataFrame_init(MCAN_TxBufElement *mess, uint16_t identifier)
{
    testDescriptor.isrIntr1Flag = 1;
    int i;
    mess->id       = ((uint32_t)(identifier))<< 18U ; // ID value
    mess->rtr      = 0U;                       // Transmit data frame.
    mess->xtd      = 0U;                       // 11-bit standard identifier.
    mess->esi      = 0U;
    mess->dlc      = 4U;                       // Payload length 4 byte
    mess->brs      = 0U;                       // CAN FD frames transmitted with bit rate switching
    mess->fdf      = 0U;                       // Frame transmitted in CAN FD format.
    mess->efc      = 0U;                       // No-Store Tx events.
    mess->mm       = 0xAAU;                    // Message Marker.
    mess->data[0]  = 0x1;
    for(i = 1; i < mess->dlc; i++)
    {
        mess->data[i]  = mess->data[i-1] + 1;
    }
}
void MCAN_RxDataFrameInit(MCAN_RxBufElement *rxMsg)
{
    int i,j;
    for(i = 0; i < NUM_OF_MSG; i++)
        {
          //
          // Initialize message to receive
          //
          rxMsg[i].id = 0U;
          rxMsg[i].rtr = 0U;
          rxMsg[i].xtd = 0U;
          rxMsg[i].esi = 0U;
          rxMsg[i].rxts = 0U;   // Rx Timestamp
          rxMsg[i].dlc = 0U;
          rxMsg[i].brs = 0U;
          rxMsg[i].fdf = 0U;
          rxMsg[i].fidx = 0U;   // Filter Index
                                      // (of matching Rx acceptance filter element)
          rxMsg[i].anmf = 0U;   // Accepted Non-matching Frame

          for(j = 0; j < RX_MSG_PAYLOAD_MAX_LENGTH; j++)  // Initialize receive buffer to 0
          {
              rxMsg[i].data[j]  = 0;
          }
        }
}
/***************************************************************************/
/********************** Interrupts set-up's functions***********************/
/***************************************************************************/
//MCAN interrupts configuration
void MCANIntrConfig()
{
    MCAN_ISRHandler();
    //
    // Enable PIE interrupt
    //
    PieCtrlRegs.PIEIER9.bit.INTx9 = 1; //MCANSS_INT0
    PieCtrlRegs.PIEIER9.bit.INTx10 = 1; //MCANSS_INT1
}
static void MCAN_ISRHandler()
{
    EALLOW;
    PieVectTable.MCANA_0_INT = &MCANIntr0ISR; //function for MCAN interrupt 0
    PieVectTable.MCANA_1_INT = &MCANIntr1ISR; //function for MCAN interrupt 1
    EDIS;
}

//XINT1 interrupt configuration
void XINT1IntrConfig()
{
    XINT1_ISRHandler();
    //
    // Enable PIE interrupt
    //
    PieCtrlRegs.PIEIER1.bit.INTx4 = 1;          //Enable PIE Group 1 INT4- XINT1
}
static void XINT1_ISRHandler()
{
    EALLOW;
    PieVectTable.XINT1_INT = &xint1_ISR; //function for XINT1 interrupt
    EDIS;
}
/***************************************************************************/
/********************** Interrupts enable's functions***********************/
/***************************************************************************/
//MCAN interrupts enable
void MCANIntrsEnable(bool enable)
{
    if (enable)
    {
        //
        // 1-Enable Interrupts.
        //
        MCAN_enableIntr(MCAN_IR_DRX_MASK, 1U);
        //
        // 2-Enable Interrupt Line.
        //
        MCAN_selectIntrLine(MCAN_IR_DRX_MASK, MCAN_INTR_LINE_NUM_0);
        //
        // 3-Enable Interrupt Line.
        //
        MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_0, 1U);
        //
        // 1-Enable Interrupts.
        //
        MCAN_enableIntr(MCAN_IR_BO_MASK, 1U);
        //
        // 2-Enable Interrupt Line.
        //
        MCAN_selectIntrLine(MCAN_IR_BO_MASK, MCAN_INTR_LINE_NUM_1);
        //
        // 3-Enable Interrupt Line.
        //
        MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_1, 1U);
    }
    else
    {
        //
        // 1-Enable Interrupts.
        //
        MCAN_enableIntr(MCAN_IR_DRX_MASK, 0U);
        //
        // 2-Enable Interrupt Line.
        //
        MCAN_selectIntrLine(MCAN_IR_DRX_MASK, MCAN_INTR_LINE_NUM_0);
        //
        // 3-Enable Interrupt Line.
        //
        MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_0, 0U);
        //
        // 1-Enable Interrupts.
        //
        MCAN_enableIntr(MCAN_IR_BO_MASK, 0U);
        //
        // 2-Enable Interrupt Line.
        //
        MCAN_selectIntrLine(MCAN_IR_BO_MASK, MCAN_INTR_LINE_NUM_1);
        //
        // 3-Enable Interrupt Line.
        //
        MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_1, 0U);
    }
}

void XINT1_enable()
{

    //
    // GPIO88 is mapped to XINT1
    //
    GPIO_SetupXINT1Gpio(62);
    //
    // Configure XINT1
    //
    XintRegs.XINT1CR.bit.POLARITY = 0;          // Falling edge interrupt
    XintRegs.XINT1CR.bit.ENABLE = 1;            // Enable XINT1
}
/***************************************************************************/
/********************** Interrupts Service Routine**************************/
/***************************************************************************/
//
// xint1ISR - External Interrupt 1 ISR
//
interrupt void xint1_ISR(void)
{
    testDescriptor.enable = true;
    //
    // Acknowledge this interrupt to get more from group 1
    //
    PieCtrlRegs.PIEACK.all = 1;
}
//
// This is Interrupt Service Routine for MCAN interrupt 0.
//
__interrupt void MCANIntr0ISR(void)
{
    uint32_t intrStatus = MCAN_getIntrStatus();
#if LOOPBACK_MODE
    if (0x81200 != intrStatus) //0x81200 - Transmission completed/ Tx FIFO event new entry/ Message Stored in RX buff
    {
    testDescriptor.error++;
    }

    //
    // Clear the interrupt Status.
    //
    MCAN_clearIntrStatus(intrStatus);

    //
    // Update the flag value.
    //
    testDescriptor.isrIntr1Flag = 1U;
    //
    // Acknowledge this interrupt located in group 9
    //
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
#else
    MCAN_RxNewDataStatus newData;
    /*
    EALLOW;
    McanaSsRegs.MCANSS_EOI.bit.EOI = 2;
    EDIS;
    */
    /* End of Interrupt. A write to this register will clear the associated
    interrupt. If the unserviced interrupt counter is > 1, another interrupt
    is generated.
    0x00 External TS Interrupt is cleared
    0x01 MCAN[0] interrupt is cleared
    0x02 MCAN[1] interrupt is cleared
    Other writes are ignored.
    */

    //
    // Clear the interrupt Status.
    //
    MCAN_clearIntrStatus(intrStatus);
    //
    //  Check to see if the interrupt is caused by a message being
    //  received in dedicated RX Buffers
    //
    if((MCAN_IR_DRX_MASK & intrStatus) == MCAN_IR_DRX_MASK)
    {
    //
    // Read the NewData registers
    //
    MCAN_getNewDataStatus(&newData);

    //  If message is received in buffer element 0
    if((newData.statusLow & (1UL << 0U)) != 0)
    {
    MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 0U,
    0, &testDescriptor.rxMsg[0]);
    }
    //  If message is received in buffer element 1
    if((newData.statusLow & (1UL << 1U)) != 0)
    {
    MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 1U,
    0, &testDescriptor.rxMsg[1]);
    }
    if((newData.statusLow & (1UL << 2U)) != 0)
    {
    MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 2U,
    0, &testDescriptor.rxMsg[2]);
    }
    if((newData.statusLow & (1UL << 3U)) != 0)
    {
    MCAN_readMsgRam(MCAN_MEM_TYPE_BUF, 3U,
    0, &testDescriptor.rxMsg[3]);
    }
    //
    //  Clearing the NewData registers
    //
    MCAN_clearNewDataStatus(&newData);
    }
    else
    {
    testDescriptor.error++;
    //
    //  Interrupt handling for other interrupt sources goes here
    //
    }

    //
    // Acknowledge this interrupt located in group 9
    //
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
#endif
}
//
// This is Interrupt Service Routine for MCAN interrupt 1.
//
__interrupt void MCANIntr1ISR(void)
{
    uint32_t intrStatus = MCAN_getIntrStatus();
    /*
    EALLOW;
    McanaSsRegs.MCANSS_EOI.bit.EOI = 2;
    EDIS;
    */
    //
    // Clear the interrupt Status.
    //
    MCAN_clearIntrStatus(intrStatus);
    McanaRegs.MCAN_CCCR.bit.CCE = 1;
    McanaRegs.MCAN_CCCR.bit.INIT = MCAN_OPERATION_MODE_NORMAL;
    McanaRegs.MCAN_CCCR.bit.CCE = 0;

    testDescriptor.error++;
    //
    // Acknowledge this interrupt located in group 9
    //
    PieCtrlRegs.PIEACK.bit.ACK9 = 1;
    //McanaErrRegs.MCANERR_SEC_EOI.bit.EOI_WR = 1;
}

#if 0
static CommunicationStatus CheckMCANCommunicationStatus()
{
    uint32_t intrStatus = MCAN_getIntrStatus();
    uint32_t receptionCompl = (intrStatus >> 0 & 1);
    CommunicationStatus event = OTHERS;
    receptionCompl = receptionCompl || (intrStatus >> 4 & 1);
    receptionCompl = receptionCompl|| (intrStatus >> 19 & 1);
    if (intrStatus >> 9 & 1)
            event =TRASMISSION_COMPLETED;
    else if(intrStatus >> 19 & 1)
            event = RECECPTION_COMPLETED;
    else if (intrStatus >> 24 & 1)
            event = BUS_OFF_STATUS;

    return event;
}
#endif

Hi experts, I absolutely need your help, I'm in trouble.

This example follows the principle behind the example mcan_ex10_receive_multiple_buffers.
The interrupt is triggered the first time and allows me to read the received texture correctly. After that, it doesn't go off again. Is there any register in addition to those inserted to reset or are there other aspects that I overlook?

For more information please ask.

  • Hi Davide,

    Which interrupt from your code are you specifically having issues with? Can you show the specific ISR definition that is only getting triggered once?

    Best Regards,

    Delaney

  • Hi,

    //MCAN interrupts configuration
    void MCANIntrConfig()
    {
        MCAN_ISRHandler();
        //
        // Enable PIE interrupt
        //
        PieCtrlRegs.PIEIER9.bit.INTx9 = 1; //MCANSS_INT0
        PieCtrlRegs.PIEIER9.bit.INTx10 = 1; //MCANSS_INT1
    }
    static void MCAN_ISRHandler()
    {
        EALLOW;
        PieVectTable.MCANA_0_INT = &MCANIntr0ISR; //function for MCAN interrupt 0
        PieVectTable.MCANA_1_INT = &MCANIntr1ISR; //function for MCAN interrupt 1
        EDIS;
    }
     //
            // 1-Enable Interrupts.
            //
            MCAN_enableIntr(MCAN_IR_RF1N_MASK, 1U);
            //
            // 2-Enable Interrupt Line.
            //
            MCAN_selectIntrLine(MCAN_IR_RF1N_MASK, MCAN_INTR_LINE_NUM_0);
            //
            // 3-Enable Interrupt Line.
            //
            MCAN_enableIntrLine(MCAN_INTR_LINE_NUM_0, 1U);
    I have enabled interrupt related to the receiving status of a message. The latter takes place the first time and not again. 

  • Hi Davide,

    So, it is your MCANIntr1ISR() ISR that is having the issue, is that correct? If this is your only initialization code, there are a few enables that need to be added. You want everything in the below diagram to be closed in order for an interrupt to propagate to the ePIE (and therefore interrupt the CPU). 

    Can you verify that you are:

    • Initially enabling IER (this can be checked in the debugger under the CPU registers)
    • Initially enabling interrupts globally (check the INTM bit in the CPU registers)
    • Initially calling InitPieCtrl() and InitPieVectTable()
    • Clearing the ack group at the end of the ISR
    • The relevant MCAN flag is actually being raised after the first ISR (check in the Register view)

    Best Regards,

    Delaney