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.

TM4C1290NCZAD: TM4C CAN Module Issue – Ghost Message ID Stuck in FIFO

Part Number: TM4C1290NCZAD

Tool/software:

Hello everyone,

I'm currently working with the CAN module of the TM4C microcontroller, and I've encountered a strange issue during communication between multiple devices.

There are 16 devices on the CAN bus. Each device monitors CAN messages from other devices and determines which devices are online based on the IDs of the received messages. For example, if devices 1, 2, 3, and 4 are online, each device counts the number of active nodes by checking which device IDs it receives messages from.

Here's the problem:

If I disconnect device 3 while keeping devices 1, 2, and 4 connected, device 1 continues to believe that device 3 is still online, even for an extended period. To rule out the possibility that device 1 might be mistakenly interpreting messages from device 2 or 4 as coming from device 3, I also disconnected devices 2 and 4, leaving only device 1 connected.

Surprisingly, even when only device 1 is on the CAN bus, it still keeps receiving messages with the CAN ID of device 3.

There is no physical CAN message from device 3 on the bus (confirmed with a CAN analyzer/sniffer), yet the interrupt handler in device 1 continues to receive a message with message_ID corresponding to device 3.

I suspect that this might be due to the CAN FIFO or message object buffer not being cleared correctly, and old/stale messages are still being triggered in the interrupt handler.

Below is the CAN initialization configuration I'm using:

CAN Init Code

    CANInit(CAN0_BASE); // Initialize the CAN controller
    CANBitRateSet(CAN0_BASE, g_ui32SysClock, ui32BitRate); // Set up the bit rate for the CAN bus.

    CANIntEnable(CAN0_BASE, CAN_INT_MASTER | CAN_INT_ERROR | CAN_INT_STATUS); // Enable interrupts on the CAN peripheral.
    IntEnable(INT_CAN0);    // Enable the CAN interrupt on the processor (NVIC).
    CANEnable(CAN0_BASE);      // Enable the CAN for operation.

    //接收初始化
    sCANMessage.ui32MsgID = 0;
    sCANMessage.ui32MsgIDMask = 0;
 
    sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER|MSG_OBJ_FIFO);
    sCANMessage.ui32MsgLen = 8;

	// MsgBox1-20 is Rx, MsgBox21-30 is TX
	for(i=1;i<=(CANMaxRXObject-1);i++)
	{
		CANMessageSet(CAN0_BASE, i, &sCANMessage, MSG_OBJ_TYPE_RX);
	}

	sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER);
	CANMessageSet(CAN0_BASE, CANMaxRXObject, &sCANMessage, MSG_OBJ_TYPE_RX);

Below is the CAN Interrupt  code:

void CAN0IntHandler(void)
{
    uint32_t status;
    uint8_t i = 0;
    uint8_t dataBuffer[8] = {0};
    tCANMsgObject receivedMsg;

    // Get the interrupt status
    status = CANIntStatus(CAN0_BASE, CAN_INT_STS_CAUSE);

    // Handle controller status interrupt
    if (status == CAN_INT_INTID_STATUS)
    {
        status = CANStatusGet(CAN0_BASE, CAN_STS_CONTROL);
    }

    // Check if the interrupt is from a receive message object
    if (status <= MAX_RX_OBJECT)
    {
        for (i = 1; i <= MAX_RX_OBJECT; i++)
        {
            if (status == i)
            {
                CANIntClear(CAN0_BASE, i);
                g_rxFlag = 1;
                receivedMsg.pui8MsgData = dataBuffer;
                CANMessageGet(CAN0_BASE, i, &receivedMsg, true);
                ProcessCANMessage(receivedMsg);  // User-defined message processing
            }
        }
    }
    else
    {
        // Clear interrupts for other message objects (e.g., transmit objects)
        for (i = 9; i <= 32; i++)
        {
            if (status == i)
            {
                CANIntClear(CAN0_BASE, i);
            }
        }
    }
}

In my CAN initialization, I'm using FIFO mode by linking multiple message objects together using the MSG_OBJ_USE_FIFO flag. For example, message objects 1 through 4 are set up as a receive FIFO chain.

