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.

CAN message transmitted with wrong ArbID

Other Parts Discussed in Thread: TMS570LS3137, HALCOGEN

I'm having a strange problem with CAN on the TMS570LS3137. Distilled to the simplest terms, I have one message box transmitting a variety of message IDs. Very rarely a message is transmitted with the correct data, but the ID from the previous transmission.

This fictitious data reflects what I have seen with both a CAN analyzer and scope:

ID         Data
08000000   00 00 00 00 00 00 00 00
08000001   00 00 00 00 00 00 00 01
08000002   00 00 00 00 00 00 00 02
08000002   00 00 00 00 00 00 00 03  <- Data is correct, but ID should have been 08000003
08000004   00 00 00 00 00 00 00 04

My driver code is based on the Halcogen's canTransmit(), but modified so that ArbID and Length are updated each transmission.

/* Abort if pending message */
if ((node->TXRQx[regIndex] & bitIndex) != 0U)
{
    success = 0U;
}
else
{
    while ((node->IF1STAT & 0x80U) == 0x80U) { }  /* Wait for IF ready */
    
    node->IF1CMD = 0xB7u;                /* Write DATA, ARB & MCTL */
    node->IF1MCTL = 0x0880 | length;     /* E0B, TxIE & length */
    node->IF1ARB = 0xE0000000 | can_id;  /* Msg Valid, Xtd, Transmit & CAN ID  */      

    my_test[i_test].id = node->IF1ARB & 0x1FFFFFFFU;  /*  Diagnostic only!  */
    my_test[i_test].data = *(uint64_t *)data;         /*  Diagnostic only!  */
    if (i_test < MAX_TEST) { i_test++; }              /*  Diagnostic only!  */ 
    
    /* Copy TX data into IF1, converting from big endian CPU mode to little endian
     * peripheral registers. */
    for (i = 0U; i < length; i++)
    {
        node->IF1DATx[kCanByteOrder[i]] = *data;
        data++;
    }
    
    node->IF1NO = (uint8)message_box;   /* This write initiates IF transfer */

    success = 1U;
}

With the addition of some diagnostic code I have verified that the correct ArbID and data are always loaded into the DCAN registers.

One pattern I have noticed is that the problem only occurs when there are other transmitters on the bus  and arbitration is occurring. But the priority of the message does not seem to matter-- it occurs equally with very high IDs and very low  IDs.

To summarize: I update  MCTL, ARB and DATA with every transmission, but intermittently it appears as though the ARB was not updated.

I appreciate any and all advice.

  • Hi,

    The reason for observed behavior is:

    -08000002 is put into can mailbox by canTransmit().

    -08000003 is now requested for transmission through canTransmit(). After 0xB7 is written in to node->IF1CMD(code in line number 10 is executed), an interrupt is triggered because 08000002 is transmitted from mail box. Control now goes to CAN ISR.

    -In ISR, node->IF1CMD is updated with 0x87. Once control comes back to canTransmit(), IF1CMD is now 0x87 instead of 0xB7. Because of this, the arbitration field is not moved from IF1 to mail box. Only the data is moved and a transmission is triggered with old ID in CAN mail box. 

    To overcome this problem, you can modify the ISR to write 0xB7 instead of 0x87.

  • Perfect! I have confirmed your suggestion fixed the problem. Thank you so much.

    -Bryan