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: How can I continuous RX interrupt in MCAN (CAN-FD)?

Part Number: TMS320F28388D

Hi.

I am developing using the 28388D.

CAN-FD, a necessary function, is being implemented.

TX is polling, and RX is an interrupt.

So, I searched for related examples in C2000 of V304 and V400 and tried to run them.

In the example of mcan_ex_2_external_loopback_receive of V304, it is confirmed that the interrupt is performed only once when data is received.

Is it true that the example provided really only has onetime receive interrupt?

Am I doing something wrong?

And, when an error interrupt occurs, is there any action other than clearing it?

  • I solved the problem.

    Problem

    MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_MASK_ALL, 0);
    MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG | MCAN_INTR_SRC_RX_FIFO0_NEW_MSG | MCAN_INTR_SRC_RX_FIFO1_NEW_MSG, 1);
    MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_SRC_RX_FIFO0_NEW_MSG | MCAN_INTR_SRC_RX_FIFO1_NEW_MSG, 0);

    MCAN_selectIntrLine(MCAN0_BASE, MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG | MCAN_INTR_SRC_RX_FIFO0_NEW_MSG | MCAN_INTR_SRC_RX_FIFO1_NEW_MSG, MCAN_INTR_LINE_NUM_1);
    MCAN_enableIntrLine(MCAN0_BASE, MCAN_INTR_LINE_NUM_1, 1U);

    normal

    MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_MASK_ALL, 1);
    MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_SRC_RES_ADDR_ACCESS | MCAN_INTR_SRC_TIMESTAMP_WRAPAROUND, 0);
    MCAN_selectIntrLine(MCAN0_BASE, MCAN_INTR_SRC_RX_FIFO1_NEW_MSG, MCAN_INTR_LINE_NUM_1);
    MCAN_enableIntrLine(MCAN0_BASE, MCAN_INTR_LINE_NUM_1, 1U);

    What I meant was to disable all interrupts and enable only the ones I need.

    However, the interrupt did not occur after the 1st time.

    The normal case was to enable all interrupts and disable unnecessary interrupts.

    I don't know the difference between the two.

  • I have additional questions.

    1. How to use continuous receive interrupt using RX BUF?
    MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG,
    MCAN_readMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_BUF, 0U, MCAN_RX_FIFO_NUM_1, &drv_mcan_rx_msg);

    2. When using RX FIFO, there is a continuous receive interrupt, but why is it branched to interrupt twice?

    __interrupt void drv_irq1_MCAN(void)
    {
        /*
         * MCAN_INTR_SRC_RX_FIFO0_NEW_MSG       = 0x00000001U
         * MCAN_INTR_SRC_RX_FIFO0_WATERMARK     = 0x00000002U
         * MCAN_INTR_SRC_RX_FIFO0_FULL          = 0x00000004U
         * MCAN_INTR_SRC_RX_FIFO0_MSG_LOST      = 0x00000008U
         * MCAN_INTR_SRC_RX_FIFO1_NEW_MSG       = 0x00000010U
         * MCAN_INTR_SRC_RX_FIFO1_WATERMARK     = 0x00000020U
         * MCAN_INTR_SRC_RX_FIFO1_FULL          = 0x00000040U
         * MCAN_INTR_SRC_RX_FIFO1_MSG_LOST      = 0x00000080U
         * MCAN_INTR_SRC_HIGH_PRIO_MSG          = 0x00000100U
         * MCAN_INTR_SRC_TRANS_COMPLETE         = 0x00000200U
         * MCAN_INTR_SRC_TRANS_CANCEL_FINISH    = 0x00000400U
         * MCAN_INTR_SRC_TX_FIFO_EMPTY          = 0x00000800U
         * MCAN_INTR_SRC_TX_EVT_FIFO_NEW_ENTRY  = 0x00001000U
         * MCAN_INTR_SRC_TX_EVT_FIFO_WATERMARK  = 0x00002000U
         * MCAN_INTR_SRC_TX_EVT_FIFO_FULL       = 0x00004000U
         * MCAN_INTR_SRC_TX_EVT_FIFO_ELEM_LOST  = 0x00008000U
         * MCAN_INTR_SRC_TIMESTAMP_WRAPAROUND   = 0x00010000U
         * MCAN_INTR_SRC_MSG_RAM_ACCESS_FAILURE = 0x00020000U
         * MCAN_INTR_SRC_TIMEOUT                = 0x00040000U
         * MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG  = 0x00080000U
         * MCAN_INTR_SRC_BIT_ERR_CORRECTED      = 0x00100000U
         * MCAN_INTR_SRC_BIT_ERR_UNCORRECTED    = 0x00200000U
         * MCAN_INTR_SRC_ERR_LOG_OVRFLW         = 0x00400000U
         * MCAN_INTR_SRC_ERR_PASSIVE            = 0x00800000U
         * MCAN_INTR_SRC_WARNING_STATUS         = 0x01000000U
         * MCAN_INTR_SRC_BUS_OFF_STATUS         = 0x02000000U
         * MCAN_INTR_SRC_WATCHDOG               = 0x04000000U
         * MCAN_INTR_SRC_PROTOCOL_ERR_ARB       = 0x08000000U
         * MCAN_INTR_SRC_PROTOCOL_ERR_DATA      = 0x10000000U
         * MCAN_INTR_SRC_RES_ADDR_ACCESS        = 0x20000000U
         */
    
        //uint32_t intrStatus;
    
    
        intrStatus1 = MCAN_getIntrStatus(MCAN0_BASE);
        isrIntr1Flag++;
        printf("\r\nintrStatus1 : 0x%lx, ", intrStatus1);
    
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_NEW_MSG)        printf("Rx FIFO 0 New Message interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_WATERMARK)      printf("Rx FIFO 0 Watermark Reached interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_FULL)           printf("Rx FIFO 0 Full interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_MSG_LOST)       printf("Rx FIFO 0 Message Lost interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG)        printf("Rx FIFO 1 New Message interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_WATERMARK)      printf("Rx FIFO 1 Watermark Reached interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_FULL)           printf("Rx FIFO 1 Full interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_MSG_LOST)       printf("Rx FIFO 1 Message Lost interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_HIGH_PRIO_MSG)           printf("High Priority Message interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TRANS_COMPLETE)          printf("Transmission Completed interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TRANS_CANCEL_FINISH)     printf("Transmission Cancellation Finished interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_FIFO_EMPTY)           printf("Tx FIFO Empty interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_NEW_ENTRY)   printf("Tx Event FIFO New Entry interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_WATERMARK)   printf("Tx Event FIFO Watermark Reached interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_FULL)        printf("Tx Event FIFO Full interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_ELEM_LOST)   printf("Tx Event FIFO Element Lost interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TIMESTAMP_WRAPAROUND)    printf("Timestamp Wraparound interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_MSG_RAM_ACCESS_FAILURE)  printf("Message RAM Access Failure interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TIMEOUT)                 printf("Timeout Occurred interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG)   printf("Message stored to Dedicated Rx Buffer interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_BIT_ERR_CORRECTED)       printf("Bit Error Corrected interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_BIT_ERR_UNCORRECTED)     printf("Bit Error Uncorrected interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_ERR_LOG_OVRFLW)          printf("Error Logging Overflow interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_ERR_PASSIVE)             printf("Error Passive interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_WARNING_STATUS)          printf("Warning Status interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_BUS_OFF_STATUS)          printf("Bus_Off Status interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_WATCHDOG)                printf("Watchdog Interrupt interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_PROTOCOL_ERR_ARB)        printf("Protocol Error in Arbitration Phase interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_PROTOCOL_ERR_DATA)       printf("Protocol Error in Data Phase interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RES_ADDR_ACCESS)         printf("Access to Reserved Address interrupt\r\n");
    
    
        if (intrStatus1 & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG || intrStatus1 & MCAN_INTR_SRC_RX_FIFO0_NEW_MSG || intrStatus1 & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG) {
            //MCAN_getNewDataStatus(MCAN0_BASE, &newData);
    
            MCAN_readMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_FIFO, 0U, MCAN_RX_FIFO_NUM_1, &drv_mcan_rx_msg);
            drv_mcan_rx_fifo_status.num = MCAN_RX_FIFO_NUM_1;
            //MCAN_getRxFIFOStatus(MCAN0_BASE, &drv_mcan_rx_fifo_status);
            //MCAN_writeRxFIFOAck(MCAN0_BASE, MCAN_RX_FIFO_NUM_1, drv_mcan_rx_fifo_status.getIdx);
    
            newData.statusHigh = 0;
            newData.statusLow = 0;
            //MCAN_clearNewDataStatus(MCAN0_BASE, &newData);
            isrIntr1_1Flag++;
        }
    
        HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x2U);
        //MCAN_extTSWriteEOI(MCAN0_BASE);
        //MCAN_extTSClearRawStatus(MCAN0_BASE);
    
        MCAN_clearIntrStatus(MCAN0_BASE, intrStatus1);
        // Acknowledge this interrupt located in group 9
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }

  • Hi,

    This query has been forwarded to our subject matter expert.

    Regards,

    Praveen

  • Thanks,

    This is my final mcan source.

    it's working...but i don't know why occure irq twowice... 

    /*
     * drv_canfd.c
     *
     *  Created on: 2021. 12. 9.
     *      Author: JOO
     */
    
    #include <string.h>
    #include <stdio.h>
    
    #include "f28x_project.h"
    #include "driverlib.h"
    #include "device.h"
    
    #include "stw_dataTypes.h"
    #include "hw_types_mcan.h"
    
    #include "drv_mcan.h"
    #include "drv_gpio.h"
    
    #ifdef CPU1
    
    #ifdef _FLASH
    #pragma CODE_SECTION(drv_WriteMCAN, ".TI.ramfunc");
    #pragma CODE_SECTION(drv_irq_MCAN0, ".TI.ramfunc");
    #endif
    
    #define MCAN_STD_ID_FILT_START_ADDR   (0U)
    #define MCAN_STD_ID_FILTER_NUM        (1U)
    #define MCAN_EXT_ID_FILT_START_ADDR   (48U)
    #define MCAN_EXT_ID_FILTER_NUM        (1U)
    #define MCAN_TX_EVENT_START_ADDR      (100U)
    #define MCAN_TX_BUFF_START_ADDR       (148U)
    #define MCAN_FIFO_0_START_ADDR        (548U)
    #define MCAN_FIFO_1_START_ADDR        (748U)
    #define MCAN_RX_BUFF_START_ADDR       (948U)
    #define MCAN_EXT_ID_AND_MASK          (0x1FFFFFFFU)
    #define MCAN_TS_PRESCALAR             (0xB0)
    
    MCAN_TxBufElement drv_mcan_tx_msg;
    MCAN_RxBufElement drv_mcan_rx_msg;
    uint32_t drv_irq_mcan0_status = 0;
    uint32_t drv_irq_mcan0_recv_cnt = 0;
    
    static void drv_ConfigMCANGpio(void);
    static void drv_ConfigMCAN(void);
    __interrupt void drv_irq_MCAN0(void);
    
    static void drv_ConfigMCANGpio(void)
    {
    #ifndef _28377D
        //MCAN(CAN-FD) RX
        drv_ConfigGPIO(GPIO_CORE_CPU1, 5, 0xFFFF, GPIO_5_MCAN_RX, 0xFFFF, 0xFFFF, 0xFFFF);
        //MCAN(CAN-FD) TX
        drv_ConfigGPIO(GPIO_CORE_CPU1, 4, 0xFFFF, GPIO_4_MCAN_TX, 0xFFFF, 0xFFFF, 0xFFFF);
    #endif
    }
    
    static void drv_ConfigMCAN(void)
    {
    #ifndef _28377D
        MCAN_RevisionId             revId;
        MCAN_InitParams             initParams;
        MCAN_ConfigParams           configParams;
        MCAN_MsgRAMConfigParams     msgRAMConfigParams;
        MCAN_StdMsgIDFilterElement  stdFiltelem;
        MCAN_ExtMsgIDFilterElement  extFiltelem;
        MCAN_BitTimingParams        bitTimes;
    
        // Initialize MCAN Init parameters.
        initParams.fdMode           = 0x1U;  // FD operation enabled.
        initParams.brsEnable        = 0x1U;  // Bit rate switching for transmissions enabled.
        initParams.txpEnable        = 0x1U;  // Transmit pause disabled.
        initParams.efbi             = 0x0U;  // Edge filtering disabled.
        initParams.pxhddisable      = 0x0U;  // Protocol exception handling enabled.
        initParams.darEnable        = 0x1U;  // Automatic retransmission of messages not transmitted successfully enabled.
        initParams.wkupReqEnable    = 0x1U;  // Wakeup request is enabled.
        initParams.autoWkupEnable   = 0x1U;  // Auto-Wakeup is enabled.
        initParams.emulationEnable  = 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        = 0x0U;  // 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             = 1;                            // Number of Dedicated Transmit Buffers.
        msgRAMConfigParams.txFIFOSize           = 1;                            // Tx FIFO/Queue.
        msgRAMConfigParams.txBufMode            = 1U;                           //Tx FIFO operation
        msgRAMConfigParams.txBufElemSize        = MCAN_ELEM_SIZE_64BYTES;       // Tx Buffer Element Size.
        msgRAMConfigParams.txEventFIFOStartAddr = MCAN_TX_EVENT_START_ADDR;     // Tx Event FIFO Start Address.
        msgRAMConfigParams.txEventFIFOSize      = 1;                            // Event FIFO Size.
        msgRAMConfigParams.txEventFIFOWaterMark = 0;                            // Level for Tx Event FIFO watermark interrupt.
    
        msgRAMConfigParams.rxFIFO0startAddr     = MCAN_FIFO_0_START_ADDR;       // Rx FIFO0 Start Address.
        msgRAMConfigParams.rxFIFO0size          = 1;                            // Number of Rx FIFO elements.
        msgRAMConfigParams.rxFIFO0waterMark     = 0;
        msgRAMConfigParams.rxFIFO0OpMode        = 1U;
        msgRAMConfigParams.rxFIFO1startAddr     = MCAN_FIFO_1_START_ADDR;       // Rx FIFO1 Start Address.
        msgRAMConfigParams.rxFIFO1size          = 1;                            // Number of Rx FIFO elements.
        msgRAMConfigParams.rxFIFO1waterMark     = 0;                            // Level for Rx FIFO 1 watermark interrupt.
        msgRAMConfigParams.rxFIFO1OpMode        = 1U;                           // FIFO blocking mode.
        msgRAMConfigParams.rxBufStartAddr       = MCAN_RX_BUFF_START_ADDR;      // Rx Buffer Start Address.
        msgRAMConfigParams.rxBufElemSize        = MCAN_ELEM_SIZE_64BYTES;       // Rx Buffer Element Size.
        msgRAMConfigParams.rxFIFO0ElemSize      = MCAN_ELEM_SIZE_64BYTES;       // Rx FIFO0 Element Size.
        msgRAMConfigParams.rxFIFO1ElemSize      = MCAN_ELEM_SIZE_64BYTES;       // Rx FIFO1 Element Size.
    
        // Initialize Tx Buffer Configuration parameters.
        //stdFiltelem.sfid2              = 0x0U; // Standard Filter ID 2.
        //stdFiltelem.sfid1              = 0x4U; // Standard Filter ID 1.
        //stdFiltelem.sfec               = 0x7U; // Store into Rx Buffer or as debug message, configuration of SFT[1:0] ignored.
        //stdFiltelem.sft                = 0x11U; // Range filter from SFID1 to SFID2.
    
        // Initialize Tx Buffer Configuration parameters.
        //extFiltelem.efid2   = 0x0U;
        //extFiltelem.efid1   = 0x0U;
        //extFiltelem.efec    = 0x0U;
        //extFiltelem.eft     = 0x11U;
    
    #if 1
        /*
         * MCANBitClk = CM_Clk/MCANCLKDIV
         * NominalbitTime = (NTSEG1 + 1) + (NTSEG2 + 1) + 1
         * NominalBRP = (NBRP+1)
         * FinalNominalBaudRate = MCANBitClk/( NominalBRP * NominalbitTime)
         *
         * DatabitTime = (DTSEG1 + 1) + (DTSEG2 + 1) + 1
         * DataBRP = (DBRP+1)
         * FinalDataBaudRate = MCANBitClk/( DataBRP * DatabitTime)
         */
    
        // Nominal Bit Rate of 500 kbps & Data bit rate of 1 Mbps
        // Initialize bit timings.
        bitTimes.nomRatePrescalar   = 0x3U;  // Nominal Baud Rate Pre-scaler.
        bitTimes.nomTimeSeg1        = 0x9U;  // Nominal Time segment before sample point.
        bitTimes.nomTimeSeg2        = 0x8U;  // Nominal Time segment after sample point.
        bitTimes.nomSynchJumpWidth  = 0x8U;  // Nominal (Re)Synchronization Jump Width Range.
        bitTimes.dataRatePrescalar  = 0x1U;  // Data Baud Rate Pre-scaler.
        bitTimes.dataTimeSeg1       = 0x9U;  // Data Time segment before sample point.
        bitTimes.dataTimeSeg2       = 0x8U;  // Data Time segment after sample point.
        bitTimes.dataSynchJumpWidth = 0x8U;  // Data (Re)Synchronization Jump Width.
    #endif
    
        // Get MCANSS Revision ID
        MCAN_getRevisionId(MCAN0_BASE, &revId);
    
        // Wait for memory initialization to happen.
        while (FALSE == MCAN_isMemInitDone(MCAN0_BASE)) {
        }
    
        // Put MCAN in SW initialization mode.
        MCAN_setOpMode(MCAN0_BASE, MCAN_OPERATION_MODE_SW_INIT);
    
        // Wait till MCAN is not initialized.
        while (MCAN_OPERATION_MODE_SW_INIT != MCAN_getOpMode(MCAN0_BASE)) {
        }
    
        // Initialize MCAN module.
        MCAN_init(MCAN0_BASE, &initParams);
    
        // Configure MCAN module.
        MCAN_config(MCAN0_BASE, &configParams);
    
        // Enable external timeStamp overflow interrupt.
        MCAN_extTSEnableIntr(MCAN0_BASE, 1);
    
        // Configure TimeStamp Counter.
        MCAN_extTSCounterConfig(MCAN0_BASE, MCAN_TS_PRESCALAR);
    
        // Configure Bit timings.
        MCAN_setBitTime(MCAN0_BASE, &bitTimes);
    
        // Set Extended ID Mask.
        MCAN_setExtIDAndMask(MCAN0_BASE, MCAN_EXT_ID_AND_MASK);
    
        // Configure Message RAM Sections
        MCAN_msgRAMConfig(MCAN0_BASE, &msgRAMConfigParams);
    
        // Configure Standard ID filter element
        MCAN_addStdMsgIDFilter(MCAN0_BASE, 0U, &stdFiltelem);
    
        // Configure Extended ID filter element
        //MCAN_addExtMsgIDFilter(MCAN0_BASE, 0U, &extFiltelem);
    
        // Enable external counter.
        MCAN_extTSCounterEnable(MCAN0_BASE, 1U);
    
        // Take MCAN out of the SW initialization mode
        MCAN_setOpMode(MCAN0_BASE, MCAN_OPERATION_MODE_NORMAL);
    
        while (MCAN_OPERATION_MODE_NORMAL != MCAN_getOpMode(MCAN0_BASE)) {
    
        }
    #endif
    }
    
    void drv_InitMCAN(void)
    {
        drv_ConfigMCANGpio();
        SysCtl_allocateSharedPeripheral(SYSCTL_PALLOCATE_MCAN_A, 0x0U);  //allocated to C28x
    
        SysCtl_setMCANClk(SYSCTL_MCANCLK_DIV_5);
    
        //Interrupt
        Interrupt_register(INT_MCANSS0, &drv_irq_MCAN0);
        Interrupt_enable(INT_MCANSS0);
    
        drv_ConfigMCAN();
    
        MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_MASK_ALL, 1);
        MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_SRC_RES_ADDR_ACCESS | MCAN_INTR_SRC_TIMESTAMP_WRAPAROUND, 0);
        MCAN_selectIntrLine(MCAN0_BASE, MCAN_INTR_SRC_RX_FIFO1_NEW_MSG | MCAN_INTR_SRC_TRANS_COMPLETE, MCAN_INTR_LINE_NUM_0);
        MCAN_enableIntrLine(MCAN0_BASE, MCAN_INTR_LINE_NUM_0, 1U);
    
        drv_mcan_tx_msg.id      = ((uint32_t) (0x4)) << 18U;  // STDID[28:18]
        drv_mcan_tx_msg.rtr     = 0U;   // RTR = 0 (Data frame)
        drv_mcan_tx_msg.xtd     = 0U;   // XTD = 0 (11-bit standard identifier)
        drv_mcan_tx_msg.esi     = 1U;
        drv_mcan_tx_msg.dlc     = 15U;  // 64 bytes
        drv_mcan_tx_msg.brs     = 0U;   // Bit-rate switching enabled
        drv_mcan_tx_msg.fdf     = 1U;   // Frame transmitted in CAN FD format
        drv_mcan_tx_msg.efc     = 1U;   // Store TX events
        drv_mcan_tx_msg.mm      = 0xAAU;
    }
    
    void drv_WriteMCAN(uint32_t id, uint16_t *data)
    {
        uint16_t i;
    
        drv_mcan_tx_msg.id = ((uint32_t) (id)) << 18U;  // STDID[28:18]
        for (i = 0; i < 64; i++) {
            drv_mcan_tx_msg.data[i] = data[i];
        }
    
        MCAN_writeMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_FIFO, 0, (const MCAN_TxBufElement*) &drv_mcan_tx_msg);
    
        MCAN_txBufTransIntrEnable(MCAN0_BASE, 0, 1U);
    
        MCAN_txBufAddReq(MCAN0_BASE, 1);
    }
    
    __interrupt void drv_irq_MCAN0(void)
    {
        drv_irq_mcan0_status = MCAN_getIntrStatus(MCAN0_BASE);
    
    #if 0
        printf("\r\nintrStatus : 0x%lx\r\n", drv_irq_mcan0_status);
    
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_NEW_MSG)        printf("Rx FIFO 0 New Message interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_WATERMARK)      printf("Rx FIFO 0 Watermark Reached interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_FULL)           printf("Rx FIFO 0 Full interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO0_MSG_LOST)       printf("Rx FIFO 0 Message Lost interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG)        printf("Rx FIFO 1 New Message interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_WATERMARK)      printf("Rx FIFO 1 Watermark Reached interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_FULL)           printf("Rx FIFO 1 Full interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RX_FIFO1_MSG_LOST)       printf("Rx FIFO 1 Message Lost interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_HIGH_PRIO_MSG)           printf("High Priority Message interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TRANS_COMPLETE)          printf("Transmission Completed interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TRANS_CANCEL_FINISH)     printf("Transmission Cancellation Finished interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_FIFO_EMPTY)           printf("Tx FIFO Empty interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_NEW_ENTRY)   printf("Tx Event FIFO New Entry interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_WATERMARK)   printf("Tx Event FIFO Watermark Reached interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_FULL)        printf("Tx Event FIFO Full interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TX_EVT_FIFO_ELEM_LOST)   printf("Tx Event FIFO Element Lost interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TIMESTAMP_WRAPAROUND)    printf("Timestamp Wraparound interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_MSG_RAM_ACCESS_FAILURE)  printf("Message RAM Access Failure interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_TIMEOUT)                 printf("Timeout Occurred interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG)   printf("Message stored to Dedicated Rx Buffer interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_BIT_ERR_CORRECTED)       printf("Bit Error Corrected interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_BIT_ERR_UNCORRECTED)     printf("Bit Error Uncorrected interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_ERR_LOG_OVRFLW)          printf("Error Logging Overflow interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_ERR_PASSIVE)             printf("Error Passive interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_WARNING_STATUS)          printf("Warning Status interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_BUS_OFF_STATUS)          printf("Bus_Off Status interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_WATCHDOG)                printf("Watchdog Interrupt interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_PROTOCOL_ERR_ARB)        printf("Protocol Error in Arbitration Phase interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_PROTOCOL_ERR_DATA)       printf("Protocol Error in Data Phase interrupt\r\n");
        if (MCAN_getIntrStatus(MCAN0_BASE) & MCAN_INTR_SRC_RES_ADDR_ACCESS)         printf("Access to Reserved Address interrupt\r\n");
    #endif
    
        if (drv_irq_mcan0_status & MCAN_INTR_SRC_DEDICATED_RX_BUFF_MSG || drv_irq_mcan0_status & MCAN_INTR_SRC_RX_FIFO0_NEW_MSG || drv_irq_mcan0_status & MCAN_INTR_SRC_RX_FIFO1_NEW_MSG) {
            MCAN_readMsgRam(MCAN0_BASE, MCAN_MEM_TYPE_FIFO, 0U, MCAN_RX_FIFO_NUM_1, &drv_mcan_rx_msg);
            drv_irq_mcan0_recv_cnt++;
        }
    
        HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x1U);
    
        MCAN_clearIntrStatus(MCAN0_BASE, drv_irq_mcan0_status);
    
        // Acknowledge this interrupt located in group 9
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }
    
    #endif
    

    Finally, the can-fd sending/receiving behavior I want is as follows.

    Receiving works as an interrupt.
    Transmission works by calling a function by polling.

    For reference, I also share the general CAN code that I have implemented and used as above.

    /*
     * drv_can.c
     *
     *  Created on: Nov 4, 2021
     *      Author: JOO
     */
    
    #include "f28x_project.h"
    #include "driverlib.h"
    #include "device.h"
    
    #include <string.h>
    
    #include "drv_gpio.h"
    #include "drv_can.h"
    
    #ifdef CPU1
    #ifdef _FLASH
    #pragma CODE_SECTION(drv_WriteCAN, ".TI.ramfunc");
    #pragma CODE_SECTION(drv_irq_CANA, ".TI.ramfunc");
    #endif
    #endif
    
    volatile DrvCanMsg drv_can_msg;
    
    static void drv_ConfigCANGpio(void);
    static void drv_InitCANMsgObj(void);
    
    static void drv_ConfigCANGpio(void)
    {
    #ifndef _28377D
        //CAN-A RX
        drv_ConfigGPIO(GPIO_CORE_CPU1, 62, GPIO_DIR_MODE_OUT, GPIO_62_CANA_RX, GPIO_PIN_TYPE_STD, GPIO_QUAL_SYNC, 1);
        //CAN-A TX
        drv_ConfigGPIO(GPIO_CORE_CPU1, 63, GPIO_DIR_MODE_OUT, GPIO_63_CANA_TX, GPIO_PIN_TYPE_STD, GPIO_QUAL_SYNC, 1);
    #endif
    }
    
    static void drv_InitCANMsgObj(void)
    {
        memset((void*)&drv_can_msg, NULL, sizeof(DrvCanMsg));
    
        //TX Report 1
        drv_can_msg.obj[0].obj_id = 1;
        drv_can_msg.obj[0].can_id = 0x110;
        drv_can_msg.obj[0].type = CAN_MSG_OBJ_TYPE_TX;
        drv_can_msg.obj[0].flag = CAN_MSG_OBJ_NO_FLAGS;
        drv_can_msg.obj[0].irq_cnt = 0;
    
        //TX Report 2
        drv_can_msg.obj[1].obj_id = 2;
        drv_can_msg.obj[1].can_id = 0x120;
        drv_can_msg.obj[1].type = CAN_MSG_OBJ_TYPE_TX;
        drv_can_msg.obj[1].flag = CAN_MSG_OBJ_NO_FLAGS;
        drv_can_msg.obj[1].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[2].obj_id = 3;
        drv_can_msg.obj[2].can_id = 0x100;
        drv_can_msg.obj[2].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[2].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[2].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[3].obj_id = 4;
        drv_can_msg.obj[3].can_id = 0x101;
        drv_can_msg.obj[3].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[3].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[3].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[4].obj_id = 5;
        drv_can_msg.obj[4].can_id = 0x102;
        drv_can_msg.obj[4].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[4].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[4].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[5].obj_id = 6;
        drv_can_msg.obj[5].can_id = 0x103;
        drv_can_msg.obj[5].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[5].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[5].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[6].obj_id = 7;
        drv_can_msg.obj[6].can_id = 0x104;
        drv_can_msg.obj[6].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[6].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[6].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[7].obj_id = 8;
        drv_can_msg.obj[7].can_id = 0x105;
        drv_can_msg.obj[7].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[7].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[7].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[8].obj_id = 9;
        drv_can_msg.obj[8].can_id = 0x106;
        drv_can_msg.obj[8].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[8].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[8].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[9].obj_id = 10;
        drv_can_msg.obj[9].can_id = 0x107;
        drv_can_msg.obj[9].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[9].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[9].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[10].obj_id = 11;
        drv_can_msg.obj[10].can_id = 0x108;
        drv_can_msg.obj[10].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[10].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[10].irq_cnt = 0;
    
        //RX Command
        drv_can_msg.obj[11].obj_id = 12;
        drv_can_msg.obj[11].can_id = 0x109;
        drv_can_msg.obj[11].type = CAN_MSG_OBJ_TYPE_RX;
        drv_can_msg.obj[11].flag = CAN_MSG_OBJ_RX_INT_ENABLE;
        drv_can_msg.obj[11].irq_cnt = 0;
    }
    
    void drv_InitCAN(void)
    {
        Uint16 i;
    
    #ifdef CPU1
        drv_ConfigCANGpio();
        SysCtl_selectCPUForPeripheral(SYSCTL_CPUSEL8_CAN, 1, SYSCTL_CPUSEL_CPU1);
    #endif
    
    #ifdef CPU1
        drv_InitCANMsgObj();
    
        CAN_initModule(USE_CAN);
        CAN_setBitRate(USE_CAN, DEVICE_SYSCLK_FREQ, CAN_BITRATE, 20);
    
        CAN_enableInterrupt(CANA_BASE, CAN_INT_IE0 | CAN_INT_ERROR | CAN_INT_STATUS);
        Interrupt_register(INT_CANA0, &drv_irq_CANA);
        Interrupt_enable(INT_CANA0);
        CAN_enableGlobalInterrupt(USE_CAN, CAN_GLOBAL_INT_CANINT0);
    
        for (i = 0; i < 32; i++) {
            if(drv_can_msg.obj[i].obj_id != NULL) {
                CAN_setupMessageObject(USE_CAN,                     //base
                                       drv_can_msg.obj[i].obj_id,   //obj ID
                                       drv_can_msg.obj[i].can_id,   //msg ID
                                       CAN_MSG_FRAME_STD,           //frame
                                       drv_can_msg.obj[i].type,     //msg type
                                       0,                           //msg IDMask
                                       drv_can_msg.obj[i].flag,     //flag
                                       8);                          //msg len
            }
        }
    
        CAN_startModule(USE_CAN);
    #endif
    }
    
    void drv_WriteCAN(uint32_t id, Uint16 *data, Uint16 size)
    {
        Uint16 i;
        Uint16 data_temp[8] = { 0, };
    
        for (i = 0; i < size; i++) {
            data_temp[i] = data[i];
        }
    
        CAN_sendMessage(USE_CAN, id, 8, data_temp);
    }
    
    //
    // CAN ISR - The interrupt service routine called when a CAN interrupt is
    //           triggered.  It checks for the cause of the interrupt, and
    //           maintains a count of all messages that have been transmitted.
    //
    __interrupt void drv_irq_CANA(void)
    {
        uint32_t status;
        Uint16 i;
    
        // Read the CAN interrupt status to find the cause of the interrupt
        status = CAN_getInterruptCause(USE_CAN);
    
        // If the cause is a controller status interrupt, then get the status
        if (status == CAN_INT_INT0ID_STATUS) {
            // Read the controller status.  This will return a field of status
            // error bits that can indicate various errors.  Error processing
            // is not done in this example for simplicity.  Refer to the
            // API documentation for details about the error status bits.
            // The act of reading this status will clear the interrupt.
            status = CAN_getStatus(USE_CAN);
    
            // Check to see if an error occurred.
            if (((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 7) && ((status & ~(CAN_STATUS_TXOK | CAN_STATUS_RXOK)) != 0)) {
                // Set a flag to indicate some errors may have occurred.
                drv_can_msg.error_cnt++;
            }
        } else {
            for (i = 0; i < 32 && drv_can_msg.obj[i].can_id != NULL; i++) {
                if (status == drv_can_msg.obj[i].obj_id) {
                    drv_can_msg.obj[i].irq_cnt++;
                    CAN_readMessage(USE_CAN, drv_can_msg.obj[i].obj_id, (uint16_t*) &drv_can_msg.obj[i].data);
                    CAN_clearInterruptStatus(USE_CAN, drv_can_msg.obj[i].obj_id);
                    break;
                }
            }
        }
    
        // Clear the global interrupt flag for the CAN interrupt line
        CAN_clearGlobalInterruptStatus(USE_CAN, CAN_GLOBAL_INT_CANINT0);
    
        // Acknowledge this interrupt located in group 9
        Interrupt_clearACKGroup(INTERRUPT_ACK_GROUP9);
    }
    

    As above, I also wanted to make CAN-FD.

  • i want to solve why interrupt takes 2 times,

    In my system, the main interrupt is a timer and operates at 20khz.

    For UI interfacing, for communication data load test, send data at a frequent cycle rate, and try to match the number of received irqs.

    Reception of both CAN and CAN-FD is normal. No data is lost.

    However, the main timer interrupt is broken in CAN-FD.

    CAN does not break the main timer interrupt.

    For CAN-FD

    For general CAN

    Both are operated in CPU1, and yellow is the signal for checking the operation of Timer 1.