RT-Thread论坛
直播中

张旭

8年用户 1082经验值
私信 关注
[问答]

GD32F470+LWIP TCP偶尔丢包怎么解决?

LWIP版本2.1.2
芯片GD32F470ZGT6
rtthread版本4.1.0
上位机IP:192.168.100.125
板子IP:192.168.100.150
现象:上位机和板子进行modustcp通信,查询间隔约10ms,对发约半小时后板子会出现一次数包丢失。
排查过程:

  • 之前查过说是芯片使用硬件校验和会遇到0xFFFF时丢包的问题,用软件检验和能解决,但是驱动内看了并没有开启硬件校验和的宏,不相符。
  • 通过wireshark在上位机监控数据,发现出现问题的时候,上位机是发送了数据的,但是板子似乎没有收到,而且过1.5秒后板子还会重发一次上一包的数据,符合tcp没有收到ack的重发机制。

    因此认为是校验和之类的原因校验失败丢包。
  • 开启了交换机端口镜像,监听tcp到交换机后的数据流量,发现两次上位机发送给板子出问题的tcp数据包的校验和都是0x0000。

有大哥遇到这样的问题吗?怎么解决的
补充:

  • 用scapy计算上面监听的数据包的校验和,发现上位机发送的数据包的校验和0x00是正确的。
  • 网卡的硬校验和关闭,此时再监听数据,监听3小时没有出现校验和为0的数据包。但是重新开启硬校验和,测试了3次,基本都在半小时左右出现了校验和为0的数据,并且板子表现出丢包现象


回帖(1)

王霞

2025-10-11 16:15:26

针对GD32F470+LWIP TCP偶尔丢包的问题,结合您的描述和排查过程,建议从以下几个关键方向进行深入排查和解决:




1. 排查硬件校验和问题(核心疑点)


尽管您已检查宏定义,但GD32F470的硬件校验和可能存在隐性使能芯片特定缺陷




  • 再次确认校验和配置
    gd32f4xx_enet.c驱动文件中,检查以下关键代码段:


    /* 接收路径 */
    if (ENET_DMA_RXDESC_CRCHL(rcv_frame.rxdesc) & ENET_DMA_RXDESC_CE)
      p->flags |= PBUF_FLAG_IS_CUSTOM; // 标记校验错误

    /* 发送路径 */
    dma_txdesc->ctl |= ENET_DMA_TXDESC_CIC_BYPASS; // 确保发送禁用硬件校验

    若存在校验错误标记,需在low_level_input()中丢弃该包。




  • 强制软件校验和
    lwipopts.h中显式禁用硬件校验和:


    #define CHECKSUM_CHECK_TCP              0  // 强制TCP校验由软件计算
    #define CHECKSUM_CHECK_IP               0
    #define CHECKSUM_CHECK_UDP              0

    重新编译并测试,观察是否解决。






2. 优化LWIP内存和缓冲区配置


LWIP内存不足会导致丢包,调整以下参数(lwipopts.h):


#define MEM_SIZE                (16*1024)      // 增大内存池
#define PBUF_POOL_SIZE          64             // 增加PBUF数量
#define PBUF_POOL_BUFSIZE       LWIP_MEM_ALIGN(TCP_MSS+40) // 确保容纳完整TCP包
#define TCP_WND                 (8*TCP_MSS)    // 增大TCP窗口
#define TCP_RECVMBOX_SIZE       20             // 增大TCP接收邮箱



3. 检查以太网DMA描述符泄漏


GD32驱动中DMA描述符未正确回收会导致后续丢包:



  • 在接收中断处理函数中
    确保每个处理后的描述符清除OWN位并回收:
    void ETH_IRQHandler(void) {
      if (enet_flag_get(ENET_DMA_FLAG_R)) { // 接收中断
          while (检查描述符OWN位为0) {      // 表示有数据
              low_level_input(&netif);      // 处理数据包
              // 回收描述符:清除OWN位,交给DMA
              current_rx_desc->ctl |= ENET_DMA_RXDESC_RCH;
          }
      }
    }

    添加统计计数器,监控描述符回收次数是否匹配中断触发次数。





4. 网络任务调度与中断冲突



  • 提升网络任务优先级
    在RT-Thread中,调整LwIP线程优先级至最高级别(如rt_thread_priority_set(tcpip_thread, 10))。

  • 优化中断处理
    缩短以太网中断服务程序(ETH_IRQHandler)执行时间,仅做信号量通知,数据处理移至线程上下文。




5. 启用LWIP调试与统计


lwipopts.h中启用诊断:


#define LWIP_STATS                  1
#define LWIP_STATS_DISPLAY          1
#define TCP_DEBUG                   LWIP_DBG_ON
#define ETHARP_DEBUG                LWIP_DBG_ON

丢包后通过netstat()打印统计信息,重点关注:



  • link_lost(物理层丢包)

  • memerr(内存分配失败)

  • chkerr(校验和错误)




6. 排查物理层干扰(PHY寄存器检查)


通过miiutil工具检查PHY状态寄存器:


miiutil eth0 0x1  # 查看PHY控制寄存器
miiutil eth0 0x1F # 查看扩展错误计数寄存器

重点关注:



  • CRC错误计数(Reg 0x19)

  • 符号错误计数(Reg 0x1A)
    若持续增长,降低PHY速度测试(强制10M半双工)排除干扰。




7. 更新驱动和协议栈



  • 升级LWIP到2.1.3+:修复TCP Fast Retransmit相关Bug。

  • 更新GD32F4xx_DFP驱动库:确认使用最新版本(如V3.2.0),修复DMA描述符处理缺陷。




测试方案



  1. 压力测试工具
    使用iperf进行持续TCP吞吐测试:
    iperf -c 192.168.100.150 -t 3600 -i 10 # 持续1小时测试

  2. 监控手段

    • 在板卡侧添加丢包计数器,记录low_level_input()中校验失败或内存分配失败的包。

    • 通过wireshark过滤tcp.analysis.retransmission定位重传时刻的交互数据。





通过以上步骤逐步排查,重点关注硬件校验和配置DMA描述符泄漏问题,这两者在GD32F470应用中最为常见。若问题依旧,建议联系GigaDevice技术支持获取芯片勘误手册(Errata Sheet),确认是否存在已知硬件缺陷。

举报

更多回帖

发帖
×
20
完善资料,
赚取积分