历史上的今天
返回首页

历史上的今天

今天是:2025年04月22日(星期二)

正在发生

2018年04月22日 | STM32网络丢包问题分析

2018-04-22 来源:eefocus

1. 测试环境说明

硬件平台:NUCLEO-F767ZI 开发板(STM32F7,Cortex-M7,216MHz,2MB Flash,512KB SRAM) 
操作系统:FreeRTOS v9.0.0(CMSIS-RTOS v1.02) 
TCP/IP协议栈:LwIP v2.0.0

  这里所描述的网络丢包问题的测试程序,是使用 STM32CubeMX 工具(库版本为 STM32Cube_FW_F7_V1.7.0),基于 FreeRTOS 和 LwIP 实现的一个以太网 Demo 程序。协议栈已实现 ICMP 包的 echo 功能(即可以通过其他以太网设备 ping 开发板),此外,我们在该程序框架之上添加了 tcp_echoserver 和 udp_echoserver 功能,进行 TCP 和 UDP 网络性能测试,均采用 RAW API 方式实现。 
   
  相关的几个测试工具:

  • Ping 测试工具(ATKKPING): http://download.csdn.net/detail/luckydarcy/9914445

  • TCP&UDP测试工具 V1.02: http://download.csdn.net/detail/luckydarcy/9895750

  • TCP/UDP Socket调试工具V2.3: http://download.csdn.net/detail/luckydarcy/9895746

2. 以太网控制器

  要分析网络丢包问题,我们先来看一下 STM32F7 的以太网控制器提供了哪些资源。如下图所示,我们可以把 STM32F7 的以太网控制器划分为三部分,从左到右分别是:DMA 控制器、MAC 控制器、PHY 接口。NUCLEO-F767ZI 开发板上的 PHY 芯片是 8742A,通过 RMII 与 MAC 控制器相连。


这里写图片描述


  需要注意的是,这里的 DMA 是以太网外设专用的,它包含两个 FIFO 缓冲区,分别用于以太网数据帧的接收和发送,大小均为 2K 字节。 
  以太网数据接收模式设置为中断模式,当产生中断或由发送需求时,对于任务来说,以太网数据的接收和发送是通过操作描述符列表和数据缓冲区来完成的。

3. 数据的接收流程

  下面我们来看一下以太网数据的接收流程: 
  中断向量表“__vector_table”中定义了以太网外设中断处理函数 ETH_IRQHandler,对于 Rx 中断来说,实际上调用的是回调函数 HAL_ETH_RxCpltCallback,而该函数只做了一件事,那就是释放信号量:

/**

  * @brief  Ethernet Rx Transfer completed callback

  * @param  heth: ETH handle

  * @retval None

  */

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)

{

  osSemaphoreRelease(s_xSemaphore);

}

  该信号量在 low_level_init 里面被定义为二值信号量,也就是互斥量:

  osSemaphoreDef(SEM);

  s_xSemaphore = osSemaphoreCreate(osSemaphore(SEM) , 1 );

  而等待该信号量的是一个称为“ethernetif_input”的线程,我们可以称它为中断服务程序 ISR,它作为整个 LwIP 协议栈的入口,它在 low_level_init 中被定义为 realtime 优先级别的线程:

osThreadDef(EthIf, ethernetif_input, osPriorityRealtime, 0, INTERFACE_THREAD_STACK_SIZE);

  线程 ethernetif_input 所做的工作也就是等待该信号量,当接收到以太网数据帧,中断处理函数就会释放信号量,从而使得 ethernetif_input 线程进入就绪态,之后便等待操作系统调度,进而进行数据帧解析。

4. 数据的发送流程

  数据的发送流程根据 LwIP 的配置有所区别,但最终都会调用 low_level_output 函数。该函数也是通过操作描述符列表和数据缓冲区来完成发送动作。 
  和接收流程不同的是,发送的动作没有使用信号量进行同步,而是根据应用程序的需求进行调用。也就是说,只要应用程序有发送数据的需求都可以直接调用相应的API进行发送。那么,这样就会造成资源冲突,所以在更底层的 HAL_ETH_TransmitFrame 函数中,使用了网卡句柄的锁进行保护:

