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.

[参考译文] AM2431:当接收到大量以太网数据包时会出现问题。

Guru**** 2747375 points

Other Parts Discussed in Thread: AM2431, LP-AM243

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1357262/am2431-issues-arise-when-receiving-a-large-volume-of-ethernet-packets

器件型号:AM2431
主题中讨论的其他器件: LP-AM243

您好!所有 TI 专家!

我目前的产品使用 AM2431作为主芯片、我现在使用的 SDK 是 mcu_plus_sdk_am243x_09_01_00_41。 我参考了 enet_layer2_cpsw 示例程序、并针对我们的应用程序对其进行了修改。

最近、我遇到了一个问题、即系统正常运行、只有几个以太网数据包、但当存在大量数据包时、会出现错误。 我发现该问题与以太网(CPSW)-> ENET RX DMA 通道>数据包池配置中的配置设置有关。 大型池数据包计数的最大设置为192、但我的系统在8ms 内发送807个数据包、每个数据包为1461字节。 传输后、有大约20ms 的空闲周期、允许 MCU 处理数据包。 使用 Wireshark 的观察结果显示、数据速率约为125Mbps、鉴于 AM2431处理千兆位以太网的能力、它从理论上应该管理此工作负载。 不过、似乎数据包的数量太大、没有足够的 DMA 空间来处理所有这些数据包。 我正在寻找有关如何解决此问题的任何建议。 谢谢!

此致!

