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.

[参考译文] TMS570LC4357:缺少 EMAC RX 数据包

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

https://e2e.ti.com/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1018620/tms570lc4357-missing-emac-rx-packets

器件型号:TMS570LC4357
主题中讨论的其他器件:DP83848YB

您好!

我正在使用启用 RX 中断的 EMAC 模块 C0接收通道0。 当接收到一个中断时、它用一个信标向一个接收 RTOS 任务发出信号、然后 RX0中断被禁用。 接收任务会检查信号量、然后读取所有者位以开始处理数据包。 当它完成时、RX0中断已被重新启用。 一切正常、我打印出当前缓冲区描述符的地址和 RX 标头指针。 如果接收到多个数据包、所有数据包都被处理、则任务退出并启用中断。 但我肯定知道、有些口袋缺失了、甚至没有为它们生成中断。 在 Wireshark 中、我可以看到从计算机发送的数据包、但它不会出现在接收端。

是否有人在 EMAC 接口上遇到过类似的情况? 我是否仍然缺少可能导致此问题的东西?

我上传了我的部分代码、也许有人可以找出我缺少的内容。

谢谢!

#pragma INTERRUPT(emacRxInterrupt, IRQ)
void emacRxInterrupt(void)
{
    disableEmacInterrupts();    ///< According to Technical Reference Manual 32.2.17.3 Proper Interrupt Processing
    hdkif_t * const hdkif = &mHdkifData[0u];

    // Disable RX0 interrupt
    EMACRxIntPulseDisable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32_t)EMAC_CHANNELNUMBER, (uint32_t)EMAC_CHANNELNUMBER);

    mEmacRxBdIntGenerated = (uint32_t)HWREG(hdkif->emac_base + EMAC_RXCP(EMAC_CHANNELNUMBER));

    EMACCoreIntAck(hdkif->emac_base, EMAC_INT_CORE0_RX);                                                ///< Acknowledge RX interrupt

    mEmacRxIntCounter++;

    semaphore_give(&mEmacRxSemaphore);
    enableEmacInterrupts();
}

