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 模块问题–Ghost 消息 ID 卡在 FIFO 中

Guru**** 2393725 points


请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1514154/tm4c1290nczad-tm4c-can-module-issue-ghost-message-id-stuck-in-fifo

器件型号:TM4C1290NCZAD

工具/软件:

大家好:

我当前正在使用 TM4C 微控制器的 CAN 模块、在多个器件之间的通信过程中遇到了一个奇怪的问题。

CAN 总线上有16个器件。 每个器件监控来自其他器件的 CAN 消息、并根据接收到的消息的 ID 确定哪些器件处于联机状态。 例如、如果器件1、2、3和4在线、则每个器件都会通过检查接收消息的器件 ID 来计算活动节点的数量。

问题如下:

如果在保持器件1、2和4连接的同时断开器件3、器件1会继续认为器件3仍在线、即使很长时间也是如此。 为了排除器件1可能会错误地将来自器件2或4的消息解释为来自器件3的可能性、我还断开了器件2和4的连接、仅保留器件1的连接状态。

令人惊讶的是、即使只有器件1位于 CAN 总线上、它仍然会继续使用器件3的 CAN ID 来接收消息。

总线上没有来自器件3的物理 CAN 消息(通过 CAN 分析仪/监听器确认)、但器件1中的中断处理程序继续接收一条消息、其中消息的 message_ID 对应于器件3。

我怀疑这可能是由于 CAN FIFO 或消息对象缓冲区未正确清除、并且中断处理程序中仍在触发旧/过时消息。

以下是我使用的 CAN 初始化配置:

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);

以下是 CAN 中断 代码:

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);
            }
        }
    }
}

我正在使用 CAN 初始化 FIFO 模式 使用MSG_OBJ_USE_FIFO标志将多个消息对象链接在一起。 例如、消息对象1至4设置为接收 FIFO 链。

在中断处理程序中、当我检测到已收到消息时、我调用:CANMessageGet (CAN0_BASE、Objid、&receivedMsg、TRUE);

我的问题是:  CANMessageGet()使用bClrPendingInt = true接收 FIFO 中断内部进行调用是否不正确?

根据我的观察、有时 FIFO 的行为似乎异常、例如似乎多次收到相同的消息、或者缓冲区中仍然存在过时的消息 ID、即使总线上没有新数据也是如此。

我怀疑这可能是由于我使用CANMessageGet() FIFO 的方式造成的。 也许以这种方式清除中断不会正确地使 FIFO 指针前进?

是否有人遇到过类似的问题、或者您是否建议如何确保 CAN 接收缓冲区或 FIFO 被正确清除以避免这种"重影"消息行为?

希望得到任何帮助!

提前感谢!

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    您好、

    您似乎 使用  MSG_OBJ_FIFO 标志设置所有消息对象(1到20)。 这是不正确的。 有关为 FIFO 模式配置 CAN 消息对象的信息、请参阅数据表。 如果使用消息对象1至20形成 FIFO、则只有最后一个消息对象可以具有 MSG_OBJ_FIFO 标志。 其他19个消息对象不能具有此标志。  

    //接收初始化
    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 FIFO 缓冲器的配置
    除了 CANIFnMCTL 寄存器中的 EOB 位外、接收消息的配置
    属于 FIFO 缓冲区的对象与单个接收消息的配置相同
    对象(参见第1357页上的"配置接收消息对象")。 连接两个或更多个串联
    消息对象转换为 FIFO 缓冲区、以及这些消息对象的标识符和掩码(如果使用)
    必须编程为匹配值。 由于消息对象的隐式优先级、因此
    具有最低消息对象编号的消息对象是 FIFO 缓冲区中的第一个消息对象。
    必须清除 FIFO 缓冲器除最后一个消息对象之外的所有消息对象的 EOB 位。 EOB
    FIFO 缓冲区最后一个消息对象的位被置位、表示它是缓冲区中的最后一个条目。

    19.3.11.2使用 FIFO 缓冲器接收消息
    所接收到的标识符与 FIFO 缓冲区匹配的消息将从消息开始存储
    具有最低消息编号的对象。 当消息存储到的消息对象时
    FIFO 缓冲区、设置该消息对象的 CANIFnMCTL 寄存器位的 NEWDAT。 来实现
    NEWDAT 清除 EOB 时、消息对象被锁定、无法被消息写入
    直到 CPU 清除 NEWDAT 位为止的处理程序。 消息会存储在 FIFO 缓冲区中、直到
    已到达此 FIFO 缓冲区的最后一个消息对象。 直到上述所有消息对象都具有
    已通过清除 NEWDAT 位来释放、此时将写入此 FIFO 缓冲区的所有后续消息
    FIFO 缓冲区的最后一个消息对象、因此覆盖之前的消息。

    19.3.11.3从 FIFO 缓冲区读取
    当 CPU 通过写入其编号从 FIFO 缓冲器传输消息对象的内容时
    对于 CANIFnCRQ 寄存器、CANIFnCMSK 寄存器中的 TXRQST 和 CLRINTPND 位应
    必须进行置位、以便在之后清除 CANIFnMCTL 寄存器中的 NEWDAT 和 INTPEND 位
    读取。 CANIFnMCTL 寄存器中这些位的值始终反映消息的状态
    更改映射目标。 为了确保 FIFO 缓冲器的正常运行、CPU 应该
    读出消息对象、从消息对象开始、消息编号最小。
    从 FIFO 缓冲区读取时、用户应该知道有新的接收到的消息
    放置在具有最低消息编号的消息对象中、该编号是的 NEWDAT 位
    CANIFnMCTL 寄存器清零。 因此、FIFO 中接收到的消息的顺序并非
    有保证。 第1360页的图19-3显示了如何连接一组消息对象
    缓冲区的信号由 CPU 处理。