__HAL_LOCK(heth);

  ......

__HAL_UNLOCK(heth);


  这样确实可以解决资源冲突的问题,但是这个 Demo 程序的问题在于,当前运行的任务无论有没有拿到锁(网卡资源),low_level_output 都返回 OK。这样就会造成丢包现象。

5. 验证测试

  经过上面的分析,我们可以确认,在这个 Demo 程序中,以太网数据的接收和发送机制是存在缺陷的。针对这些缺陷,我们采用 Ping 和 UDP echo 进行测试,并在关键位置添加统计信息。 
  一个是 ICMP 的 echo 计数(ping_times),我们在程序认为发送成功时才计数:

/* send an ICMP packet */

ret = ip4_output_if(p, src, LWIP_IP_HDRINCL,ICMP_TTL, 0, IP_PROTO_ICMP, inp);

if (ret != ERR_OK) {

  // ......

  }else{

    ping_times++;

  }


另一个是 UDP 的 echo 计数(udp_times),同样,我们在程序认为发送成功时才计数:


static void udp_echoserver_recv_callback(......)

{

if(ERR_OK == udp_sendto(upcb, p, addr, port))udp_times++;

pbuf_free(p);

}


  另外,我们在 low_level_output 的各个出错部分添加出错统计(output_err),比如:


/* Prepare transmit descriptors to give to DMA */ 

if(HAL_OK != HAL_ETH_TransmitFrame(&heth, framelength)) {

    output_err++;

}

5.1 PC直接连接STM32F7

测试一、UDP echo测试(间隔100ms,长度1000字节)

  PC 机计数显示成功发送 18005 个数据包,成功接收 17999 个数据包。也即丢失 6 个,丢包率为 0.0333%。

这里写图片描述

  STM32F7 打印数据显示,程序“认为”成功发送 18005 个 UDP 数据包,但实际上有 6 个没有发送成功。与 PC 端统计数据相符。 
(串口打印数据只需关注最后三个数字,分别表示 ping_times、udp_times、output_err)

这里写图片描述

测试二、UDP echo测试(间隔10ms,长度1000字节)

  PC 机计数显示成功发送 59255 个数据包,成功接收 59233 个数据包。也即丢失 22 个,丢包率为 0.0371%。

这里写图片描述

  STM32F7 打印数据显示,程序“认为”成功发送 59255 个 UDP 数据包,但实际上有 22 个没有发送成功。与 PC 端统计数据相符。

这里写图片描述

测试三、UDP echo测试(间隔1ms,长度1000字节)

  PC 机计数显示成功发送 1920341 个数据包,成功接收 1919724 个数据包。也即丢失 617 个,丢包率为 0.0321%。

这里写图片描述

  STM32F7 打印数据显示,程序“认为”成功发送 1920341 个 UDP 数据包,但实际上有 617 个没有发送成功。与 PC 端统计数据相符。

这里写图片描述

测试四、Ping测试(以最快速度Ping,长度32字节)

  PC 机计数显示成功发送 15409 个 ICMP 包,超时 8 个,丢包率为 0.05%。

这里写图片描述

  STM32F7 打印数据显示,程序“认为”成功发送 15409 个 ICMP 包,但实际上有 1 个没有发送成功。与 PC 端显示丢失 8 个不相符。

这里写图片描述

测试五、Ping测试(以最快速度Ping,长度1472字节)

  PC 机计数显示成功发送 15402 个 ICMP 包,超时 30 个,丢包率为 0.19%。

这里写图片描述

  STM32F7 打印数据显示,程序“认为”成功发送 15402 个 ICMP 包,但实际上有 2 个没有发送成功。与 PC 端显示丢失 30 个不相符。

这里写图片描述

5.2 PC通过交换机连接STM32F7(交换机连接外网)

测试一、UDP echo测试(间隔10ms,长度1000字节)

  PC 机计数显示成功发送 61240 个数据包,成功接收 61209 个数据包。也即丢失 31 个,丢包率为 0.0506%。

