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.

TMS320F28377S: CAN slave cannot receive the specified ID data

Part Number: TMS320F28377S
Other Parts Discussed in Thread: C2000WARE

Master&Slave devices: F28377S

baudrate: 500kHz

The master sends a frame of data to the slave every 1ms, with a length of 5 bytes.

The slave uses interrupt method to receive data from the master. At the beginning, the slave received normally. After a period of time, the slave cannot receive data(only specified ID) from the master. The interval is not fixed, and the slave sometimes works normally for a long time.

The connection between master and slave is normal.

After the error occurs, use the CAN tool to send data of other frame IDs to the slave, and the slave can receive it normally.

It can also be detected that the data sent by the master with this specified frame ID comes out.

Use the CAN tool to send data with this specified ID, and the slave cannot receive it.

// ====================================================================
// === 1. 主函数初始化部分 ============================================
// ====================================================================
void main(void)
{
    //
    // Initialize the CAN controllers
    //
    CANInit(CANA_BASE);

    //
    // Setup CAN to be clocked off the PLL output clock
    //
    CANClkSourceSelect(CANA_BASE, 0);

    //
    // Set up the CAN bus bit rate to 500kHz for each module
    // This function sets up the CAN bus timing for a nominal configuration.
    // You can achieve more control over the CAN bus timing by using the
    // function CANBitTimingSet() instead of this one, if needed.
    // Additionally, consult the device data sheet for more information about
    // the CAN module clocking.
    //
    CANBitRateSet(CANA_BASE, 200000000, 500000);
//    CANBitRateSet(CANA_BASE, 200000000, 1000000);

    //
    // Enable interrupts on the CAN A peripheral.
    //
//    CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS);
    CANIntEnable(CANA_BASE, CAN_INT_MASTER | CAN_INT_ERROR);

    // Enable AutoBusOn
    CAN_enableAutoBusOn(CANA_BASE);
    CAN_setAutoBusOnTime(CANA_BASE, 100000);
    CAN_disableRetry(CANA_BASE);
    //
    // Enable the CAN-A interrupt signal
    //
    CANGlobalIntEnable(CANA_BASE, CAN_GLB_INT_CANINT0);

    CanObjInit();

    //
    // Start CAN module A operations
    //
    CANEnable(CANA_BASE);
}

// ====================================================================
// === 2. 主机DSP CanObjInit()初始化配置邮箱,及发送程序  =============
// ====================================================================
void CanObjInit()
{
    // 两DSP CAN通信,发送
    sTXCANMsgDspComm01.ui32MsgID = 0x0C100201;
    sTXCANMsgDspComm01.ui32MsgIDMask = 0;
    sTXCANMsgDspComm01.ui32Flags = 0;
    sTXCANMsgDspComm01.ui32MsgLen = 5;
    sTXCANMsgDspComm01.pucMsgData = TxMsgDspCommData01;
}


// ====== 发送部分程序,1ms发送1次 =====================================
    // 发送给从机电流设定值
    TxMsgDspCommData01[0] = ((int)(onGridCloseLoopIdref * 100) & 0x00FF);
    TxMsgDspCommData01[1] = ((int)(onGridCloseLoopIdref * 100) & 0xFF00) >> 8;
    TxMsgDspCommData01[2] = ((int)(onGridCloseLoopIqref * 100) & 0x00FF);
    TxMsgDspCommData01[3] = ((int)(onGridCloseLoopIqref * 100) & 0xFF00) >> 8;
    TxMsgDspCommData01[4] = 0;
    CANMessageSet(CANA_BASE, 4, &sTXCANMsgDspComm01, MSG_OBJ_TYPE_TX);