In my interrupt handler, when I detect a message has been received, I call:CANMessageGet(CAN0_BASE, objID, &receivedMsg, true);

My question is: Is it incorrect to call CANMessageGet() with bClrPendingInt = true inside a receive FIFO interrupt?

From my observation, sometimes the FIFO seems to behave abnormally — such as the same message appearing to be received multiple times, or stale message IDs remaining in the buffer even when no new data is on the bus.

I suspect this may be caused by the way I’m using CANMessageGet() with FIFO. Perhaps clearing the interrupt this way doesn't properly advance the FIFO pointer?

Has anyone experienced a similar issue, or do you have suggestions on how to ensure the CAN receive buffer or FIFO is properly cleared to avoid this kind of "ghost" message behavior?

Any help would be appreciated!

Thanks in advance!

  • Hi,

    You seem to set all message objects (1 to 20) with the MSG_OBJ_FIFO flag. This is not correct. Please refer to the datasheet for configuring the CAN message objects for FIFO mode. If you are forming a FIFO using message objects 1 to 20 then only the last message object can have the MSG_OBJ_FIFO flag. The other 19 message objects cannot have this flag. 

    //接收初始化
    sCANMessage.ui32MsgID = 0;
    sCANMessage.ui32MsgIDMask = 0;

    sCANMessage.ui32Flags = (MSG_OBJ_RX_INT_ENABLE | MSG_OBJ_USE_ID_FILTER|MSG_OBJ_FIFO);
    sCANMessage.ui32MsgLen = 8;

    // MsgBox1-20 is Rx, MsgBox21-30 is TX
    for(i=1;i<=(CANMaxRXObject-1);i++)
    {
    CANMessageSet(CAN0_BASE, i, &sCANMessage, MSG_OBJ_TYPE_RX);
    }

    19.3.11.1 Configuration of a FIFO Buffer
    With the exception of the EOB bit in the CANIFnMCTL register, the configuration of receive message
    objects belonging to a FIFO buffer is the same as the configuration of a single receive message
    object (see “Configuring a Receive Message Object” on page 1357). To concatenate two or more
    message objects into a FIFO buffer, the identifiers and masks (if used) of these message objects
    have to be programmed to matching values. Due to the implicit priority of the message objects, the
    message object with the lowest message object number is the first message object in a FIFO buffer.
    The EOB bit of all message objects of a FIFO buffer except the last one must be cleared. The EOB
    bit of the last message object of a FIFO buffer is set, indicating it is the last entry in the buffer.

    19.3.11.2 Reception of Messages with FIFO Buffers
    Received messages with identifiers matching to a FIFO buffer are stored starting with the message
    object with the lowest message number. When a message is stored into a message object of a
    FIFO buffer, the NEWDAT of the CANIFnMCTL register bit of this message object is set. By setting
    NEWDAT while EOB is clear, the message object is locked and cannot be written to by the message
    handler until the CPU has cleared the NEWDAT bit. Messages are stored into a FIFO buffer until the
    last message object of this FIFO buffer is reached. Until all of the preceding message objects have
    been released by clearing the NEWDAT bit, all further messages for this FIFO buffer are written into
    the last message object of the FIFO buffer and therefore overwrite previous messages.

    19.3.11.3 Reading from a FIFO Buffer
    When the CPU transfers the contents of a message object from a FIFO buffer by writing its number
    to the CANIFnCRQ register, the TXRQST and CLRINTPND bits in the CANIFnCMSK register should
    be set such that the NEWDAT and INTPEND bits in the CANIFnMCTL register are cleared after the
    read. The values of these bits in the CANIFnMCTL register always reflect the status of the message
    object before the bits are cleared. To assure the correct function of a FIFO buffer, the CPU should
    read out the message objects starting with the message object with the lowest message number.
    When reading from the FIFO buffer, the user should be aware that a new received message is
    placed in the message object with the lowest message number for which the NEWDAT bit of the
    CANIFnMCTL register is clear. As a result, the order of the received messages in the FIFO is not
    guaranteed. Figure 19-3 on page 1360 shows how a set of message objects which are concatenated
    to a FIFO Buffer can be handled by the CPU.