zcu106 lwip搭建以太网配置寄存器
创始人
2024-03-07 15:23:45

文章目录

        • 实验一
          • 1.配置网口GEM3
          • 2.导出xsa文件,在vitis中创建工程,选择freertos10_xilinx的操作系统来使用
          • 3.配置lwip211,选择SOCKET API的模式
          • 4.创建工程 选择FreeRTOS Iwip TCP Perf Server模板
          • 5.代码分析
            • main.c
            • freertos_tcp_perf_server.c
            • freertos_tcp_perf_server.h
          • 6.流程梳理
          • 7.网络测试
        • 实验二
          • 1.配置block design
          • 2.配置conf_list核,存放在lwip_tcp.ipdef/conf_reg_list下面
          • 3.vitis开发
            • conf_list.h
            • conf_list.c
            • freertos_tcp_perf_server.c
          • 4.实验结果

实验一

1.配置网口GEM3

image-20221130154415671

2.导出xsa文件,在vitis中创建工程,选择freertos10_xilinx的操作系统来使用

image-20221130190131167

3.配置lwip211,选择SOCKET API的模式

image-20221130161930948

4.创建工程 选择FreeRTOS Iwip TCP Perf Server模板

image-20221130163247489

5.代码分析
main.c

配置服务器端的ip地址 掩码 网关

#define DEFAULT_IP_ADDRESS "192.168.137.11"  //IP
#define DEFAULT_IP_MASK "255.255.255.0"    //掩码
#define DEFAULT_GW_ADDRESS "192.168.1.1"   //网关

main函数使用sys_thread_new新建了一个线程调用了main_thread,使用vTaskStartScheduler启动任务调度。

int main()
{main_thread_handle = sys_thread_new("main_thread", main_thread, 0,THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);vTaskStartScheduler();while(1);return 0;
}

main_thread函数调用其他线程network_thread

void main_thread(void *p)
{
#if ((LWIP_IPV6==0) && (LWIP_DHCP==1))int mscnt = 0;
#endif#ifdef XPS_BOARD_ZCU102IicPhyReset();
#endif/* initialize lwIP before calling sys_thread_new */lwip_init();   /* 初始化lwip *//* any thread using lwIP should be created using sys_thread_new */sys_thread_new("nw_thread", network_thread, NULL,THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);/* 申请线程network_thread  *//* Suspend Task until auto-negotiation is completed */if (!complete_nw_thread)vTaskSuspend(NULL);#if LWIP_IPV6==0
#if LWIP_DHCP==1   /* 默认不开启DHCP */while (1) {vTaskDelay(DHCP_FINE_TIMER_MSECS / portTICK_RATE_MS);if (server_netif.ip_addr.addr) {xil_printf("DHCP request success\r\n");break;}mscnt += DHCP_FINE_TIMER_MSECS;if (mscnt >= 10000) {xil_printf("ERROR: DHCP request timed out\r\n");assign_default_ip(&(server_netif.ip_addr),&(server_netif.netmask),&(server_netif.gw));break;}}#elseassign_default_ip(&(server_netif.ip_addr), &(server_netif.netmask),&(server_netif.gw));
#endifprint_ip_settings(&(server_netif.ip_addr), &(server_netif.netmask),&(server_netif.gw));   /* 打印IP的有关信息 */
#endif /* LWIP_IPV6 */xil_printf("\r\n");/* print all application headers */print_app_header();  /* 打印连接的端口,打印提示*/xil_printf("\r\n");/* start the application*/start_application(); /* 运行应用 */vTaskDelete(NULL);return;
}

network_thread函数配置lwip网络连接