这里写图片描述

  STM32F7 打印数据显示,程序“认为”成功发送 61240 个 UDP 数据包,但实际上有 12 个没有发送成功。与 PC 端显示丢失 31 个不相符。

这里写图片描述

测试二、Ping测试(以最快速度Ping,长度1472字节)

  PC 机计数显示成功发送 21827 个 ICMP 包,超时 161 个,丢包率为 0.74%。

这里写图片描述

  STM32F7 打印数据显示,程序“认为”成功发送 21827 个 ICMP 包,但实际上有 3 个没有发送成功。与 PC 端显示丢失 161 个不相符。

这里写图片描述

6. 总结

  根据以上测试,我们可以判断,不管是 UDP 测试还是 ICMP 测试,STM32F7 接收到的数据包都与 PC 端统计的成功发送数量完全相同。也就是说,对于 STM32F7 来说并没有丢包。但对于 PC 来说,确实是丢包了。情况如下: 
  (1)在 UDP 的 echo 测试中,我们发现在与 PC 直连的环境下,STM32F7 的发送失败统计数据与 PC 端统计的丢包数据完全吻合。而在交换机环境下,STM32F7 的发送失败统计数据却小于 PC 端的丢包数据。 
  (2)在 Ping 测试中,不管直连还是存在交换机,STM32F7 接收到的包与 PC 端发送的一致,但 STM32F7 的发送失败统计数据却总小于 PC 端的丢包数据。但 Ping 存在超时时间等条件限制,建议以 UDP 测试数据为准。

  经分析认为,STM32F7 出现网络丢包的主要原因不在于 LwIP 协议栈、网卡驱动以及中断响应,而是该 Demo 程序所实现的以太网数据收发机制存在缺陷所致。即: 
  (1)对于接收部分,采用二值信号量来同步以太网外设中断和中断服务程序 ISR 是个不错的主意,在上述测试中也确实没出现接收端丢包的情况。但是如果网络数据过于频繁,系统任务繁重,使得中断服务程序还没执行完就出现了下一个中断,也可能会导致丢包。 
  (2)对于发送部分,采用网卡句柄的锁来保护共享资源的做法有待商榷,Demo 中的这种机制会直接导致资源冲突的时候丢包。

  此外,根据测试情况,Demo 程序中应该还存在其他导致数据包发送时丢失的路径。所以,建议相关开发工程师不要过分依赖 Demo 程序,如果确定使用 STM32 + FreeRTOS + LwIP 的设计方案,应该明确项目需求,在硬件资源有限的条件下,结合 FreeRTOS 和 LwIP 协议栈的特性设计出更合理的程序



推荐阅读

史海拾趣

Good Will Instrument Co., Ltd.公司的发展小趣事

对于恒温箱控制器电路,网友可能会有多种问题,以下是一些常见问题及其详细回答:

一、恒温箱控制器电路的基本原理是什么?

回答
恒温箱控制器电路的基本原理是通过温度传感器(如热敏电阻、热电偶等)实时检测恒温箱内的温度,并将检测到的温度信号转换为电信号(如电压或电流信号)。这个电信号随后被送入控制器中进行处理,与预设的温度值进行比较。如果检测到的温度高于或低于预设值,控制器会发出指令,通过调节加热元件(如电热丝、加热管等)或制冷元件(如压缩机、半导体制冷片等)的工作状态,使恒温箱内的温度回到预设值,从而实现恒温控制。

二、恒温箱控制器电路常见的故障有哪些?

回答
恒温箱控制器电路常见的故障包括但不限于以下几种:

  1. 温度显示异常
    • 可能原因:温度传感器损坏、控制器内部电路故障、显示屏故障等。
    • 解决方法:检查并更换损坏的温度传感器、修复或更换控制器内部故障电路、更换显示屏等。
  2. 温度控制不准确
    • 可能原因:控制器参数设置错误、温度传感器位置不当、加热/制冷元件故障等。
    • 解决方法:重新校准控制器参数、调整温度传感器位置、检查并修复加热/制冷元件等。
  3. 控制器无法启动
    • 可能原因:电源故障、控制器内部保险丝熔断、电路板短路等。
    • 解决方法:检查电源是否正常、更换熔断的保险丝、修复电路板短路等。

