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.

MSPM0G3519-Q1: MCAN TX Skipping Messages and Transmission Complete Interrupt Not Triggering

Part Number: MSPM0G3519-Q1

Hi TI,

Regarding the discussion about MCAN TX messages being skipped:

WRT : link  i.e : MCAN TX skipping messages.

It was mentioned that:

"You need to send the next frame only after the previous frame has been transmitted successfully. Adding a delay between transmissions helps."

I understand that adding a delay allows time for the previous frame to complete transmission, and when I add a delay between TX operations, my messages are transmitted correctly. However, I would like to avoid using delays and instead rely on the Transmission Complete (TC) interrupt to know when the previous frame has been fully transmitted.

I have enabled the TC interrupt using the following configuration:

    DL_MCAN_enableIntr(pCfg->cfg.pRegs, DL_MCAN_INTERRUPT_TC, 1U);

    DL_MCAN_selectIntrLine(pCfg->cfg.pRegs, DL_MCAN_INTERRUPT_TC, DL_MCAN_INTR_LINE_NUM_0);
    DL_MCAN_enableIntrLine(pCfg->cfg.pRegs, DL_MCAN_INTR_LINE_NUM_0, 1U);

    DL_MCAN_clearInterruptStatus(pCfg->cfg.pRegs, DL_MCAN_MSP_INTERRUPT_LINE0);
    DL_MCAN_enableInterrupt(pCfg->cfg.pRegs, DL_MCAN_MSP_INTERRUPT_LINE0);

