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.

[参考译文] CC2674R10:TCAN455X 驱动程序:TCAN455X_handleRxFIFO ()是否正确使用 MCAN_setRxFIFOAck ()?

Guru**** 2392905 points
Other Parts Discussed in Thread: TCAN4550, SYSCONFIG

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

https://e2e.ti.com/support/wireless-connectivity/other-wireless-group/other-wireless/f/other-wireless-technologies-forum/1508573/cc2674r10-tcan455x-driver-is-tcan455x_handlerxfifo-using-mcan_setrxfifoack-correctly

器件型号:CC2674R10
主题中讨论的其他器件:TCAN4550SysConfig

工具/软件:

大家好!

通过 SPI 对 TCAN455X 使用 simplelink_cc13xx_cc26xx_SDK_7_40_00_77可以驱动程序

我们在接收消息时遇到了问题:收到的消息经常会被复制,很少会丢失。

我的意思是"重复"是指 TCAN455X_taskFxn ()通过 TCAN455X_handleRxFIFO ()从 RX FIFO 两次读取同一条消息。
CAN 分析器显示该消息仅在总线上发送一次、因此必须在芯片或其驱动程序中进行复制。

更仔细地看 TCAN455X_handleRxFIFO ():

static void TCAN455X_handleRxFIFO(CAN_Handle handle, uint32_t fifoNum)
{
    CAN_Object *object           = (CAN_Object *)handle->object;
    MCAN_RxFIFOStatus fifoStatus = {0};

    MCAN_getRxFIFOStatus(fifoNum, &fifoStatus);

    if ((fifoStatus.fillLvl > 0U) && !TCAN455X_isRxStructRingBufFull(handle))
    {
        MCAN_readRxMsg(MCAN_MEM_TYPE_FIFO, fifoNum, &rxElem);
        /* Return value can be ignored since ring buffer is not full */
        (void)StructRingBuf_put(&object->rxStructRingBuf, &rxElem);

        fifoStatus.fillLvl--;

        while ((fifoStatus.fillLvl > 0U) && !TCAN455X_isRxStructRingBufFull(handle))
        {
            MCAN_readRxMsg(MCAN_MEM_TYPE_FIFO, fifoNum, &rxElem);
            /* Return value can be ignored since ring buffer is not full */
            (void)StructRingBuf_put(&object->rxStructRingBuf, &rxElem);

            fifoStatus.fillLvl--;
            fifoStatus.getIdx++;

            /* Check for rollover */
            if (fifoStatus.getIdx >= object->rxFIFONum[fifoNum])
            {
                fifoStatus.getIdx = 0U;
            }
        }
    }

    /* Return value can be ignored since the inputs are known to be valid */
    (void)MCAN_setRxFIFOAck(fifoNum, fifoStatus.getIdx);
}


我们看到了2个潜在问题:

1.调用 MCAN_setRxFIFOCK()、即使消息未从 FIFO 中读取、因为 if 子句中的 TCAN455X_isRxStructRingBufull()、即默默地丢弃消息。 这是有意的吗?

2. 即使读取了多条消息、也只调用一次 MCAN_setRxFIFOCK()。 当索引在 while 循环中回滚时、这似乎不起作用。

我们现在修改了 TCAN455X_handleRxFIFO()、以便在阅读后立即对每条消息进行确认、这似乎已经解决了问题:
(删除 if 子句、保留 while 循环、并将 MCAN_setRxFIFOAck ()移入循环)

static void TCAN455X_handleRxFIFO(CAN_Handle handle, uint32_t fifoNum)
{
    CAN_Object *object           = (CAN_Object *)handle->object;
    MCAN_RxFIFOStatus fifoStatus = {0};

    MCAN_getRxFIFOStatus(fifoNum, &fifoStatus);

    while ((fifoStatus.fillLvl > 0U) && !TCAN455X_isRxStructRingBufFull(handle))
    {
        MCAN_readRxMsg(MCAN_MEM_TYPE_FIFO, fifoNum, &rxElem);
        /* Return value can be ignored since ring buffer is not full */
        (void)StructRingBuf_put(&object->rxStructRingBuf, &rxElem);

        /* Return value can be ignored since the inputs are known to be valid */
        (void)MCAN_setRxFIFOAck(fifoNum, fifoStatus.getIdx);

        fifoStatus.fillLvl--;
        fifoStatus.getIdx++;

        /* Check for rollover */
        if (fifoStatus.getIdx >= object->rxFIFONum[fifoNum])
        {
            fifoStatus.getIdx = 0U;
        }
    }
}

由于额外的 ACK、fillLvl > 1时可能会造成性能损失、但 OTOH 我们现在会提前确认、因此 TCAN4550可以立即重新使用 FIFO 位置。 这极大地降低了最大 观察到的文件级别

这里的部分问题是 TCAN455X+MCAN+SPI 驱动程序效率非常低、无法以500kbit/s 的高总线负载接收所有消息:大约需要450µs 来处理1条 Rx 消息、但总线可以每个200µs 传输一条消息、即很容易地溢出 TCAN455X 驱动程序。

此致、
Wolfgang

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

    尊敬的 Wolfgang:

    感谢您的全面分析。  我已将您的观察结果通知 TI 驱动程序开发团队、并将在答复可用时告知他们。   

    此致、
    Ryan

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

    您好、Wolfgang、

    TI 驱动程序团队的回复:

    如果振铃缓冲区已满、我们会故意丢弃消息、因为没有复制消息的位置、并且 Rx IRQ 将被清除。  在 SysConfig 中、Rx 环形缓冲器的大小必须适当、具体取决于清空环形缓冲器的速度以及接收消息的速度。  

     关于:" 即使读取了多条消息、也只调用一次 MCAN_setRxFIFOAck ()。 当索引在 while 循环中回滚时、这似乎不起作用。"   已提交错误 TT 以进行此更改。

    TCAN455X 使用 SPI 接口、因此由于接口开销要求、固有速度很慢。  对于支持的器件(8或12MHz)、SPI 速度最大。  如果需要处理高消息负载、开发人员应使用具有集成 CAN 控制器(如 CC2745)的器件。

    我希望这对您有所帮助、
    Ryan

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

    更改了代码、以便在振铃缓冲区已满时丢弃 Rx 消息:

    static void TCAN455X_handleRxFIFO(CAN_Handle handle, uint32_t fifoNum)
    {
        CAN_Object *object           = (CAN_Object *)handle->object;
        MCAN_RxFIFOStatus fifoStatus = {0};
    
        MCAN_getRxFIFOStatus(fifoNum, &fifoStatus);
    
        while (fifoStatus.fillLvl > 0U)
        {
            if (!TCAN455X_isRxStructRingBufFull(handle))
            {
                MCAN_readRxMsg(MCAN_MEM_TYPE_FIFO, fifoNum, &rxElem);
                /* Return value can be ignored since ring buffer is not full */
                (void)StructRingBuf_put(&object->rxStructRingBuf, &rxElem);
            }
            else
            {
                // discard the message; TCAN455X_isRxStructRingBufFull() has already counted this
            }
    
            /* Return value can be ignored since the inputs are known to be valid */
            (void)MCAN_setRxFIFOAck(fifoNum, fifoStatus.getIdx);
    
            fifoStatus.fillLvl--;
            fifoStatus.getIdx++;
    
            /* Check for rollover */
            if (fifoStatus.getIdx >= object->rxFIFONum[fifoNum])
            {
                fifoStatus.getIdx = 0U;
            }
        }
    }