0
  • 聊天消息
  • 系统消息
  • 评论与回复
登录后你可以
  • 下载海量资料
  • 学习在线课程
  • 观看技术视频
  • 写文章/发帖/加入社区
会员中心
创作中心

完善资料让更多小伙伴认识你,还能领取20积分哦,立即完善>

3天内不再提示

ZC706千兆网测试(ZYNQ,FreeRTOS,Echo,lwIP,TCP,RGMII)

FPGA之家 来源:FPGA之家 2023-10-16 16:43 次阅读

(1)使用ZC706开发板测试PS端网口(EcholwIP协议栈

(2)配合操作PLLED(直接驱动和使用消息队列两种方式)

(3)PS端串口UART打印调试信息

(4)QSPI固化(Dual Quad SPI Parallel 8 bit模式)。

ZC706中,MAC 控制器 PHY 通过 RGMIIReduced Gigabit Media Independent Interface接口进行连接,实现千兆网。

一、工程概述

1.开发板配置

使用Xilinx ZYNQ开发板ZC706,默认配置ARM后即可使用PS端网口、串口和QSPI,放置AXI GPIOIP核驱动PL端的4LED

9cd24384-6bf9-11ee-939d-92fbcf53809c.png

ARM端配置如下图所示,以5处的ARM-A9为核心,使用1处的UART1打印调试信息,使用2处的网口0进行以太网通信,使用3处的AXI GPGeneral PortMaster通用主设备接口连接PL端的AXI GPIO,最后使用4处的QSPI固化程序,烧录Boot文件。

9cf287a2-6bf9-11ee-939d-92fbcf53809c.png

2.SDK程序

上述工程综合、布局布线并生成bit流后,导出硬件

新建应用工程Application Project,选择 OS Platform 平台为 freertos10_xilinxVivadoSDK版本2018.2,低版本的可能是freertos9_xilinx),选择Next,选中“FreeRTOS lwIP Echo Server”。

9cfe13c4-6bf9-11ee-939d-92fbcf53809c.png

9d0b1a92-6bf9-11ee-939d-92fbcf53809c.png

新建完成后,即可进行最基础的网络通信了。这里注意,默认设置的是DCHP动态主机配置协议,需要开发板和电脑都连接到一个路由器上。如果直接使用网线连接开发板和电脑,则启用IPv4协议,默认配置的IP地址为192.168.1.10,子网掩码255.255.255.0,网关196.128.1.1,如果想要更改默认配置,可以在main.c文件的main_thread()主线程中修改,如下所示:

xil_printf("ERROR: DHCP request timed out
");  
xil_printf("Configuring default IP of 192.168.1.10
");  
IP4_ADDR(&(server_netif.ip_addr),  192, 168, 1, 10);  
IP4_ADDR(&(server_netif.netmask), 255, 255, 255,  0);    
IP4_ADDR(&(server_netif.gw),  192, 168, 1, 1);    

LWIP 是一个小型开源的 TCP/IP 协议栈,支持IPv4IPv6TCPUDPDHCP等。

•IGMP 协议,用于网络组管理,可以实现多播数据的接收

Internet 协议(IP),包括 IPv4 IPv6,支持 IP 分片与重装,包括通过多个网络接口的数据包转发

用于网络维护和调试的 Internet 控制消息协议(ICMP

用户数据报协议(UDP

传输控制协议(TCP)拥塞控制,往返时间(RTT)估计,快速恢复和重传

•DNS,域名解析

•SNMP,简单网络管理协议

动态主机配置协议(DHCP

以太网地址解析协议(ARP

•AUTOIPIP 地址自动配置

•PPP,点对点协议,支持

3.网络设置

使用网线直接连接ZC706开发板和计算机网口,配置计算机IP地址为192.168.1.11,子网掩码255.255.255.0,网关192.168.1.1,其中IP地址的最后一处可以更改为其他值,但是不能和开发板的相同。

9d1da720-6bf9-11ee-939d-92fbcf53809c.png

9d31f2a2-6bf9-11ee-939d-92fbcf53809c.png

4.开启监听测试

使用SecureCRT软件监听,除此之外,使用其他网口助手也可以。

9d4b79de-6bf9-11ee-939d-92fbcf53809c.png

9d691c00-6bf9-11ee-939d-92fbcf53809c.png

9d749b2a-6bf9-11ee-939d-92fbcf53809c.png

9d846168-6bf9-11ee-939d-92fbcf53809c.png

9d945f32-6bf9-11ee-939d-92fbcf53809c.png

二、工程测试

1.测试Echo官方例程

先打开串口,波特率115200下载官方例程到ZC706开发板,连接SecureCRT_CN,初始化工程中串口打印信息如下:配置DCHP动态主机协议超时,自动转为IPv4,将板子的IP地址配置为192.168.1.10,子网掩码255.255.255.0,网关192.168.1.1,使用端口7

9dab0fde-6bf9-11ee-939d-92fbcf53809c.png

SecureCRT_CN界面输入字符或字符串,回车,通过网口向开发板发送数据,开发板会返回同样的数据,测试正确。

9db24f4c-6bf9-11ee-939d-92fbcf53809c.gif

2.分析源码

2.1 main函数

打开main.c文件,找到main()函数。在main函数中创建了一个线程,传入的参数依次为线程名(调试用)、函数指针、函数需要的参数、需要的堆栈大小、优先级

按照如下配置,调用了main_thread函数,不需要传参(用0NULL),堆栈大小由#define定义为1024,优先级为2。

int main()    
{        
  sys_thread_new("main_thrd", (void(*)(void*))main_thread, 0,      
                  THREAD_STACKSIZE,      
                  DEFAULT_THREAD_PRIO);      
  vTaskStartScheduler();    
  while(1);    
  return 0;    
}    

2.2 main_thread函数

此函数中实现的功能如下:

(1)初始化lwip协议栈;lwip_init();

(2)调用network_thread()创建线程;

(3)调用echo_application_thread()创建线程;

500ms检测一次DHCP是否成功,若成功则创建echo应用线程,如果10秒还没有成功,则启用IPv4,配置IP地址、子网掩码和网关后,创建echo应用程序;创建成功后退出while,配置完成;

while (1) {      
  vTaskDelay(DHCP_FINE_TIMER_MSECS / portTICK_RATE_MS);        
  if (server_netif.ip_addr.addr) {        
    xil_printf("DHCP request success
");      
    print_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask), &(server_netif.gw));      
    print_echo_app_header();          
    xil_printf("
");    
    sys_thread_new("echod", echo_application_thread, 0,    
    THREAD_STACKSIZE,    
    DEFAULT_THREAD_PRIO);    
    break;    
}
  mscnt += DHCP_FINE_TIMER_MSECS;      
  if (mscnt >= 10000) {    
    xil_printf("ERROR: DHCP request timed out
");    
    xil_printf("Configuring default IP of 192.168.1.10
");    
    IP4_ADDR(&(server_netif.ip_addr),  192, 168, 1, 10);    
    IP4_ADDR(&(server_netif.netmask), 255, 255, 255,  0);    
    IP4_ADDR(&(server_netif.gw),  192, 168, 1, 1);    
    print_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask), &(server_netif.gw));      
    /* print all application headers */    
    xil_printf("
");      
    xil_printf("%20s %6s %s
", "Server", "Port", "Connect With..");    
    xil_printf("%20s %6s %s
", "--------------------", "------", "--------------------");      


    print_echo_app_header();    
    xil_printf("
");    
    sys_thread_new("echod", echo_application_thread, 0,    
    THREAD_STACKSIZE,    
    DEFAULT_THREAD_PRIO);    
    break;    
  }    
}  

2.3 echo_application_thread函数

位置:echo.c文件。

1)创建socket,绑定端口,监听;

2)调用process_echo_request函数创建线程;

此函数需要传入参数。

while (1) {  
  if ((new_sd = lwip_accept(sock, (struct sockaddr *)&remote, (socklen_t *)&size)) > 0) {  
      sys_thread_new("echos",       
process_echo_request,
                    (void*)new_sd,  
                    THREAD_STACKSIZE,  
                    DEFAULT_THREAD_PRIO);  
  }    
}

2.4 process_echo_request函数

位置:echo.c文件,用户需要注意的最重要的函数,发送和接收的移植全部在这个函数

1)接收数据,最大数据长度2048char类型,存储在recv_buff数组中,若接收出错,打印错误信息并退出while

2)若接收到的数据的前4个字符为quit,则退出while

3)将接收到的数据发送出去;

void process_echo_request(void *p)    
{    
  int sd = (int)p;    
  int RECV_BUF_SIZE = 2048;    
  char recv_buf[RECV_BUF_SIZE];    
  int n, nwrote;    


  while (1) {    
    /* read a max of RECV_BUF_SIZE bytes from socket */    
    if ((n = read(sd, recv_buf, RECV_BUF_SIZE)) < 0) {    
      xil_printf("%s: error reading from socket %d, closing socket
", __FUNCTION__, sd);    
      break;    
    }    


    /* break if the recved message = "quit" */    
    if (!strncmp(recv_buf, "quit", 4))    
      break;    


    /* break if client closed connection */    
    if (n <= 0)    
      break;    


    /* handle request */    
    if ((nwrote = write(sd, recv_buf, n)) < 0) {      
      xil_printf("%s: ERROR responding to client echo request. received = %d, written = %d
",    
          __FUNCTION__, n, nwrote);      
      xil_printf("Closing socket %d
", sd);    
      break;    
    }  
  }  


  /* close connection */   
  close(sd);     
  vTaskDelete(NULL);   
}

3.测试网口发送数据

2.4可知,在process_echo_request函数中更改发送即可。新增一个字符数组:

char tx_buf[16]={'H','e','l','l','o',',','W','o','r','l','d','
','
'}; 

在发送完接收到的数据后,新增一个发送函数,即可发送tx_buf数组,长度为16

write(sd, tx_buf, 16);   

9dbde708-6bf9-11ee-939d-92fbcf53809c.png

4.测试网口接收数据并控制LED

在向开发板发送数据时,规定一组特殊数据,如“led0”“led5”“led8”等,前3个字符“led”用于指示这部分数据是用于控制LED的,第4个字符表示点亮组合,四个LED使用二进制编码数据为0~15注意,这里发送的是ASCII字符,在控制LED时需处理成数字(减 ’0’

接收到数据后,仿照函数中对quit字符串的处理方式,新增一个处理,将接收到的字符串与字符串“led”比较,如果收到的字符串的前3个字符是“led”,则使用第4个字符控制LED的亮灭。

strncmp函数,字符串比较函数,字符串大小的比较以ASCII 码表上的顺序来决定。函数声明为int strncmp ( const char * str1, const char * str2, size_t n ),把 str1 str2 进行比较,最多比较前n个字节,若str1str2的前n个字符相同,则返回0;若s1大于s2,则返回大于0的值;若s1 小于s2,则返回小于0的值。

if (!strncmp(recv_buf, "led", 3)) { 
  XGpio_DiscreteWrite(&Gpio_Led, 1, recv_buf[3]-'0'); 
  xil_printf("Led Value =  %d
", recv_buf[3]-'0'); 
} 

9dcbde4e-6bf9-11ee-939d-92fbcf53809c.png

9dda076c-6bf9-11ee-939d-92fbcf53809c.png

5.测试LED任务及消息队列

5.1 包含头文件,声明队列

#include "FreeRTOS.h"  
#include "task.h"  
#include "queue.h"  
#include "timers.h"  
QueueHandle_t xQueue = NULL;

5.2 main函数中创建消息队列

传入两个参数,分别为队列长度和队列中每个元素的长度,xQueueCreate(1,1)表示队列长度为1,队列中的每个元素时一个char类型数据,xQueueCreate(2,15)表示队列长度为2,每个元素都是一个char[15]类型的字符数组。

xQueue = xQueueCreate(1,1);  
/* Check the queue was created. 检查队列是否创建成功*/  
configASSERT( xQueue );

5.3 main函数中创建LED任务,接收队列消息

xTaskCreate( prvPlLedTask,  
            ( const char * ) "PL Led",  
            configMINIMAL_STACK_SIZE,  
            NULL,  
            tskIDLE_PRIORITY + 1,  
            NULL);

其中,调用的prvPlLedTask定义如下,每次从队列中读取一个char类型的数据,若队列为空则等待,若队列不为空则读出后控制LED,注意这里的rece_led_value一定要加取地址符号&,表示传入指针,否则出错

static void prvPlLedTask( void *pvParameters )  
{  
  const TickType_t x1second = pdMS_TO_TICKS( DELAY_1_SECOND );  
  char rece_led_value;  


  for( ;; )  
  {  
    xil_printf( "PL LED task
" );  
    xQueueReceive( xQueue,  /* The queue being read. */  
          &rece_led_value,  /* Data is read into this address. */  
          portMAX_DELAY );  /* 延时 */  


    xil_printf( "PL LED task
" );  
  xil_printf("rece_led_value=%d
",rece_led_value-'0');  
  XGpio_DiscreteWrite(&Gpio_Led, 1, rece_led_value-'0');  


  /* Delay for 1 second. */  
  vTaskDelay( x1second );  
  }  
}

5.4 process_echo_request中添加发送队列消息

若满足条件,则将对LED的控制信息写入队列,注意要加取地址符号&

if (!strncmp(recv_buf, "led", 3)) {  
  xQueueSend(xQueue,  
              &recv_buf[3],  
              0UL );  
}

9df085f0-6bf9-11ee-939d-92fbcf53809c.gif

9e0b9548-6bf9-11ee-939d-92fbcf53809c.png

三、程序固化

1.新建FSBL工程

9e14d540-6bf9-11ee-939d-92fbcf53809c.png

2.生成Boot镜像文件

生成工程后,右键“Create Boot Image,依次添加FSBL工程的elf(默认已添加)、工程的bit文件(默认已添加)、需固化的程序elfAdd找到路径添加),“Create Image”。

9e2959de-6bf9-11ee-939d-92fbcf53809c.png

3.烧录QSPI Flash

选择Image和FSBL的路径,对Flash一定选择“qspi_dual_parallel若选择“qspi_single”也能下载成功,但是无法加载,ZC706板载指示灯亮红灯

9e475222-6bf9-11ee-939d-92fbcf53809c.png

4.配置启动模式

9e6405ca-6bf9-11ee-939d-92fbcf53809c.png

9e6fd56c-6bf9-11ee-939d-92fbcf53809c.png


声明:本文内容及配图由入驻作者撰写或者入驻合作网站授权转载。文章观点仅代表作者本人,不代表电子发烧友网立场。文章及其配图仅供工程师学习之用,如有内容侵权或者其他违规问题,请联系本站处理。 举报投诉
  • ARM
    ARM
    +关注

    关注

    134

    文章

    9084

    浏览量

    367380
  • Zynq
    +关注

    关注

    10

    文章

    609

    浏览量

    47174
  • 千兆网
    +关注

    关注

    0

    文章

    35

    浏览量

    9571

原文标题:ZC706千兆网测试(ZYNQ,FreeRTOS,Echo,lwIP,TCP,RGMII)

文章出处:【微信号:zhuyandz,微信公众号:FPGA之家】欢迎添加关注!文章转载请注明出处。

收藏 人收藏

    评论

    相关推荐

    如何使用Vitis自带的LWIP模板进行PS端千兆以太TCP通信?

    开发板有两路千兆以太,通过RGMII接口连接,本实验演示如何使用Vitis自带的LWIP模板进行PS端千兆以太
    的头像 发表于 04-28 10:44 3381次阅读
    如何使用Vitis自带的<b class='flag-5'>LWIP</b>模板进行PS端<b class='flag-5'>千兆</b>以太<b class='flag-5'>网</b><b class='flag-5'>TCP</b>通信?

    Vivado板文件找不到ZC706

    嗨,我正在使用Vivado 2018.2并拥有ZC706评估套件。启动一个新项目我在板文件中找不到ZC706。看看C:\ Xilinx \ Vivado \ 2018.2 \ data
    发表于 01-03 11:17

    PL DDR是否在ZC706 cachealbe中?

    嗨, 我想知道连接到ZC706板上Zynq的PL部分的外部DDR RAM是否为cachealbe。如果是可缓存的,是否需要任何配置?请帮忙。谢谢。以上来自于谷歌翻译以下为原文Hi,I want
    发表于 03-21 16:56

    是否有可能在ZC706上关闭DDR并仍能加载lwIP

    是否有可能在ZC706上关闭DDR并仍能加载lwIP?我将lwIP mem_size配置为0,将pbuf_pool_size配置为16,然后我就可以构建一个带有库的Hello World应用程序
    发表于 04-25 11:12

    ZC706开发板的SI5324配置方法

    ZC706开发板上的SI5324需要通过I2C配置,官找了一圈,只有VC709和KC705的例程,都是基于MICROBLAZE的,改到ZC706上问题也不大,准备动手这际,转念一想,何不
    发表于 07-05 08:22

    为什么zc706的速度等级会有不同?

    大家好?Afaik,zc706的速度等级为-2 soc。(是的,我手中有zc706板。我检查它的速度等级-2 soc在板上)但是当我在planAhead或xps上选择zc706时,部件号为
    发表于 09-04 08:22

    哪里可以找到Zynq 7000 Zc706 ISE设计套件项目?

    大家好,我在ISE设计套件中找不到使用Board Zynq 7000 ZC706的任何手册。以前我只使用过Digilent Nexys-2 Board。因此,我很难启动Zynq板的使用。你能给我一些建议吗?非常感谢。
    发表于 09-17 09:55

    如何使用Zynq Zc706板作为fpga板?

    我有zc706板,我想用这块板作为FPGA板。我不想用SDK编程我的板我只需要编写一个verilog代码并将此代码发送到Zynq的PL部分是可以只使用没有SDK或Petalinux的Zynq的PL部分。即使有可能你能建议我一些教
    发表于 10-10 09:01

    Vivado 2016.1无法在ZC706中运行?

    你好,我们今天刚刚收到一个ZC706开发套件(带有Zynq XC7Z045),我们非常惊讶,因为在欢迎信中写道:“随着Vivado 2015.4的发布,该产品已被冻结。它将不会在后来的Vivado软件中运行”这应该是什么意思?我们正在使用最新的Vivado版本2016.1
    发表于 10-10 08:24

    vivado Zynq zc706板上使用SFP模块做4.25Gbps怎么实现?

    大家好, 我想在vivado Zynq zc706板上使用SFP模块做4.25Gbps。你能指导我吗?
    发表于 05-22 09:20

    Zynq-7000 AP SoC ZC706评估套件的特点与应用

    观看Zynq-7000 AP SoC ZC706评估套件,这是一款基于收发器的套件,包含所有必需的硬件,工具和IP,可快速完成对基于收发器的嵌入式系统的评估和开发。 董事会给出了
    的头像 发表于 11-20 06:03 5716次阅读

    如何在ZC706中实现千兆配置?

    (1)使用ZC706开发板测试PS端口(EcholwIP协议栈); (2)配合操作PL端LED(直接驱动和使用消息队列两种方式); (3
    的头像 发表于 04-02 16:49 3776次阅读
    如何在<b class='flag-5'>ZC706</b>中实现<b class='flag-5'>千兆</b><b class='flag-5'>网</b>配置?

    Zynq-7000全可编程SoC ZC706评估套件(ISE Design Suite 14.5)入门指南

    Zynq-7000全可编程SoC ZC706评估套件(ISE Design Suite 14.5)入门指南
    发表于 05-19 14:20 20次下载
    <b class='flag-5'>Zynq</b>-7000全可编程SoC <b class='flag-5'>ZC706</b>评估套件(ISE Design Suite 14.5)入门指南

    ADC-FMC插入器&Xilinx ZC706参考设计

    ADC-FMC插入器&Xilinx ZC706参考设计
    发表于 05-21 20:37 11次下载
    ADC-FMC插入器&Xilinx <b class='flag-5'>ZC706</b>参考设计

    ZC706千兆测试

    ZC706中,MAC 控制器与 PHY 通过 RGMII(Reduced Gigabit Media Independent Interface)接口进行连接,实现千兆
    的头像 发表于 06-21 10:03 1944次阅读
    <b class='flag-5'>ZC706</b><b class='flag-5'>千兆</b><b class='flag-5'>网</b><b class='flag-5'>测试</b>