void network_thread(void *p)
{
#if ((LWIP_IPV6==0) && (LWIP_DHCP==1))int mscnt = 0;
#endif/* the mac address of the board. this should be unique per board */u8_t mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };/* 配置MAC地址 */xil_printf("\n\r\n\r");xil_printf("-----lwIP Socket Mode TCP Server Application------\r\n");/* Add network interface to the netif_list, and set it as default */if (!xemac_add(&server_netif, NULL, NULL, NULL, mac_ethernet_address,PLATFORM_EMAC_BASEADDR)) {xil_printf("Error adding N/W interface\r\n");return;}/* 将mac地址加入netif_list */#if LWIP_IPV6==1server_netif.ip6_autoconfig_enabled = 1;netif_create_ip6_linklocal_address(&server_netif, 1);netif_ip6_addr_set_state(&server_netif, 0, IP6_ADDR_VALID);print_ipv6("\n\rlink local IPv6 address is:",&server_netif.ip6_addr[0]);
#endif /* LWIP_IPV6 */netif_set_default(&server_netif);/* specify that the network if is up */netif_set_up(&server_netif);   /* 设置为默认的network *//* start packet receive thread - required for lwIP operation */sys_thread_new("xemacif_input_thread",(void(*)(void*))xemacif_input_thread, &server_netif,THREAD_STACKSIZE, DEFAULT_THREAD_PRIO);/* 开启packet的接受线程xemacif_input_thread */complete_nw_thread = 1;/* Resume the main thread; auto-negotiation is completed */vTaskResume(main_thread_handle);/* 恢复主线程,自动协商恢复 */#if ((LWIP_IPV6==0) && (LWIP_DHCP==1))dhcp_start(&server_netif);while (1) {vTaskDelay(DHCP_FINE_TIMER_MSECS / portTICK_RATE_MS);dhcp_fine_tmr();mscnt += DHCP_FINE_TIMER_MSECS;if (mscnt >= DHCP_COARSE_TIMER_SECS*1000) {dhcp_coarse_tmr();mscnt = 0;}}
#elsevTaskDelete(NULL);
#endif
}
freertos_tcp_perf_server.c

start_application函数是执行时的数据传输

void start_application(void)
{int sock, new_sd;
#if LWIP_IPV6==1struct sockaddr_in6 address, remote;
#elsestruct sockaddr_in address, remote;
#endif /* LWIP_IPV6 */int size;/* set up address to connect to */memset(&address, 0, sizeof(address));
#if LWIP_IPV6==1if ((sock = lwip_socket(AF_INET6, SOCK_STREAM, 0)) < 0) {xil_printf("TCP server: Error creating Socket\r\n");return;}address.sin6_family = AF_INET6;address.sin6_port = htons(TCP_CONN_PORT);address.sin6_len = sizeof(address);
#elseif ((sock = lwip_socket(AF_INET, SOCK_STREAM, 0)) < 0) {xil_printf("TCP server: Error creating Socket\r\n");return;}address.sin_family = AF_INET;address.sin_port = htons(TCP_CONN_PORT);address.sin_addr.s_addr = INADDR_ANY;/* 设置socket的套接字网络连接 */
#endif /* LWIP_IPV6 */if (bind(sock, (struct sockaddr *)&address, sizeof (address)) < 0) {xil_printf("TCP server: Unable to bind to port %d\r\n",TCP_CONN_PORT);close(sock);return;}/* bind函数 */if (listen(sock, 1) < 0) {xil_printf("TCP server: tcp_listen failed\r\n");close(sock);return;}/* listen监听函数实现 */size = sizeof(remote);while (1) {if ((new_sd = accept(sock, (struct sockaddr *)&remote,(socklen_t *)&size)) > 0)sys_thread_new("TCP_recv_perf thread",tcp_recv_perf_traffic, (void*)&new_sd,TCP_SERVER_THREAD_STACKSIZE,DEFAULT_THREAD_PRIO);/* accept函数接受客户端网络连接,开启一个新的线程*/}
}

tcp_recv_perf_traffic函数执行数据传输

/* thread spawned for each connection */
void tcp_recv_perf_traffic(void *p)
{char recv_buf[RECV_BUF_SIZE];int read_bytes;int sock = *((int *)p);server.start_time = sys_now() * portTICK_RATE_MS;server.client_id++;server.i_report.last_report_time = 0;server.i_report.start_time = 0;server.i_report.total_bytes = 0;server.total_bytes = 0;print_tcp_conn_stats(sock);  /* 打印TCP*/while (1) {/* read a max of RECV_BUF_SIZE bytes from socket */if ((read_bytes = lwip_recvfrom(sock, recv_buf, RECV_BUF_SIZE,0, NULL, NULL)) < 0) {u64_t now = sys_now() * portTICK_RATE_MS;u64_t diff_ms = now - server.start_time;tcp_conn_report(diff_ms, TCP_ABORTED_REMOTE);break;}/* lwip_recvfrom接受1500字节的数据*//* break if client closed connection */if (read_bytes == 0) {u64_t now = sys_now() * portTICK_RATE_MS;u64_t diff_ms = now - server.start_time;tcp_conn_report(diff_ms, TCP_DONE_SERVER);xil_printf("TCP test passed Successfully\n\r");break;}/* 如果接受数据大小为0,说明TCP测试已经通过了 */if (REPORT_INTERVAL_TIME) {u64_t now = sys_now() * portTICK_RATE_MS;server.i_report.total_bytes += read_bytes;if (server.i_report.start_time) {u64_t diff_ms = now - server.i_report.start_time;if (diff_ms >= REPORT_INTERVAL_TIME) {tcp_conn_report(diff_ms, INTER_REPORT);server.i_report.start_time = 0;server.i_report.total_bytes = 0;}} else {server.i_report.start_time = now;}}/* Record total bytes for final report *//* 记录接受的总数据量大小 */server.total_bytes += read_bytes;}/* close connection */close(sock);vTaskDelete(NULL);
}
freertos_tcp_perf_server.h