void MCAN0_INST_IRQHandler(void)
{
            uint32_t temp = DL_MCAN_getIntrStatus(MCAN0_INST);
            dbgPrintf("temp: %x\n", temp);
            if(temp & DL_MCAN_INTERRUPT_TC)
            {
                tempTXCom = 1;
            }
            dbgPrintf("tempTXCom: %x\n", tempTXCom);

            DL_MCAN_clearIntrStatus(MCAN0_INST, DL_MCAN_INTERRUPT_TC, DL_MCAN_INTR_SRC_MCAN_LINE_0);

However, I am not receiving the Transmission Complete interrupt, even though:

  • Multiple CAN nodes are connected

  • Bus termination is correct

Question 1: Why does adding a delay between CAN transmissions help prevent message skipping?

Question 2: What additional configuration is required to make the MCAN TC interrupt trigger correctly?

  • Hi,

    I will take a look, and get back to you.

    Could you share your CAN syscfg setup?

    Thanks


  • /* Defines for MCAN0 */
    #define MCAN0_INST                                                        CANFD0
    #define GPIO_MCAN0_CAN_TX_PORT                                             GPIOA
    #define GPIO_MCAN0_CAN_TX_PIN                                     DL_GPIO_PIN_12
    #define GPIO_MCAN0_IOMUX_CAN_TX                                  (IOMUX_PINCM34)
    #define GPIO_MCAN0_IOMUX_CAN_TX_FUNC               IOMUX_PINCM34_PF_CANFD0_CANTX
    #define GPIO_MCAN0_CAN_RX_PORT                                             GPIOA
    #define GPIO_MCAN0_CAN_RX_PIN                                     DL_GPIO_PIN_13
    #define GPIO_MCAN0_IOMUX_CAN_RX                                  (IOMUX_PINCM35)
    #define GPIO_MCAN0_IOMUX_CAN_RX_FUNC               IOMUX_PINCM35_PF_CANFD0_CANRX
    #define MCAN0_INST_IRQHandler                                 CANFD0_IRQHandler
    #define MCAN0_INST_INT_IRQN                                     CANFD0_INT_IRQn


    /* Defines for MCAN0 MCAN RAM configuration */
    #define MCAN0_INST_MCAN_STD_ID_FILT_START_ADDR     (0)
    #define MCAN0_INST_MCAN_STD_ID_FILTER_NUM          (2)
    #define MCAN0_INST_MCAN_EXT_ID_FILT_START_ADDR     (0)
    #define MCAN0_INST_MCAN_EXT_ID_FILTER_NUM          (1)
    #define MCAN0_INST_MCAN_TX_BUFF_START_ADDR         (148)
    #define MCAN0_INST_MCAN_TX_BUFF_SIZE               (2)
    #define MCAN0_INST_MCAN_FIFO_1_START_ADDR          (192)
    #define MCAN0_INST_MCAN_FIFO_1_NUM                 (2)
    #define MCAN0_INST_MCAN_TX_EVENT_START_ADDR        (164)
    #define MCAN0_INST_MCAN_TX_EVENT_SIZE              (2)
    #define MCAN0_INST_MCAN_EXT_ID_AND_MASK            (0x1FFFFFFFU)
    #define MCAN0_INST_MCAN_RX_BUFF_START_ADDR         (208)
    #define MCAN0_INST_MCAN_FIFO_0_START_ADDR          (172)
    #define MCAN0_INST_MCAN_FIFO_0_NUM                 (3)

    #define MCAN0_INST_MCAN_INTERRUPTS (DL_MCAN_INTERRUPT_ARA | \
                            DL_MCAN_INTERRUPT_BEU | \
                            DL_MCAN_INTERRUPT_BO | \
                            DL_MCAN_INTERRUPT_DRX | \
                            DL_MCAN_INTERRUPT_ELO | \
                            DL_MCAN_INTERRUPT_EP | \
                            DL_MCAN_INTERRUPT_EW | \
                            DL_MCAN_INTERRUPT_MRAF | \
                            DL_MCAN_INTERRUPT_PEA | \
                            DL_MCAN_INTERRUPT_PED | \
                            DL_MCAN_INTERRUPT_RF0N | \
                            DL_MCAN_INTERRUPT_TC | \
                            DL_MCAN_INTERRUPT_TEFN | \
                            DL_MCAN_INTERRUPT_TOO | \
                            DL_MCAN_INTERRUPT_TSW | \
                            DL_MCAN_INTERRUPT_WDI)

    /* clang-format on */
     DL_MCAN_reset(pCfg->cfg.pRegs);
        DL_MCAN_enablePower(pCfg->cfg.pRegs);

        delay_cycles(MS_TO_CPU_CLOCK_CYCLES(2));

        if (!DL_MCAN_isPowerEnabled(pCfg->cfg.pRegs))
        {
            dbgPrintf("DL_MCAN_isPowerEnabled() returns false.\n");
            return thb_Status_ErrHW;
        }

        // Enable and configure clock.
        DL_MCAN_enableModuleClock(pCfg->cfg.pRegs);
        DL_MCAN_setClockConfig(pCfg->cfg.pRegs, &pCfg->cfg.cfgClk);

        // Wait for Memory initialization to be completed.
        while (false == DL_MCAN_isMemInitDone(pCfg->cfg.pRegs));

        // Put MCAN in SW initialization mode.
        DL_MCAN_setOpMode(pCfg->cfg.pRegs, DL_MCAN_OPERATION_MODE_SW_INIT);

        /* Wait untill MCAN is in SW initialization mode. */
        while (DL_MCAN_OPERATION_MODE_SW_INIT != DL_MCAN_getOpMode(pCfg->cfg.pRegs));

        // Initialize MCAN module.
        DL_MCAN_init(pCfg->cfg.pRegs, &pCfg->cfg.initParams);

        // Configure MCAN module.
        DL_MCAN_config(pCfg->cfg.pRegs, &pCfg->cfg.cfgParams);

        // Configure Bit timings.
        DL_MCAN_setBitTime(pCfg->cfg.pRegs, &canBitrateEnumToCfg[pCfg->eBitrate]);

        // Configure Message RAM
        DL_MCAN_msgRAMConfig(pCfg->cfg.pRegs, &pCfg->cfg.cfgMsgRAM);

        // Configure Standard ID filter element
        DL_MCAN_addStdMsgIDFilter(pCfg->cfg.pRegs, 0U, &pCfg->cfg.cfgStdFiltElem);

        // Set Extended ID Mask.
        DL_MCAN_setExtIDAndMask(pCfg->cfg.pRegs, MCAN0_INST_MCAN_EXT_ID_AND_MASK);

        // Take MCAN out of the SW initialization mode.
        DL_MCAN_setOpMode(pCfg->cfg.pRegs, DL_MCAN_OPERATION_MODE_NORMAL);
        while (DL_MCAN_OPERATION_MODE_NORMAL != DL_MCAN_getOpMode(pCfg->cfg.pRegs));

        // Configure and enable MCAN module interrupts.
        DL_MCAN_enableIntr(pCfg->cfg.pRegs, MCAN0_INST_MCAN_INTERRUPTS & ~DL_MCAN_INTERRUPT_PEA & ~DL_MCAN_INTERRUPT_PED, 1U);

        DL_MCAN_selectIntrLine(pCfg->cfg.pRegs, DL_MCAN_INTR_MASK_ALL, DL_MCAN_INTR_LINE_NUM_0);
        DL_MCAN_enableIntrLine(pCfg->cfg.pRegs, DL_MCAN_INTR_LINE_NUM_0, 1U);

        DL_MCAN_clearInterruptStatus(pCfg->cfg.pRegs, DL_MCAN_MSP_INTERRUPT_LINE0);
        DL_MCAN_enableInterrupt(pCfg->cfg.pRegs, DL_MCAN_MSP_INTERRUPT_LINE0);