// ====================================================================
// === 3. 从机DSP CanObjInit()初始化配置邮箱,及接收程序  =============
// ====================================================================
void CanObjInit()
{
    // 两DSP CAN通信,接收
    sRXCANMsgDspComm01.ui32MsgID = 0x0C100201;
    sRXCANMsgDspComm01.ui32MsgIDMask = 0;
    sRXCANMsgDspComm01.ui32Flags = MSG_OBJ_RX_INT_ENABLE;
    sRXCANMsgDspComm01.ui32MsgLen = 5;
    sRXCANMsgDspComm01.pucMsgData = RxMsgDspCommData01;
    CANMessageSet(CANA_BASE, 15, &sRXCANMsgDspComm01, MSG_OBJ_TYPE_RX);
}

// ======== 在中断中接收主机发送过来的数据(status = 15时接收该帧  ) ============================
#if (G9_5PL != 0)
__interrupt void CANA0_ISR(void)    // CAN-A
{
    // Set interrupt priority:
    volatile Uint16 TempPIEIER = PieCtrlRegs.PIEIER9.all;
    IER |= M_INT9;
    IER    &= MINT9;                         // Set "global" priority
    PieCtrlRegs.PIEIER9.all &= MG9_5;   // Set "group"  priority
    PieCtrlRegs.PIEACK.all = 0xFFFF;   // Enable PIE interrupts
    __asm("  NOP");
    EINT;

    uint32_t status;

    //
    // Read the CAN-A interrupt status to find the cause of the interrupt
    //
    status = CANIntStatus(CANA_BASE, CAN_INT_STS_CAUSE);

    //
    // If the cause is a controller status interrupt, then get the status
    //
    if(status == CAN_INT_INT0ID_STATUS)
    {
//        DSP_OUT1_TOGGLE;

        //
        // 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 = CANStatusGet(CANA_BASE, CAN_STS_CONTROL);

        //
        // Check to see if an error occurred.
        //
//        if(((status  & ~(CAN_ES_RXOK)) != 7) &&
//           ((status  & ~(CAN_ES_RXOK)) != 0))
//        if(((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK | CAN_ES_BOFF)) != 7) &&
//           ((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK | CAN_ES_BOFF)) != 0))
        if(((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK)) != 7) &&
           ((status  & ~(CAN_ES_RXOK | CAN_ES_TXOK)) != 0))
        {
            //
            // Set a flag to indicate some errors may have occurred.
            //
            errorFlag = 1;   // 调试
            CanConfigInit();
//            DSP_OUT1_TOGGLE;   // 调试
        }
    }
    else if(status == 15)
    {
        DSP_OUT1_TOGGLE;

        errorFlag = 0;
        CanReceiveDsp01();

        CANIntClear(CANA_BASE, 15);
    }
    else if(status == 16)
    {
        CanReceiveDsp02();

        CANIntClear(CANA_BASE, 16);
    }
    else if(status == 17)
    {
//        DSP_OUT1_TOGGLE;   // 调试

        CanReceiveDsp03();

        CANIntClear(CANA_BASE, 17);
    }
    //
    // Check if the cause is the CAN-A receive message object 1
    //
    else if(status == 25)
    {
        //
        // Get the received message
        //
//        CANMessageGet(CANA_BASE, 2, &sRXCANMsgChkInfo, true);

        CanReceiveSrhInfo();

        //
        // Getting to this point means that the RX interrupt occurred on
        // message object 1, and the message RX is complete.  Clear the
        // message object interrupt.
        //
        CANIntClear(CANA_BASE, 25);

        //
        // Increment a counter to keep track of how many messages have been
        // received. In a real application this could be used to set flags to
        // indicate when a message is received.
        //
//        rxMsgCount++;

        //
        // Since the message was received, clear any error flags.
        //
//        errorFlag = 0;
    }
    else if(status == 26)
    {
        CanReceiveRdSet();

        CANIntClear(CANA_BASE, 26);
    }
    else if(status == 27)
    {
        CanReceiveCtlSet();

        CANIntClear(CANA_BASE, 27);
    }
    else if(status == 28)
    {
        CanReceiveParaSet();

        CANIntClear(CANA_BASE, 28);
    }

    //
    // If something unexpected caused the interrupt, this would handle it.
    //
    else
    {
        //
        // Spurious interrupt handling can go here.
        //
//        errorFlag = 2;   // 调试
    }

    //
    // Clear the global interrupt flag for the CAN interrupt line
    //
    CANGlobalIntClear(CANA_BASE, CAN_GLB_INT_CANINT0);


    //
    // Restore registers saved:
    //
    DINT;
    PieCtrlRegs.PIEIER9.all = TempPIEIER;
}
#endif