服务器端使用的端口号是5001

/* server port to listen on/connect to */
#define TCP_CONN_PORT 5001
6.流程梳理
main_thread_handle
-> main_thread(lwip_init) -> network_thread-> start_application->lwip_socket(bind listen accept)-> tcp_recv_perf_traffic->lwip_recvfrom
7.网络测试
ping 192.168.137.11 -t  //循环ping目标iperf -c 192.168.137.10 -p 5001 -i 5 -t 30 -w 2M
-c 客户端连接服务器的ip
-p 服务端的端口号
-i 打印带宽的时间间隔
-t 测试带宽时间为30s
-w 使用的包窗口大小

image-20221130185725992

从图中可见,网速大小可以达到85Mbits/sec左右,大概是百兆以太网的速度大小,可以在lwip那里修改一些参数去调大它。

实验二

1.配置block design

AXI_HPM0 FPD interface 32位

image-20221130215724334

image-20221130221234812

2.配置conf_list核,存放在lwip_tcp.ipdef/conf_reg_list下面

在这里插入图片描述

conf_list_v1_0_S00_AXI.v

(// Users to add ports hereoutput reg[31:0] hdmi_bit_sel,output reg[31:0] img_width,output reg[31:0] img_high,// User ports ends// Do not modify the ports beyond this line
// Add user logic herealways @(posedge S_AXI_ACLK) beginif ( S_AXI_ARESETN == 1'b0 ) beginhdmi_bit_sel <= 0;img_width <= 0;img_high <= 0;endelse beginhdmi_bit_sel <= slv_reg0;img_width <= slv_reg1;img_high <= slv_reg2;endend// User logic ends

conf_list_v1_0.v

// Users to add ports hereoutput wire[31:0] hdmi_bit_sel,output wire[31:0] img_width,output wire[31:0] img_high,// User ports ends// Do not modify the ports beyond this line
// Instantiation of Axi Bus Interface S00_AXIconf_list_v1_0_S00_AXI # ( .C_S_AXI_DATA_WIDTH(C_S00_AXI_DATA_WIDTH),.C_S_AXI_ADDR_WIDTH(C_S00_AXI_ADDR_WIDTH)) conf_list_v1_0_S00_AXI_inst (.hdmi_bit_sel(hdmi_bit_sel),.img_width(img_width),.img_high(img_high),.S_AXI_ACLK(s00_axi_aclk),
3.vitis开发

lwip_send(int s, const void* dataptr, size_t size,int flags)

其中s是socket,dataptr是数据,size是数据大小,flag默认为0

需要判断收到的数据的前8位都是55,然后把对应地址的数据取出来放到对应的IP里面

conf_list.h
#include "Xil_io.h"#define CONF_LIST_mWriteReg(BaseAddress, RegOffset, Data) \
Xil_Out32((BaseAddress) + (RegOffset), (u32)(Data))#define CONF_LIST_mReadReg(BaseAddress, RegOffset) \
Xil_In32((BaseAddress) + (RegOffset))void write_conf_list(u32 BaseAddr, u32 RegAddr, u32 Data);
u32 read_conf_list(u32 BaseAddr, u32 RegAddr);
conf_list.c
#include "conf_list.h"void write_conf_list(u32 BaseAddr, u32 RegAddr, u32 Data)
{CONF_LIST_mWriteReg(BaseAddr, RegAddr<<2,Data); //RegAddr*4
}u32 read_conf_list(u32 BaseAddr, u32 RegAddr)
{return CONF_LIST_mReadReg(BaseAddr, RegAddr<<2); //RegAddr*4
}
freertos_tcp_perf_server.c
#include "conf_list.h"
#include "Xil_io.h"
#define REGBASEADDR 0X00A0000000u32 imagewidth;
u32 imagehigh;
u32 readback; //0表示写,1表示读void tcp_recv_perf_traffic(void *p) {//lwip_send(sock, recv_buf, 14, 0);if(recv_buf[0] == 0x55 && recv_buf[1] == 0x55 && recv_buf[2] == 0x55 && recv_buf[3] == 0x55 && recv_buf[4] == 0x55 && recv_buf[5] == 0x55 && recv_buf[6] == 0x55 && recv_buf[7] == 0x55){u32 regaddr;u8 rwnflag;u32 regdata;regaddr = recv_buf[8];rwnflag = recv_buf[9];if(rwnflag == 0) {//write registerregdata = recv_buf[10]<<24;regdata |= recv_buf[11]<<16;regdata |= recv_buf[12]<<8;regdata |= recv_buf[13]<<0;if(regaddr == 1)imagewidth = regdata;else if(regaddr == 2)imagehigh = regdata;else if(regaddr == 3)readback = regdata;write_conf_list(REGBASEADDR, regaddr, regdata);regdata = read_conf_list(REGBASEADDR, regaddr);recv_buf[10] = (regdata>>24) & 0XFF;recv_buf[11] = (regdata>>16) & 0XFF;recv_buf[12] = (regdata>>8) & 0XFF;recv_buf[13] = (regdata>>0) & 0XFF;if(lwip_send(sock,recv_buf,read_bytes,0) < 0){xil_printf("%s: Send Error!\r\n", sock);}}else {//read registerregdata = read_conf_list(REGBASEADDR, regaddr);recv_buf[10] = (regdata>>24) & 0XFF;recv_buf[11] = (regdata>>16) & 0XFF;recv_buf[12] = (regdata>>8) & 0XFF;recv_buf[13] = (regdata>>0) & 0XFF;if(lwip_send(sock,recv_buf,read_bytes,0) < 0){xil_printf("%s: Send Error!\r\n", sock);}}}
if(read_byte == 0)
4.实验结果

image-20221201170040853

能够通过网口去修改hdmi_bit_sel,img_width以及img_high。

上一篇:MySQL——进阶

下一篇:Cookie Session JSP

相关内容

热门资讯

猫咪吃了塑料袋怎么办 猫咪误食... 你知道吗?塑料袋放久了会长猫哦!要说猫咪对塑料袋的喜爱程度完完全全可以媲美纸箱家里只要一有塑料袋的响...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
世界上最漂亮的人 世界上最漂亮... 此前在某网上,选出了全球265万颜值姣好的女性。从这些数量庞大的女性群体中,人们投票选出了心目中最美...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...
长白山自助游攻略 吉林长白山游... 昨天介绍了西坡的景点详细请看链接:一个人的旅行,据说能看到长白山天池全凭运气,您的运气如何?今日介绍...
脚上的穴位图 脚面经络图对应的... 人体穴位作用图解大全更清晰直观的标注了各个人体穴位的作用,包括头部穴位图、胸部穴位图、背部穴位图、胳...
demo什么意思 demo版本... 618快到了,各位的小金库大概也在准备开闸放水了吧。没有小金库的,也该向老婆撒娇卖萌服个软了,一切只...
埃菲尔铁塔在哪 中国仿建埃菲尔... 2019年4月26日,广西南宁市,街头惊现一座巨型山寨版埃菲尔铁塔,高约20米,白色塔身,造型逼真,...
苗族的传统节日 贵州苗族节日有... 【岜沙苗族芦笙节】岜沙,苗语叫“分送”,距从江县城7.5公里,是世界上最崇拜树木并以树为神的枪手部落...
北京的名胜古迹 北京最著名的景... 北京从元代开始,逐渐走上帝国首都的道路,先是成为大辽朝五大首都之一的南京城,随着金灭辽,金代从海陵王...
应用未安装解决办法 平板应用未... ---IT小技术,每天Get一个小技能!一、前言描述苹果IPad2居然不能安装怎么办?与此IPad不...