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.

TM4C123BH6PM: Lost CAN massage object

Part Number: TM4C123BH6PM

Hi Team

 

The customer use CAN module and has the following problem.

They set three objects (30, 31, 32) by Tivaware CANMessageSet. But Only the massage object 32 is transmitted.

However, if they leave the interval between CANMessageSet executions by debugging or set wait cycles, all three massage objects are sent correctly.

 

Do you have any suggestion for this problem?

 

Here is the code.

*****************

#define TXOBJECT_ST             30

#define TXOBJECT_END           32

 

uint8_t                               g_ui8CAN0TXMsgData[3][8];

tCANMsgObject      g_sCAN0TxMessage[3];

 

int main(void)

{

   uint32_t mno;

   uint32_t count, s_count;

   uint32_t status;

 

   // massage Initialization

   g_sCAN0TxMessage[0].ui32MsgIDMask = 0;

   g_sCAN0TxMessage[0].pui8MsgData = (uint8_t *)(&g_ui8CAN0TXMsgData[0][0]);

   g_sCAN0TxMessage[1].ui32MsgIDMask = 0;

   g_sCAN0TxMessage[1].pui8MsgData = (uint8_t *)(&g_ui8CAN0TXMsgData[1][0]);

   g_sCAN0TxMessage[2].ui32MsgIDMask = 0;

   g_sCAN0TxMessage[2].pui8MsgData = (uint8_t *)(&g_ui8CAN0TXMsgData[2][0]);

 

   //data TX process

   for(count=0; count<10; count++){

       for(s_count=TXOBJECT_ST; s_count <= TXOBJECT_END; s_count++){

           mno = s_count - TXOBJECT_ST;

           g_ui8CAN0TXMsgData[mno][0] = count*3 + mno;

           g_ui8CAN0TXMsgData[mno][1] = count*3 + mno;

           g_ui8CAN0TXMsgData[mno][2] = count*3 + mno;

           g_ui8CAN0TXMsgData[mno][3] = count*3 + mno;

           g_ui8CAN0TXMsgData[mno][4] = count*3 + mno;

           g_ui8CAN0TXMsgData[mno][5] = count*3 + mno;

           g_ui8CAN0TXMsgData[mno][6] = count*3 + mno;

           g_ui8CAN0TXMsgData[mno][7] = count*3 + mno;

           g_sCAN0TxMessage[mno].ui32MsgID = 0x10000000 + count*3 + mno;

           g_sCAN0TxMessage[mno].ui32MsgLen = 8;

           CANMessageSet(CAN0_BASE, s_count, &g_sCAN0TxMessage[mno], MSG_OBJ_TYPE_TX);

       }

       while(1){

           status = (CANStatusGet(CAN0_BASE, CAN_STS_TXREQUEST) & 0xE0000000);

           if(status == 0){

               break;

          }

       }

   }

 

}

*****************

 

Thanks and Best regards,

