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.

TMS320F28384D: MCAN only generate once interrupt

Part Number: TMS320F28384D
Other Parts Discussed in Thread: C2000WARE

Dears

My customer 1st time to develop MCAN base on F28384, we expect to generate MCAN RX interrupt while RX BUFF receive new data, however now only can generate once interrupt then never happen interrupt again, we check the register status as below:

1,   CPU enter MCAN 1st time RX interrupt function, check both MCAN interrupt flag and CPU PIE flag are set in register window

2,   Firmware clear both MCAN interrupt flag and CPU PIE flag and confirm they turn to 0 in register window, then exit the interrupt function

3,   Send CAN new data to the Bus, and confirm the RX BUFF receive the new data in register window

4,   Check the MCAN interrupt flag is set again, and confirm the MCAN interrupt enable is set

5,   however CPU never respond the MCAN interrupt function, check the CPU PIE flag is always 0 and will not set again

6,   Other function interrupt can still continue work normal, indicate the CPU PIE should work without block

May I ask if we have example code for implement MCAN RX BUFF interrupt? Because I check it seem do not have such example in C2000WARE so far? I also attach customer code for MCAN configuration, or could you help review if customer code has some mistake?    

#include "f28x_project.h"
#include "inc/hw_memmap.h"
#include "MCAN_Config.h"
#include "UDS_Para.h"
#include "hw_types.h"
#include "gpio.h"
#include "device.h"
#include "HW_Config.h"


void Init_MCAN(void)
{
    MCAN_InitParams         initParams;
    MCAN_BitTimingParams    bitTimes;
    MCAN_MsgRAMConfigParams msgRAMConfigParams;

    //
    // Initialize MCAN Init parameters.
    //
    initParams.fdMode            = 0x0U; // FD operation disabled.
    initParams.brsEnable         = 0x0U; // Bit rate switching for

    //
    // Initialize bit timings.
    //
#if (CAN_BAUD_RATE == CAN_BR_500K)
    bitTimes.nomRatePrescalar   = 19U;  // Nominal Baud Rate Pre-scaler.
    bitTimes.nomTimeSeg1        = 14U;  // Nominal Time segment before SP.
    bitTimes.nomTimeSeg2        = 3U;   // Nominal Time segment after SP.
    bitTimes.nomSynchJumpWidth  = 2U;   // Nominal SJW Range.
#elif (CAN_BAUD_RATE == CAN_BR_250K)
    bitTimes.nomRatePrescalar   = 39U;  // Nominal Baud Rate Pre-scaler.
    bitTimes.nomTimeSeg1        = 14U;  // Nominal Time segment before SP.
    bitTimes.nomTimeSeg2        = 3U;   // Nominal Time segment after SP.
    bitTimes.nomSynchJumpWidth  = 2U;   // Nominal SJW Range.
#endif

    //
    // Initialize Message RAM Sections Configuration Parameters
    //
    msgRAMConfigParams.txStartAddr          = MCAN_TX_BUFF_START_ADDR;  // Tx Buffers Start Address.
    msgRAMConfigParams.txBufNum             = MCAN_TX_BUFF_SIZE;        // Number of Dedicated Transmit Buffers.
    msgRAMConfigParams.txBufMode            = 0U;
    msgRAMConfigParams.txBufElemSize        = MCAN_ELEM_SIZE_8BYTES;    // Tx Buffer Element Size.

    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.
#if (CAN_RXMODE == CAN_RXBUFFMODE)
    msgRAMConfigParams.rxBufStartAddr       = MCAN_RX_BUFF_START_ADDR;  // Rx Buffer Start Address.
    msgRAMConfigParams.rxBufElemSize        = MCAN_ELEM_SIZE_8BYTES;    // Rx Buffer Element Size.
#elif (CAN_RXMODE == CAN_RXFIFOMODE)
    // FIFO Configuration Parameters
    msgRAMConfigParams.rxFIFO0startAddr     = MCAN_FIFO_0_START_ADDR;   // Rx FIFO1 Start Address (748U).
    msgRAMConfigParams.rxFIFO0size          = MCAN_FIFO_0_NUM;          // Number of Rx FIFO elements (1).
    msgRAMConfigParams.rxFIFO0waterMark     = MCAN_FIFO_0_WATERMARK;    // Level for Rx FIFO 1 watermark interrupt (1).
    msgRAMConfigParams.rxFIFO0OpMode        = 1U;                       //FIFO Overwrite mode
    msgRAMConfigParams.rxFIFO0ElemSize      = MCAN_ELEM_SIZE_8BYTES;    // Rx FIFO1 Element Size. RBDS field of MCAN_RXESC Register
#endif

    //
    // 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 Bit timings.
    //
    MCAN_setBitTime(MCAN0_BASE, &bitTimes);

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

    //
    // Configure Standard ID filter element
    //
    SetMsgBox();

    //
    // Enable Interrupts.
    //
//    MCAN_enableIntr(MCAN0_BASE, MCAN_INTR_MASK_ALL, 1U);
    MCAN_enableIntr(MCAN0_BASE, MCAN_IR_DRX_MASK, 1U);
//    MCAN_enableIntr(MCAN0_BASE, MCAN_IR_RF0N_MASK, 1U);

//    Uint32 LTempAx;
//    LTempAx = MCAN_getIE(MCAN0_BASE); //DeBug

    //
    // Select Interrupt Line.
    //
    MCAN_selectIntrLine(MCAN0_BASE, MCAN_IR_DRX_MASK, MCAN_INTR_LINE_NUM_0);

    //
    // Enable Interrupt Line.
    //
    MCAN_enableIntrLine(MCAN0_BASE, MCAN_INTR_LINE_NUM_0, 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))
    {

    }
}

