查看: 1422|回复: 0

[分享] i.MXRT1020 Iperf网络速度测试

[复制链接]
  • TA的每日心情
    开心
    2024-3-26 15:16
  • 签到天数: 266 天

    [LV.8]以坛为家I

    3298

    主题

    6545

    帖子

    0

    管理员

    Rank: 9Rank: 9Rank: 9

    积分
    32003
    最后登录
    2024-4-9
    发表于 2021-4-6 09:58:35 | 显示全部楼层 |阅读模式
    i.MXRT1020 Iperf网络速度测试
    11.png
    实现上述 100Mbps网络测试,需要确认SDK 修改地方如下:
    12.png
        默认的代码 TCP_WND是 2*TCP_MSS,测试速度并不高。如下所示。
    13.png
        需要和开发板上确认的 PHY芯片的硬件连接是 SPEED引脚需要接下拉电阻到GND。引脚状态时低则为100M模式,引脚状态为高为10M模式。
    14.png
        也可以设置SPEED选择寄存器,设置寄存器位SPEED Select为1则是100M模式,设置为9 则是10Mbps模式。


    15.png
        ENET 寄存器位RMII_10T对应的是 100Mbps的操作模式。


    16.png
    jperf脚本软件链接下载地址:
    17.png
      JPerf 应用程序使用jperf-2.0.0/jperf.bat 脚本文件下载地址: https://sourceforge.net/projects ... 2.0.0.zip/download.


        当在 Windows环境下打开 jperf-2.0.0/bin 文件夹的时候,需要用如下链接的文件替换 https://iperf.fr/download/windows/iperf-2.0.5b-win32.zip.


        当在 Linux环境下使用的时候,iperf binary 版本 2.0.5 需要 单独安装在系统目录中。


        在客户端模式下运行 lwIP IPERF,选择 "Server" 按钮,点击运行 [Run iperf!] (上述测试图片的测试结果是在开发板运行Server模式,PC端运行在客户端模式下)。


        在服务端模式下运行 lwIP IPERF,选择 "Client“ 按钮,在JPerf中输入 192.168.0.102 作为 板子的 IPv4 地址作为 "Server address" 参数。


        开发板参考硬件PHY KSZ8081RNB 连接原理图。


    图片


        另外在LWIP使用过程中有断线或者断网检测操作,可以参考如下代码。
    1. bool linkstatus=false;

    2. tempvalue =0;

    3. GetLinkStatus(ENET, BOARD_ENET0_PHY_ADDRESS, &linkstatus);       

    4. while ((tempvalue < 100) && (!linkstatus))

    5. {

    6. GetLinkStatus(ENET, BOARD_ENET0_PHY_ADDRESS, &linkstatus);       

    7. if (linkstatus)

    8. {

    9. phy_speed_t speed;

    10. phy_duplex_t duplex;

    11. GetLinkSpeedDuplex(ENET, BOARD_ENET0_PHY_ADDRESS, &speed, &duplex);

    12. PRINTF("\n\r link =%d \n\r",linkstatus);

    13. }

    14. tempvalue++;

    15. PRINTF("\n\r tempvalue =%d \n\r",tempvalue);

    16. }

    17. if (tempvalue == 100)

    18. {

    19. __NVIC_SystemReset();

    20. }
    复制代码
    TCP发送数据的时候并不是直接送出数据的,而是考虑了后续的数据一起发送,所以采用的是缓存队列机制。 在每次tcp_write函数之前,需要判断一下 pcb->snd_buf (以字节为单位的发送缓冲区)还有多少栈数据空间可用,如果数据长度超过当前发送缓冲区大小或传出段的队列长度pcb->snd_queuelen(当前发送队列记录里面的包的数目)大于lwipopts.h中定义的上限,则tcp_write()函数将失败并返回ERR_MEM。可以使用tcp_sndbuf(pcb) 函数检索输出队列中可用的字节数。使用此函数的正确方法是使用最多tcp_sndbuf(pcb) 字节的数据调用函数。如果函数返回ERR_MEM,应用程序应该等到其他主机成功接收到当前排队的数据后重试。


        可开启心跳包机制LWIP_TCP_KEEPALIVE,通过定期发送心跳包,是否收到ACK检测tcp异常的发生(如突然拔网线等)。发送数据前需检查缓冲区剩余长度,tcp_write()只是把数据包加入发送队列,实际发送动作由tcp_output()执行。
    1. if((tcp_sndbuf(pcb) > TCP_MSS) && (tcp_write(pcb, data, len, TCP_WRITE_FLAG_MORE) == ERR_OK)) {
    2. /* send current data /
    3. tcp_output(pcb);
    4. } else {
    5. / send data in tcp queue */
    6. tcp_output(pcb);
    7. }
    复制代码
    连续tcp_write超过12次后失败的问题,可以在tcp_out.c文件中找到了如下代码:
    1. if ((queuelen > TCP_SND_QUEUELEN) || (queuelen > TCP_SNDQUEUELEN_OVERFLOW)) {

    2. LWIP_DEBUGF(TCP_OUTPUT_DEBUG | 2, ("tcp_enqueue: queue too long %"U16_F" (%"U16_F")\n", queuelen, TCP_SND_QUEUELEN));

    3. goto memerr;

    4. }
    复制代码
    这里,TCP_SND_QUEUELEN值为12,TCP_SND_QUEUELEN定义代码。


    #define TCP_SND_BUF             (2*TCP_MSS)  


    // 发送缓冲区,为两个MSS的大小


    // 此参数限制了tcp_write的次数,系数默认为6, 改为30


    #define TCP_SND_QUEUELEN        (30 * TCP_SND_BUF)/TCP_MSS


        于是将那个默认的系数由6改为30,就可以解决tcp_write的连续多次调用后失败的问题。应该检查没有超过TCP_SND_QUEUELEN,但由于需要分拆数据包,这样实际上可能会超过最大值。


        tcp_write这个函数最后一个参数的说明,该函数声明如下。


    err_t tcp_write(struct tcp_pcb *pcb, void *dataptr, u16_t len, u8_t copy);


        其中第四个参数是一个copy参数,当为0时为不拷贝数据,也就是在dataptr所指的缓冲区里面发送数据,因为调用tcp_write成功后数据并不会立即发送,所以要确保dataptr所指的缓冲区内容保持不变,如果调用tcp_write成功后,再改变dataptr缓冲区可能就会和预期发送的数据不一致。将最后的参数改为1,为1时即拷贝缓冲区内容,当执行tcp_write时,会将dataptr所指向的缓冲区内容先拷贝到发送的缓冲区中,这样的话执行tcp_write之后再改变dataptr所指的内容是不影响数据的正确发送的。

    签到签到
    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /4 下一条

    Archiver|手机版|小黑屋|恩智浦技术社区

    GMT+8, 2024-4-20 03:34 , Processed in 0.110645 second(s), 22 queries , MemCache On.

    Powered by Discuz! X3.4

    Copyright © 2001-2021, Tencent Cloud.

    快速回复 返回顶部 返回列表