拉里

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

    有人有想法吗?

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

    尊敬的 :

    感谢您的提问。

    本周我不在办公室。

    下周同一时间再见。

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    感谢您的回复、希望尽快获取您的反馈。

    此致!

    拉里

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

    尊敬的 :

    谢谢耐心等待。

    我们可以看到、您已经很好地描述了该问题。

    您可以帮助我逐步按照操作以更快地重现问题吗?

    同时、您能否在 SDK-AM243X 软件开发套件(MCU-PLUS-SDK)| TI.com 上尝试 相同的步骤、并确认得到相同的结果?

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    当然、根据您的描述、我将 SDK 版本升级到了9.2.0.50、但我仍然遇到了问题。 您需要我提供哪些信息来逐步重现问题?

    以下是我认为必须提供的一些信息:

    1. 我的 AM2431通过 RGMII 与另一个以太网交换机 IC 通信、因此启用了外部 PHY 管理。
    2. 每个数据包大小为1461字节、两次数据包传输的间隔为2-3ms。 这个间隔可能会下降、具体取决于我的设置。 最多可以接收到1000个连续数据包、然后是10-20ms 的休息周期、这使得 AM2431可以处理最近接收到的数据包。

    您还需要哪些其他信息?

    此致!
    拉里

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

    好的、Larry、

    我将从 AM243x-EVM 上的 MCU SDK 9.2开始。

    Unknown 说:
    AM2431

    这是 AM243x-EVM。 对吧?

    Unknown 说:
    Enet (CPSW)中的配置设置

    要更好地获得您在本地完成的更改的屏幕截图吗?

    此致

    阿什瓦尼

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    否,这是我们的产品,我们使用 AM2431作为主芯片

    好的。 这是您的定制板。 您能否在 AM243x-EVM 上尝试相同的测试、并提供相关步骤和结果。

    这将帮助我们在 EVM 上重现问题。

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    很抱歉这么晚才回复、我最近一直在处理其他任务。

    为了澄清一下、我正在使用的开发板是 LP-AM243、因此我即将进行的所有测试都将使用此板。 我已修改的示例代码 enet_l2_cpsw出于测试目的、我在两个方面进行了更改。

    首先、我在中修改了数据包池配置 ENET (CPSW) ,更改 大型池包数 至192、 数据包数量 对于 ENET RX DMA 通道 到124、然后 数据包数量 对于 ENET TX DMA 通道 至64。

    第二,我修改了EnetApp_rxTask()中的内容l2_cpsw_dataflow.c,以便只有当有效载荷的第一个字节不是0x21时才返回数据包。 以下是修改内容:

     

    void EnetApp_rxTask(void *args)
    {
        EnetApp_PerCtxt *perCtxt = (EnetApp_PerCtxt *)args;
        EnetDma_PktQ rxReadyQ;
        EnetDma_PktQ rxFreeQ;
        EnetDma_PktQ txSubmitQ;
        EnetDma_Pkt *rxPktInfo;
        EnetDma_Pkt *txPktInfo;
        EthFrame *rxFrame;
        EthFrame *txFrame;
        uint32_t totalLenReceived = 0U;
        uint32_t index = 0U,i = 0U;
        uint32_t totalRxCnt = 0U;
        int32_t status = ENET_SOK;
    
        while ((ENET_SOK == status) && (gEnetApp.run))
        {
            /* Wait for packet reception */
            SemaphoreP_pend(&perCtxt->rxSemObj, SystemP_WAIT_FOREVER);
    
            /* All peripherals have single hardware RX channel, so we only need to retrieve
             * packets from a single flow.*/
            EnetQueue_initQ(&rxReadyQ);
            EnetQueue_initQ(&rxFreeQ);
            EnetQueue_initQ(&txSubmitQ);
    
            /* Get the packets received so far */
            status = EnetDma_retrieveRxPktQ(perCtxt->hRxCh, &rxReadyQ);
            if (status != ENET_SOK)
            {
                /* Should we bail out here? */
                EnetAppUtils_print("Failed to retrieve RX pkt queue: %d\r\n", status);
                continue;
            }
    #if DEBUG
            EnetAppUtils_print("%s: Received %u packets\r\n", perCtxt->name, EnetQueue_getQCount(&rxReadyQ));
    #endif
            totalRxCnt += EnetQueue_getQCount(&rxReadyQ);
    
            /* Consume the received packets and send them back */
            rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
            while (rxPktInfo != NULL)
            {
                rxFrame = (EthFrame *)rxPktInfo->sgList.list[0].bufPtr;
                EnetDma_checkPktState(&rxPktInfo->pktState,
                                        ENET_PKTSTATE_MODULE_APP,
                                        ENET_PKTSTATE_APP_WITH_DRIVER,
                                        ENET_PKTSTATE_APP_WITH_READYQ);
                totalLenReceived = 0;
                for (i = 0; i < rxPktInfo->sgList.numScatterSegments; i++)
                {
                    totalLenReceived += rxPktInfo->sgList.list[i].segmentFilledLen;
                }
                EnetAppUtils_assert(totalLenReceived <= ENET_MEM_LARGE_POOL_PKT_SIZE);
    
                if(rxFrame->payload[0] != 0x21)
                {
                    TickType_t tickCount  = xTaskGetTickCount();
                    uint32_t current_time = tickCount * portTICK_PERIOD_MS;
                    static prev_time = 0;
    
                    EnetAppUtils_print("Recv 0x22: %d\r\n", current_time - prev_time);
                    prev_time = current_time;
    
                    /* Retrieve TX packets from driver and recycle them */
                    EnetApp_retrieveFreeTxPkts(perCtxt);
    
                    /* Dequeue one free TX Eth packet */
                    txPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&gEnetApp.txFreePktInfoQ);
                    if (txPktInfo != NULL)
                    {
                        /* Fill the TX Eth frame with test content */
                        txFrame = (EthFrame *)txPktInfo->sgList.list[0].bufPtr;
                        memcpy(txFrame->hdr.dstMac, rxFrame->hdr.srcMac, ENET_MAC_ADDR_LEN);
                        memcpy(txFrame->hdr.srcMac, &perCtxt->macAddr[0U], ENET_MAC_ADDR_LEN);
                        txFrame->hdr.etherType = rxFrame->hdr.etherType;
    
                        txPktInfo->sgList.list[0].segmentFilledLen = totalLenReceived;
                        EnetAppUtils_assert(txPktInfo->sgList.list[0].segmentAllocLen >= txPktInfo->sgList.list[0].segmentFilledLen);
    
                        memcpy(&txFrame->payload[0U],
                               &rxFrame->payload[0U],
                               rxPktInfo->sgList.list[0].segmentFilledLen - sizeof(EthFrameHeader));
                        index = rxPktInfo->sgList.list[0].segmentFilledLen - sizeof(EthFrameHeader);
                        for (i = 1; i < rxPktInfo->sgList.numScatterSegments; i++)
                        {
                            memcpy(&txFrame->payload[index],
                                   rxPktInfo->sgList.list[i].bufPtr,
                                   rxPktInfo->sgList.list[i].segmentFilledLen);
                            index += rxPktInfo->sgList.list[i].segmentFilledLen;
                        }
    
                        txPktInfo->sgList.numScatterSegments = 1;
                        txPktInfo->chkSumInfo = 0U;
                        txPktInfo->appPriv = &gEnetApp;
                        txPktInfo->tsInfo.enableHostTxTs = false;
    
                        EnetDma_checkPktState(&txPktInfo->pktState,
                                                ENET_PKTSTATE_MODULE_APP,
                                                ENET_PKTSTATE_APP_WITH_FREEQ,
                                                ENET_PKTSTATE_APP_WITH_DRIVER);
    
                        /* Enqueue the packet for later transmission */
                        EnetQueue_enq(&txSubmitQ, &txPktInfo->node);
                    }
                    else
                    {
                        EnetAppUtils_print("%s: Drop due to TX pkt not available\r\n", perCtxt->name);
                    }
                }
    
                EnetDma_checkPktState(&rxPktInfo->pktState,
                                        ENET_PKTSTATE_MODULE_APP,
                                        ENET_PKTSTATE_APP_WITH_READYQ,
                                        ENET_PKTSTATE_APP_WITH_FREEQ);
    
                /* Release the received packet */
                EnetQueue_enq(&rxFreeQ, &rxPktInfo->node);
                rxPktInfo = (EnetDma_Pkt *)EnetQueue_deq(&rxReadyQ);
            }
    
            /* Transmit all enqueued packets */
            status = EnetDma_submitTxPktQ(perCtxt->hTxCh, &txSubmitQ);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("%s: Failed to submit TX pkt queue: %d\r\n", perCtxt->name, status);
            }
    
            EnetAppUtils_validatePacketState(&rxFreeQ,
                                                ENET_PKTSTATE_APP_WITH_FREEQ,
                                                ENET_PKTSTATE_APP_WITH_DRIVER);
    
            /* Submit now processed buffers */
            EnetDma_submitRxPktQ(perCtxt->hRxCh, &rxFreeQ);
            if (status != ENET_SOK)
            {
                EnetAppUtils_print("%s: Failed to submit RX pkt queue: %d\r\n", perCtxt->name, status);
            }
        }
    
        EnetAppUtils_print("%s: Received %u packets\r\n", perCtxt->name, totalRxCnt);
    
        SemaphoreP_post(&perCtxt->rxDoneSemObj);
        TaskP_exit();
    }

    我的程序发送的数据包的负载内容通过第一个字节区分为命令类型。 我的程序将发送大量0x21数据包、并将进行其他处理。 仅当接收到0x22数据包时、才需要响应。 因此、上述修改模拟了我的固件需要执行的任务。

    我的程序每2-3毫秒发送一个0x21数据包、总共发送200个数据包、最后发送一个0x22数据包。 发送0x22数据包后、它会停止发送大约20毫秒、然后开始下一个发送过程。 但在这些情况下、LP-AM243每次都无法正确返回0x22数据包。 我的目标是发送超过1000个0x21甚至更多的数据包。 为实现此目的、还可以修改哪些参数?

    此致!

    拉里

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

    尊敬的 

    本周我正在旅行。

    请期待下周回复。

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    期待您的回应。

    此致!

    拉里

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    在这种情况下,每次 LP-AM243无法正确返回0x22数据包

    一些数据/统计的缺失?

    此致

    阿什瓦尼  

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

    尊敬的 Ashwani:

    我使用 Wireshark 捕获了一些传输数据。 以下链接显示了具有较小数据量的状态。 请frame[14] == 0x22在筛选器位置添加。 您可以看到、传输结束发送的每个0x22数据包都会返回0x22数据包。

    https://drive.google.com/file/d/166aD-oyV_p6vm3LCOwW41a0NWHiF5SF9/view?usp=drive_link

    在以下链接中、当我使用相同的筛选器命令将传输的数据量增加到一定程度时、您可以看到、在发送每个0x22命令后、LP 板不再能够返回数据包、如之前的捕获所示。

    https://drive.google.com/file/d/11_gku0VKEqp9sTVBE7mCmnL2Sxt3imYL/view?usp=drive_link

    您是否需要任何其他信息?

    此致!

    拉里

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

    尊敬的 Ashwani:

    其他信息:根据第二个文件"Four_By_eight_panel_capture"、使用 Wireshark 计算的数据速率仅为50 Mbit/s。 但是、根据 SDK 文档"以太网性能"、AM243的 UDP 吞吐量在 CPU 负载为16%的情况下可实现50Mbps。 理论上、处理此数据速率应该绰绰有余。 尽管如此、我在 AM243-LP 上测试了示例程序"enet_lwip_cpsw"、并且使用 iperf 命令、测试的 RX 吞吐量仅为10 Mbps 左右。 这可能是潜在问题吗?

    此致!

    拉里

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

    Larry、您好!

    "enet_lwip_cpsw"(在 AM243-LP 上),使用 ipperf 命令,测试的 RX 吞吐量仅为10 Mbps 左右。

    您是否参考以下示例?

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    可以。

    此致!

    拉里

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

    感谢 Larry 的 确认。

    我将在内部讨论这一点、然后再与您联系。

    此致

    阿什瓦尼

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

    Larry、您好!

    您使用的是应用/示例调试模式还是释放模式?

    您使用的是交换机模式还是 MAC 模式的端口?

    发送到主板的数据包是否启用了 VLAN 和优先级?

    如果需要、那么具有多大优先级的数据包是什么?

    您是否在引用以下示例?

    我分享的屏幕截图显示~100M iperf 性能与恒定(非突发)流量。

    您的案例似乎有激增的流量。

    您是否可以尝试使用以下 IOCTL 对到达主机的流量进行整形?

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    为了纠正错误、在我之前的"enet_lwip_cpsw"测试中、我的 PC 连接到 WiFi、然后连接到交换机、而 LP-AM243通过 RJ45连接到交换机。 在此设置中、我通过 iperf 获得的吞吐量仅为10Mbps。 上星期五、我通过 RJ45将 PC 和 LP-AM243连接到同一个交换机、更正了测试条件。 在这些条件下、我实现了与 SDK 文档类似的吞吐量、大约为50Mbps。

    通过该实验、我了解到 LP-AM243实际上可以处理至少50Mbps 的数据、甚至在100% CPU 负载下处理高达110Mbps 的数据。 但是、为什么"enet_lwip_cpsw"可以处理此数据量、但"enet_l2_cpsw"似乎无法处理大约50Mbps 的数据? 如果没有 lwIP、"enet_L2_cpsw"应该更高效。 到底是什么导致了这种差异?

    此致!

    拉里

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    我获得的吞吐量类似于 SDK 文档,大约为50Mbps。

    感谢 Lary 更新。

    但"enet_L2_cpsw"似乎无法处理大约50Mbps?

    您使用的是应用/示例调试模式还是释放模式?

    您使用的是交换机模式还是 MAC 模式的端口?

    如果需要、那么具有多大优先级的数据包是什么?

    你的情况似乎有暴躁的流量?

    您是否可以尝试使用以下 IOCTL 对到达主机的流量进行整形?

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    您使用的是应用/示例调试模式还是释放模式?

       我正在使用调试模式进行测试。

    您使用的是交换机模式还是 MAC 模式的端口?

       我只是使用示例代码enet_l2_cpsw""进行测试、我认为它是在开关模式下?

    如果需要、那么具有多大优先级的数据包是什么?

      对于任何数据包、我都没有任何优先级。

    您是否可以尝试使用以下 IOCTL 对到达主机的流量进行整形?

      如何使用 IOCTL?  您能提供一些分步示例吗?

    此致!

    拉里

     

       

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

    您可以尝试释放模式以获得更好的结果。

    如何使用 IOCTL?  您能提供一些分步示例吗?

    到目前为止、我们还没有它的测试代码。

    此致

    阿什瓦尼

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

    尊敬的 Ashwani:

    我想确认某件事。 根据 SDK 中的文档、在 UDP 吞吐量的"以太网性能"下表中、当数据报长度为1470B 时、在理想情况下、LP-AM243每秒只能处理11Mbps 的数据、对吗? 在硬件方面、以太网速度最高可达每秒1千兆位、但 LP-AM243的处理能力仅为110Mbps。 我的理解是否正确?

    此致!

    拉里

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

    Lary、您好!

    我正在内部处理此问题。

    我有一些更新后就会回复您。

    您能检查发生丢包的位置吗?

    在主机(R5F)还是 MAC 级?

    此致

    阿什瓦尼