三、如何检查恒温箱控制器电路是否正常工作?

回答
检查恒温箱控制器电路是否正常工作,可以按照以下步骤进行:

  1. 检查电源
    • 确认电源插头是否牢固插入插座,电源线是否完好无损。
    • 使用万用表测量电源电压,确保在控制器要求的范围内。
  2. 检查温度传感器
    • 使用万用表测量温度传感器的电阻值或电压值,与标准值进行比较,判断传感器是否正常。
    • 检查传感器与控制器之间的连接是否牢固可靠。
  3. 检查控制器显示
    • 观察控制器显示屏上的温度读数是否准确,有无异常显示。
  4. 检查加热/制冷元件
    • 检查加热/制冷元件是否正常工作,可以通过观察其工作状态或使用万用表测量其电流/电压值来判断。
  5. 进行功能测试
    • 设置一个预设温度值,观察恒温箱是否能准确达到并保持在预设温度。
    • 如果条件允许,可以使用更精确的温度测量设备(如高精度温度计)对恒温箱内的温度进行校验。

四、如何维护和保养恒温箱控制器电路?

回答
为了保持恒温箱控制器电路的长期稳定工作,可以进行以下维护和保养工作:

  1. 定期清洁
    • 定期清洁恒温箱内部和外部的灰尘和污垢,防止对控制器电路造成不良影响。
    • 清洁时应断开电源,并使用合适的清洁工具和清洁剂。
  2. 检查连接
    • 定期检查温度传感器、加热/制冷元件与控制器之间的连接是否牢固可靠,如有松动应及时紧固。
  3. 校准参数
    • 定期对控制器进行校准,确保温度读数准确可靠。
    • 校准时应按照控制器的使用说明书或生产厂家的建议进行操作。
  4. 更换老化部件
    • 对于已经老化或损坏的部件(如温度传感器、加热/制冷元件等),应及时进行更换。
  5. 注意使用环境
    • 恒温箱应放置在通风良好、干燥清洁的环境中,避免阳光直射和潮湿环境对控制器电路造成损害。
  6. 定期维护
    • 定期对恒温箱进行全面检查和维护,包括控制器电路、加热/制冷系统、进出料装置等部分。
    • 维护时应按照设备的操作手册和生产厂家提供的维护保养指导进行。
DIOO公司的发展小趣事

DIOO公司的创始人李奥(Leo)是一位热衷于电子技术的工程师。在20世纪80年代初,他看到了电子行业的巨大潜力,并决定创立DIOO公司,专注于开发和生产高端电子产品。凭借对技术的热爱和对市场的敏锐洞察,李奥带领DIOO公司推出了第一款自主研发的电子产品——高性能音频放大器,该产品凭借其卓越的性能和独特的设计在市场上引起了轰动。

Design Gateway公司的发展小趣事

随着Gateway业务的不断发展,公司开始寻求更多的市场曝光。1987年,Gateway在《Computer Shopper》杂志上投放了一版独特的广告,吸引了众多消费者的目光。1991年,公司推出了彰显其牧场起家背景的别具一格的奶牛花斑盒状商标,这一创新举措获得了全国消费者的认可,进一步提升了Gateway的品牌知名度和市场地位。

(请注意,由于篇幅限制,以上两个故事为简化版。在实际写作中,可以进一步扩展每个故事,包括更详细的背景信息、人物对话、市场反应等。)

由于篇幅所限,这里只提供了两个故事概要。如果需要更多关于Gateway或其他电子公司的发展故事,可以进一步研究和撰写。

汇科公司的发展小趣事

2010年,山东汇科电气技术有限公司在山东淄博成立,标志着汇科公司在电子行业迈出了坚实的第一步。创立之初,公司就确定了以节能环保为发展核心的战略方向。2011年,汇科与日本富士等国内外一线品牌建立了战略合作关系,成为富士一级代理及指定维修中心,这一举措为公司的技术积累和市场拓展奠定了坚实基础。