void rx_task(void)
{
    while (1)
    {
        if (isOk(semaphore_take(&mEmacRxSemaphore, mEmacTaskRxBlockTime)))
        {
            LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Start! Semaphore Received! Int count: %d, Int BD: %x", mEmacRxIntCounter, mEmacRxBdIntGenerated));

            while ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_OWNER) != EMAC_BUF_DESC_OWNER )
            {
                LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: SOP set! Current BD: %x", currentBufferDescriptor));

                // Start processing the received packet only after SOP(Start Of Packet) received and we have the ownership
                if ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_SOP) == EMAC_BUF_DESC_SOP)
                {
                    if ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_DSC_FLAG_ERROR_MASK) == 0)
                    {
                        // Check received packet size
                        packetSize = BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & 0xffffu;

                        // Invalidate cache, to not to interfere with new packets in memory
                        _dcacheInvalidateRange_(BYTE_SWAP(currentBufferDescriptor->bufptr), BYTE_SWAP(currentBufferDescriptor->bufptr) + packetSize);

                        LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Packet arrived, BD: %x, RXHP: %x size: %d\r\n", currentBufferDescriptor, HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)), packetSize));

                        if ((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_EOP) != EMAC_BUF_DESC_EOP)
                        {
                            LWIP_DEBUGF(NETIF_DEBUG, ("EMACRX: NO EOP: %x, RXHP: %x\r\n", currentBufferDescriptor, HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER))));
                        }

                        if (packetSize > 0u && packetSize <= ETH_MAX_FRAME_SIZE)
                        {
                            pbuf_t *p;
                            p = pbuf_alloc(PBUF_RAW, packetSize, PBUF_POOL);    ///< We allocate a pbuf chain of pbufs from the pool.

                            LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Packet processing!"));

                            if (NN(p))
                            {
                                memcpy(p->payload, (void *)(BYTE_SWAP(currentBufferDescriptor->bufptr)), packetSize);

                                eth_hdr_t *ethhdr;
                                ethhdr = p->payload;

                                switch (htons(ethhdr->type))
                                {
                                // IP or ARP packet?
                                case ETHTYPE_ARP:
                                case ETHTYPE_IP:
                                    // full packet send to tcpip_thread to process
                                    if (mLwipRuntimeData.netif.input(p, &mLwipRuntimeData.netif) != ERR_OK)
                                    {
                                        LWIP_DEBUGF(NETIF_DEBUG, ("ifx_netif_input: IP input error\n"));
                                        pbuf_free(p);
                                        p = NULL;
                                    }
                                    break;

                                default:
                                    LWIP_DEBUGF(NETIF_DEBUG, ("ifx_netif_input: type unknown\n"));
                                    pbuf_free(p);
                                    p = NULL;
                                    break;
                                }
                            }
                            else
                            {
                                LWIP_DEBUGF(NETIF_DEBUG, ("EMACRX: pbuf allocation error\n"));
                            }
                        }
                        else
                        {
                            LWIP_DEBUGF(NETIF_IN_DEBUG, ("Too large: %d\n", packetSize));
                        }

                        mEmacRxBdAcknowledged = (uint32_t)currentBufferDescriptor;
                        HWREG(hdkif->emac_base + EMAC_RXCP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor;        ///< To acknowledge BD
                        LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Acknowledged BD[1]: %x", mEmacRxBdAcknowledged));

                        volatile emac_rx_bd_t *currentBufferDesListStart = currentBufferDescriptor;
                        while((BYTE_SWAP(currentBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_EOP) != EMAC_BUF_DESC_EOP)
                        {
                            currentBufferDescriptor->bufoff_len = BYTE_SWAP(ETH_MAX_FRAME_SIZE);
                            currentBufferDescriptor->flags_pktlen = BYTE_SWAP(EMAC_BUF_DESC_OWNER);
                            currentBufferDescriptor = (emac_rx_bd_t *)BYTE_SWAP((uint32_t)currentBufferDescriptor->next);

                            mEmacRxBdAcknowledged = (uint32_t)currentBufferDescriptor;
                            HWREG(hdkif->emac_base + EMAC_RXCP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor;        ///< To acknowledge BD
                            LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Acknowledged BD[2]: %x", mEmacRxBdAcknowledged));
                        }

                        // free up the current BD
                        currentBufferDescriptor->bufoff_len = BYTE_SWAP(ETH_MAX_FRAME_SIZE);
                        currentBufferDescriptor->flags_pktlen = BYTE_SWAP(EMAC_BUF_DESC_OWNER);
                        volatile emac_rx_bd_t *currentBufferDescTemp = (emac_rx_bd_t *)BYTE_SWAP((uint32_t)currentBufferDescriptor->next);
                        currentBufferDescriptor->next = NULL;

                        // update the linked list
                        tailBufferDescriptor->next = (emac_rx_bd_t *)BYTE_SWAP((uint32_t)currentBufferDesListStart);

                        // Check if we are at the end of queue
                        if ((BYTE_SWAP(tailBufferDescriptor->flags_pktlen) & EMAC_BUF_DESC_EOQ) == EMAC_BUF_DESC_EOQ)
                        {
                            while (HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) != 0u) { task_sleep((sysTimeDuration_t)DURATION_MS(1)); }
                            // Restart EMAC reception with updating the head pointer
                            HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor;
                            LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: RX restarted at BD: %x\r\n", currentBufferDescriptor));
                        }
                        tailBufferDescriptor = currentBufferDescriptor;
                        currentBufferDescriptor = currentBufferDescTemp;

                        LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: End of packet!"));
                    }
                    else
                    {
                        LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: Packet error!"));
                    }
                }
                else
                {
                    LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: BD no SOP found!"));
                    break;
                }
            }

            // Re-enable RX0 interrupt
            EMACRxIntPulseEnable(hdkif->emac_base, hdkif->emac_ctrl_base, (uint32_t)EMAC_CHANNELNUMBER, (uint32_t)EMAC_CHANNELNUMBER);

            LWIP_DEBUGF(NETIF_IN_DEBUG, ("EMACRX: End!"));
        }
        else
        {
            // We didn't receive semaphore inside the given blocking time, but the head pointer is on the next location -> IRQ lost
            if (HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) == 0u)
            {
                // Restart EMAC reception with updating the head pointer
                HWREG(hdkif->emac_base + EMAC_RXHDP(EMAC_CHANNELNUMBER)) = (uint32_t)currentBufferDescriptor;
                LWIP_DEBUGF(NETIF_DEBUG, ("EMACRX: IRQ lost RX restarted at BD: %x\r\n", currentBufferDescriptor));
            }
        }
    }
}

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="492576" URL"~/support/microcontrollers/other-microcontrollers-group/other/f/other-microcontrollers-forum/1018620/tms570lc4357-missing-emac-rx-packets "]但我知道某些药格缺失,甚至没有为这些药格生成中断。[/quot]

    我尚未研究您的代码、但 EMAC 模块具有   一些网络统计寄存器、这些寄存器在《TMS570LC43x 16/32 RISC 闪存微控制器技术参考手册》(修订版 A)中进行了介绍。

    您是否曾尝试查看网络统计寄存器中是否有错误迹象?

    由于 Wireshark 显示从 PC 传输的数据包、以下任何一项显示的值都不为零、这将表明 EMAC 无法接收帧:

    • 32.5.50.34接收 FIFO 或 DMA 帧起始超限寄存器(RXSOFOVERRUNS)(偏移= 284h)
    • 32.5.0.35接收 FIFO 或 DMA 中间帧超限寄存器(RXMOFOVERRUNS)(偏移= 288h)
    • 32.5.50.36接收 DMA 超限寄存器(RXDMAOVERRUNS)(偏移= 28Ch)
  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。

    我已检查网络统计寄存器。 没有任何类型的错误表明数据包丢失。 我进行了一个大约1分钟的测试、接收端有3个数据包丢失、但统计数据中没有这种情况的迹象。

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

    您好、Marton、

    我们有两个演示项目:lwip 演示和活动的 Web 服务器演示。  

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

    我发现、如果启用了半双工模式、则没有丢失的10Mbps 或100Mbps 数据包。 如果我使用两个速度选项重新启用全双工模式、则数据包丢失问题会再次出现。

    这可能是硬件问题、还是 PHY 问题?
    使用的 PHY 是 DP83848YB。

  • 请注意,本文内容源自机器翻译,可能存在语法或其它翻译错误,仅供参考。如需获取准确内容,请参阅链接中的英语原文或自行翻译。
    [引用 userid="492576" URL"~/support/microcontrollers/arm-based-microcontrollers-group/arm-based-microcontrollers/f/arm-based-microcontrollers-forum/1018620/tms570lc4357-missing-emac-rx-packets/3771633 #3771633">我发现、如果启用了半双工模式、则不会丢失10或100 Mbps 的数据包。 如果我重新启用具有两个速度选项的全双工模式、则数据包丢失问题会再次出现。

    链路两端的 PHY 是否设置为自动协商?

    如果不是 、您可能会受到双工不匹配的影响

    在之前的网络统计寄存器屏幕截图中 、发送载波侦听错误寄存器(TXCARRIERSENSE)的值不为零。 当数据包丢失时、EMAC_TXCARRIERSENSE 的值是否增大?

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

    感谢切斯特的帮助。 当我将以太网适配器设置为全双工模式时、TXCARRIERSENSE 不断递增、这次我有丢包。 我发现 EMAC 在启动后仅初始化一次、我使用 DP83848YB 的自动协商功能。 但在给定的时间窗口中无法进行自动协商、因此检测到错误(默认)的双工模式(半 双工而不是全双工)。 因此、我的问题是双工不匹配。 我已经将启动时的 EMAC 设置为固定的100Mbps-FDX、现在它可以正常工作。