void SetMsgBox(void)
{
    int16 i;
    Uint16 RxFiltNum = 0;

    MCAN_StdMsgIDFilterElement  RxMsg_Std;
    MCAN_ExtMsgIDFilterElement  RxMsg_Ext;

    for(i = 0; i < MAX_ID_CNT; i++)
    {
        if(CanIdConfig[i].MsgBoxId < 32)
        {
            if(CanIdConfig[i].IsTxId == RX_ID)
            {
                if(CanIdConfig[i].IsExtId == STAND_ID)
                {
#if (CAN_RXMODE == CAN_RXBUFFMODE)
                    RxMsg_Std.sfid2 = (0x1 << RxFiltNum);   // Standard Filter ID 2.
                    RxMsg_Std.sfid1 = CanIdConfig[i].ID;    // Standard Filter ID 1.
                    RxMsg_Std.sfec  = 0x7U;                 // Store into Rx Buffer
#elif (CAN_RXMODE == CAN_RXFIFOMODE)
                    RxMsg_Std.sft   = 1;                    // SFID1 or SFID2
                    RxMsg_Std.sfid2 = CanIdConfig[i].ID;    // Standard Filter ID 2.
                    RxMsg_Std.sfid1 = CanIdConfig[i].ID;    // Standard Filter ID 1.
                    RxMsg_Std.sfec  = 0x1U;                 // Store in Rx FIFO 0 if filter matches
#endif

                    MCAN_addStdMsgIDFilter(MCAN0_BASE, (2 * RxFiltNum + 1), &RxMsg_Std);
                    RxFiltNum++;
                }
                else
                {
#if (CAN_RXMODE == CAN_RXBUFFMODE)

                    RxMsg_Ext.efid2 = (0x1 << RxFiltNum);            // Standard Filter ID 2.
                    RxMsg_Ext.efid1 = CanIdConfig[i].ID;    // Standard Filter ID 1.
                    RxMsg_Ext.efec  = 0x7U;                 // Store into Rx Buffer

#elif (CAN_RXMODE == CAN_RXFIFOMODE)

                    RxMsg_Ext.eft   = 1;                    // SFID1 or SFID2
                    RxMsg_Ext.efid2 = CanIdConfig[i].ID;    // Standard Filter ID 2.
                    RxMsg_Ext.efid1 = CanIdConfig[i].ID;    // Standard Filter ID 1.
                    RxMsg_Ext.efec  = 0x1U;                 // Store in Rx FIFO 0 if filter matches

#endif

                    MCAN_addExtMsgIDFilter(MCAN0_BASE, RxFiltNum, &RxMsg_Ext);
                    RxFiltNum++;
                }
            }
        }
        else
        {
            asm ("      ESTOP0");
        }
    }
}

  • Second question is that customer can receive both standard Message and Extended Message by using RX FIFO, however only can receive one type Message by using RX BUFF. May we get advice what setting will cause such difference behavior? thank you.

  • Hi Terry,

    For the interrupt question, i did not see from the customer code how the interrupt has been configured.  In the MCAN loopback example, there is a function call which is MCANIntrConfig() which sets and defines the MCAN interrupt.  That might be able to help.

    Checking with the other MCAN experts on the RX FIFO and RX BUFF issues.

    Regards,

    Joseph

  • Hi Joseph

    Thanks your advice. We have solved the interrupt issue today. It affected by how to clear the MCAN flag in RX interrupt function as below.

    EALLOW;   McanssRegs.MCANSS_EOI.bit.EOI = 1; EDIS;     // this code has issue and only generate once RX interrupt

    HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x1U);    // this code will run normal and continue generate RX interrupt

    However we still do not solve the RX message type issue. We set the both Standard ID and Extended ID filter, and can receive both two type message while using RX FIFO, however only can receive Extended message while using RX BUFF. Appreciate expert advice for how to receive both type message by using RX BUFF.

  • Terry, 

    In case I'm interpreting your question right, you are having issues receiving extended messages using RX BUFF. If I'm wrong in understanding your question, please let me know.

    I think you need to reevaluate the values for SFID2/EFID2 being set. The value being set for SFID2/EFID2 directly corresponds to the filter number.

    RxMsg_Ext.efid2 = RxFiltNum; 
    
    //Other configurations go here
    
    MCAN_addExtMsgIDFilter(MCAN0_BASE, RxFiltNum, &RxMsg_Ext);

    Thanks.

  • Terry, 

    To properly clear the interrupt, include the following line in the ISR

    HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x2);
    
    //      For the last parameter
    //  0x01 clears Interrupt line 0
    //  0x02 clears Interrupt line 1

    Thanks.

  • Thanks, Sahil

    Yes, you are right. Now we include code 1 as "HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x2);" in the ISR and run normal.  At beginning we include code 2 as "EALLOW;   McanssRegs.MCANSS_EOI.bit.EOI = 1; EDIS; " in the ISR and only generate once interrupt. Actually I do not understand what is different for code 1 and code 2, I though there should set same register to same value.  

  • Terry, 

    We are looking into it and will get back to you soon.

    Do provide an update on if you are able to operate the RX BUFF properly.

    Thanks.

  • Hi Sahil

    Sorry for late update because china just spend several day holiday. Now we can receive both extended and standard message by using RX BUFF according your advice. thank you. 

    However the ISR still generate only once interrupt by using RX BUFF.  We make sure included "HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x2" in the interrupt function, and if we using RX FIFO then ISR can continue generate interrupt. I cannot understand why ISR come to difference behavior for RX FIFO and RX BUFF? 

  • Terry, 

    First of all, given that the code mentioned above is enabling Interrupt Line 0, so I am assuming that the last parameter you have used is "0x1" and not as you have mentioned in the reply above.

    HW_WR_FIELD32(MCAN0_BASE + MCAN_MCANSS_EOI, MCAN_MCANSS_EOI, 0x2

    Second, as can be seen mentioned in the device TRM, the NewData flag for the respective RX BUFF needs to be cleared, without which the next message cannot be received. 

    Refer to the following function defined in "mcan.c" that can be used to clear the NewData flag.

    void  MCAN_clearNewDataStatus(uint32_t                    baseAddr,
                                  const MCAN_RxNewDataStatus *newDataStatus)

    Writing 1 to the particular bit in the MCAN_NDAT1/2 register clears the bit.

    Thanks.

  • Hi Sahil

    After include "MCAN_clearNewDataStatus" according your advice, now the ISR function continue running as normal by using RX BUFF. thank you very much!