HellermannTyton公司的发展小趣事

随着全球对环境保护意识的增强,Heimann Optoelectronics Gmbh积极响应,将绿色环保理念融入产品设计和生产中。公司投入大量资源研发出低功耗、长寿命的光电传感器,这些产品在使用过程中能够显著减少能源消耗和废弃物产生。此外,公司还采用环保材料进行包装,确保从生产到废弃的整个生命周期都符合环保标准。这一举措不仅赢得了市场的广泛赞誉,还为公司树立了良好的企业形象。

Aborn Electronics Inc公司的发展小趣事

在激烈的市场竞争中,成本控制是企业生存和发展的重要因素之一。Aborn Electronics深知这一点,因此在供应链管理上下了大力气。公司与多家优质供应商建立了长期稳定的合作关系,确保了原材料的稳定供应和质量可靠。同时,通过对生产流程的不断优化和改进,降低了生产成本,提高了生产效率。这些措施使得Aborn Electronics的产品在市场上更具竞争力。

问答坊 | AI 解惑

HT48CAx/HT48RAx 软件应用要点

HT48CAx/HT48RAx  软件应用要点…

查看全部问答>

诺基亚5110LCD 驱动 字体放大

5110LCD邮购回来了,经过一个晚上的研究算是可以点亮了,但是我用的16f84a,程序存储器不是非常大,但是我想显示大一些的字符,没办法只好自己研究了,经过好几个夜晚的调试修改终于可以正常显示了,今天过来显摆下。呵呵! 大家注意第一行的三个 ...…

查看全部问答>

嵌入式技术

安徽省信息产业厅唯一指定的嵌入式实训基地坐落在合肥,其培训的课程体系主要是 ARM+Linux课程体系 嵌入式系统的基本概念及软硬件开发过程 ARM体系结构及指令 嵌入式集成开发工具ADS的集成开发 LPC2000系列原理及基于LPC2000系列的系统构成 ...…

查看全部问答>

请各位大哥帮忙看一下build编译驱动的问题

近日才学驱动 在build环境下编译驱动一直不成功,请大家帮忙看一下 C:\\WINDDK\\2600>build -0 BUILD: Object root set to: ==> objchk BUILD: Adding /Y to COPYCMD so xcopy ops won\'t hang. BUILD: /i switch ignored BUILD: Compile a ...…

查看全部问答>

请问ic卡于银行间通信的问题。

现在手上有个单子,是要将煤气购买ic卡能够通过银行atm来购买的,不知道这个需要从哪里入手?具体过程是怎样的?难不难啊?…

查看全部问答>

IAR 限制问题

现在用IAR运行自带程序的时候提示程序超过32K,无法装载。论坛的高手有没有谁可以发个破解的方法给我呀,限制得很是郁闷....…

查看全部问答>

ab 1769 L32e CPU 通讯问题?

用RSLINX 连接ab 1769 L32e CPU 通讯不上,用工业以太网, 拼地址拼不通,无网络连接,计算机加网线上网正常,连接其他ab通讯模块正常,rslinx显示不识别硬件,cpu还挂着ab panel view plus 1000 连接正常 麻烦各位给分析分析什么原因。…

查看全部问答>

电路分析

本帖最后由 paulhyde 于 2014-9-15 09:38 编辑 当拿到一个电路,我们应该从哪里开始分析,应当注意哪些特征?期待您的好的方法和思路或感悟。  …

查看全部问答>

Lm8962,UDP同时接收、发送数据,UDP接收会丢包,请问下各位大侠是什么原因?

我创建了一个UDP socket,来实现对数据的收发。   我用PC机周期性地通过UDP给lm3s8962发数据,lm3s8962处理完后,再通过UDP发送给PC机。 无论PC机的周期设为多大,发现lm3s8962只能收到一半pc机发送的数据。   假如我分别创建两个U ...…

查看全部问答>

做的流水灯程序,要求从右到做两次就停下来,可是不行?

#include #include #define uint unsigned int #define uchar unsigned char uchar temp,b; void delay(uint z); void main() {              temp=0xfe;       &nbs ...…

查看全部问答>