--

Thanks & Regards

  • Yale,

                Since it works correctly for a period of time, we cannot suspect the interrupt initialization or configuration. Looking through the code, it appears acceptance mask filtering is not used. If true, a separate message object is being configured for every one of the messages transmitted on the bus. What could be happening is that the interrupts are not being serviced promptly leading to the impression that messages are being lost. If masking is not used and the message object is retaining the correct MSGID (ARBID), it will receive a transmitted message. It cannot suddenly stop receiving messages.

  • Hi Hareesh,

    What could be happening is that the interrupts are not being serviced promptly leading to the impression that messages are being lost.

    What would cause the interrupt program to not be serviced in time?

    If masking is not used and the message object is retaining the correct MSGID (ARBID), it will receive a transmitted message. It cannot suddenly stop receiving messages.

    The mask in the program is un-used and the MSGID (ARBID) is not changed.

    How to further locate the issues?

    --

    Thanks & Regards

  • What would cause the interrupt program to not be serviced in time?

    If the application is "busy" doing something else, it may not service the interrupt on time, leading to messages being lost. Please have customer check the MsgLst (Receive Message Lost) bit for the suspected message object. If a message was indeed over-written (because it was not read in time by the software), this bit would be set. 

    How to further locate the issues?

    As emphasized before, this is not a hardware issue. The application could either configure more message objects for receive or otherwise ensure that CAN interrupts are serviced on time.

  • If a message was indeed over-written (because it was not read in time by the software), this bit would be set.

    After the message is rewritten and lost, will the errored message object never receive data?

    The application could either configure more message objects for receive or otherwise ensure that CAN interrupts are serviced on time.

    Can I use two different message objects to receive data for the same ID?

    --

    Thanks & Regards

  • After the message is rewritten and lost, will the errored message object never receive data?

    No, the fact that a message was overwritten before being read should not prevent that message object from receiving future messages.

    Can I use two different message objects to receive data for the same ID?

    Only if the message objects are part of a FIFO. Otherwise, the numerically least message object will be overwritten again and again. This is explained in 

    8.2 Basic Reception Process in page 21 of www.ti.com/lit/SPRAD59

  • The problem my customer is facing now is that the message object is no longer receiving messages. Can they solve the problem by configuring it into FIFO receive mode?

  • Can they solve the problem by configuring it into FIFO receive mode?

    No, customer should get to the root of the problem and understand why messages are not being received. Just configuring a FIFO will not magically solve the issue. The underlying mechanism of Message object reception does not change simply because it is now part of a FIFO. As mentioned before, a Message object cannot suddenly stop receiving messages. Either the expected message was not transmitted at all. Or if it was transmitted, the Receive Message Object configuration somehow changed. Customer needs to double-check the configuration of the receive Message object.

  • Please have customer check the MsgLst (Receive Message Lost) bit for the suspected message object. If a message was indeed over-written (because it was not read in time by the software), this bit would be set.

    They checked the MsgLst bit in the following method and found that when the slave could not receive data from the master, the MsgLst of the slave error message object was not set.

    if( (sRXCANMsgDspComm05.ui32Flags & MSG_OBJ_DATA_LOST) == 1)
    {
    systemFault.bit.DebugFault = 1;    // Send to the upper computer for observation
    }

    What other debugging can they do?

  • Yale,

                Customer can disable all interrupts in their system except CAN interrupts. If the problem goes away, it is definitely a case of interrupts not being serviced soon enough. 

    Customer can also try Driverlib from the latest C2000ware. 

    As stated before, this is a code issue. It is hard to debug issues like this remotely, without access to the H/W or S/W. I regret I cannot help further on this.