Kuerbis

  • Hi Kuerbis,

      I have forwarded your post to our CAN expert. 

  • I cannot reproduce your problem. Do you have a full CAN network? Are you receiving an ACK from another node on the network?

    I took your code and added the CAN initialization and made a network with one other node that acts as a receiver of each message. Here is a logic analyzer trace of the CAN messages being sent.

    and continuing:

    My logic analyzer was able to capture the start of the 16th frame before it ran out of sample memory:

    I have attached a .zip file that contains two projects. "multipleCanMessages" contains your code and is for the device transmitting. "simple_can_rx" is for the device receiving.

    multipleCANMessages.zip

  • I am a customer to ask this problem.
    Thank you for your support.

    I investigated the difference between your project and my project.
    As a result, the following settings caused this problem.

    *****************

    CANRetrySet(CAN0_BASE, false);

    *****************

    Please comment this problem.

    Best regards,
    Yuzo

  • From the TivaWare Peripheral Driver Library User's Guide page 87:

    If your code is behaving differently because you disabled automatic retransmission on errors, they you are getting errors on your CAN bus. Look at the signals on your CAN bus with a logic analyzer or scope.

  • I looked at the signals on my CAN bus.
    If setting "CANRetrySet" is true, this problem has been resolved.
    But, then setting "CANRetrySet" is false, this problem has not been resolved.

    Could you set "CANRetrySet" is false on your testing environment, please?

    Best regards,
    Yuzo

  • If the transmitting node starts before the receiving node and CANRetry is set to false, the original messages will be lost. Retries are enabled by default. There is no reason to disable retry. The CAN protocol has a robust error detection and recovery method. Here is a more detailed explanation of the CAN bus with a discussion of error checking and fault confinement starting on page 6.

    https://www.ti.com/lit/an/sloa101b/sloa101b.pdf

    I am on holiday for the rest of this week. If you need urgent help, please start a new thread by clicking the "Ask a related question" button.

  • Our product's spec need retries, because our product do not use standard CAN protocol. Our product arrange CAN protocol a little.

    Do you mean, if CANRetry is set to false, i can not set three objects (30, 31, 32) by Tivaware CANMessageSet?

    Best regards,
    Yuzo

  • It the CAN message sent by the TM4C123 device is not received because some other device on the bus is using a modified protocol and CANRetry is false, the message will not be sent again. You should get logic analyzer images of the CAN bus traffic to diagnose what is happening in your system.

  • If setting "CANRetrySet" is true,

    If setting "CANRetrySet" is false,

    I can not understand, why CAN massage object lost.

    Please comment this problem.

    Best regards,
    Yuzo

  • This yellow line is CANH, this green line is CANL, and these yellow numbers are CANID from CAN protocol analyzer.

  • I am able to reproduce your issue by disabling auto-retry. I admit that this behavior perplexes me. It is as though the CAN state-machine is failing to properly arbitrate pending messages for transmission. Is there a reason you must disable auto-retry?

  • I need disable auto-retry, because our system spec. Our system accept ack error only one shot using disable auto-retry. We chose TM4C123BH6PM, because it can disable auto-retry. That’s disappointing, if it can not disable auto-retry.

    I Would like to confirm, if only one object CANMessage for trancemitted, can i use disable auto-retry?

  • When sending only one object at a time with Auto-retry disabled the TXREQ bit does not get set. Therefore you cannot use it to determine when to check the error bits or when to try again. By adding a 2mS software delay, I can send a single frame with auto-retry disabled and then check if the frame was acknowledged or not. Here is a logic analyzer shot of sending 10 frames with a 2mS delay.

    Here is an enlargement showing the end of the first frame. The missing ACK bit is circled in red.

    The CAN_STS register shows the last error was 3, missing ACK. The CAN_ERR shows a count of 5 receive errors.

    I can see how this might be used when trying to identify the baudrate of an unknown CAN bus, but I do not know how it will repsond with other traffic on the bus.

  • Do you mean, if i use Auto-retry disabled, I must use fixed-cycle operation with a timer?

    If so, I wonder.
    I can use sending only one object at a time with Auto-retry disabled, using TXREQ bit check .
    Am I using it incorrectly?

  • With auto-retry disabled, I was not able to use TXREQ bit to determine if the previous transmission had be sent. 

  • Here is the code.

    *****************

    #define TXOBJECT_ST             30

    #define TXOBJECT_END           32

     

    uint8_t                               g_ui8CAN0TXMsgData[3][8];

    tCANMsgObject      g_sCAN0TxMessage[3];

     

    int main(void)

    {

       uint32_t mno;

       uint32_t count, s_count;

       uint32_t status;

     

       // massage Initialization

       g_sCAN0TxMessage[0].ui32MsgIDMask = 0;

       g_sCAN0TxMessage[0].pui8MsgData = (uint8_t *)(&g_ui8CAN0TXMsgData[0][0]);

     

       //data TX process

      for(count=0; count<10; count++){
        g_ui8CAN0TXMsgData[0][0] = count;
        g_ui8CAN0TXMsgData[0][1] = count;
        g_ui8CAN0TXMsgData[0][2] = count;
        g_ui8CAN0TXMsgData[0][3] = count;
        g_ui8CAN0TXMsgData[0][4] = count;
        g_ui8CAN0TXMsgData[0][5] = count;
        g_ui8CAN0TXMsgData[0][6] = count;
        g_ui8CAN0TXMsgData[0][7] = count;
        g_sCAN0TxMessage[0].ui32MsgID = 0x10000000 + count;
        g_sCAN0TxMessage[0].ui32MsgLen = 8;
        CANMessageSet(CAN0_BASE, TXOBJECT_ST, &g_sCAN0TxMessage[0], MSG_OBJ_TYPE_TX);
        while(1){
          status = (CANStatusGet(CAN0_BASE, CAN_STS_TXREQUEST) & 0x20000000);
          if(status == 0){
            break;
          }
          else{
            status = 0; //test
          }
        }
     }

    *****************

    Here is the CAN signal and  CANID.

    The "while(1)" code is wait process using TXREQ.
    If I cut off "while(1)" code. The CAN signal and CANID is here.

    In this result, I was able to use TXREQ bit to determine if the previous transmission had be sent. 

    Will you check it again?

  • I am still not able to read the TXREQUEST bit as set. I tried different optimization levels with no change. Here is my project. Perhaps you did something different in your CAN configuration. I have attached my project.

    1513.multipleCANMessages.zip