1 测试平台搭建
搭建过程请参考我的另一篇blog的过程:“
具体参考github:
请参考另一篇blog:
xemacif_input(echo_netif);
根据上面的这句话,其实际上的作用是将mac层的数据读入到lwip
当中去,根据另外一篇blog 的内容:
也对这句话进行了说明了原因。
第二次测试的结果,通过计数这个时候共有接收到了多少个数据包
我们将延时降低,出现内存错误的地方显然在已经传输额了很多数据之后才出现了,这个时候也验证了上面那一节blog 所提到的原因,此时能够有快频率的将mac中的队列包读入lwip堆栈中。
这样的测试结论,可仍然见我的另一篇blog:
'''
子系统自身信息:
IP:192.168.127.11
slave:11
port:5001子系统需要检测的信息
电源电压采样 value1:05 03 07 data crc1 crc2----registerid=07 datatype=float
电源电流采样 value1:05 03 08 data crc1 crc2----registerid=08 datatype=float'''import threading
import zmq
import time
import socket
import datetime
import struct
HWM_VAL = 100000*60*31*5HWM_VAL = 100000def zmq_recv(context, url):socket = context.socket(zmq.SUB)# socket = context.socket(zmq.t(url)socket.setsockopt(zmq.SUBSCRIBE, ''.encode('utf-8')) # 接收所有消息zhanbao = 0buzhanbao = 0start_time = time.clock()while True:b = v();# socket.send(b'1')# print(b)end_time = time.clock()if len(b) == 1:# print('总计耗时',end_time-start_time)breaksize = len(b)# print(size)# if end_time-start_time > 10:# pass# breakif size > 10:zhanbao = zhanbao + 1else:buzhanbao = buzhanbao + 1print('接收不粘包', buzhanbao)print('接收粘包', zhanbao)def set_keepalive_linux(sock, after_idle_sec=1, interval_sec=3, max_fails=5):"""Set TCP keepalive on an open socket.It activates after 1 second (after_idle_sec) of idleness,then sends a keepalive ping once every 3 seconds (interval_sec),and closes the connection after 5 failed ping (max_fails), or 15 seconds"""sock.setsockopt(socket.SOL_SOCKET, socket.SO_KEEPALIVE, 1)sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPIDLE, after_idle_sec)sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPINTVL, interval_sec)sock.setsockopt(socket.IPPROTO_TCP, socket.TCP_KEEPCNT, max_fails)return sockdef tcp_recv_zmq_send(context, sub_server_addr, syncaddr, down_computer_addr, port):# socketzmq = context.socket(zmq.PUB)# socketzmq.bind("tcp://115.156.162.76:6000")reveiver_url = "ipc://11_Router"socketzmq = context.socket(zmq.ROUTER)socketzmq.set_hwm(HWM_VAL)# t(reveiver_url)sendinglist=[]# client = context.socket(zmq.ROUTER)# 为了定义一个对象线程# 创建一个socket:# tcp_server_socket = socket.socket(socket.AF_INET,socket.SOCK_STREAM)#创建套接字# tcp_server_socket.bind((down_computer_addr,port))#绑定本机地址和接收端口# tcp_server_socket.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,True)# tcp_server_socket.listen(1)#监听()内为最大监听值# # tcp_server_socket = set_keepalive_linux(tcp_server_socket)## s,s_addr= tcp_server_socket.accept()#建立连接(accept(无参数)# s = set_keepalive_linuZZ8888888888888888888888;Bx(s)client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 建立连接,这个建立的是tcp的链接# client_socket.setsockopt(socket.IPPROTO_TCP,socket.TCP_NODELAY,True)IP_Server='192.168.127.202'Port=t((IP_Server,Port))# s.connect(('192.168.127.5', 5001))print('we have connected to the tcp data send server!---port is :', port)packagenum = 0zhanbao = 0buzhanbao = 0start_time_perf = time.perf_counter()start_time_process = time.process_time()count = 0# 实际上应当启用的市多线程来做这些事情的# 每一个线程要做的事情就是接收对应的内容# 我想epics里面做的也是基本想同样的事情 ---最后写一个自动化的脚本多线程start_flag = Truewhile True:# try: #许久没有接收到下位机来的消息,首先会有一个keep alive 的数据包的出现,如果太久没有了就直接关闭当前socketb = v(10)print('I',count)if count==1000000:break# size = len(b)count = count + 1# timestample = str(w()).encode()# b = b + timestample## sendinglist.append(b)# print('Sending list size ',len(sendinglist))print(packagenum)end_time_perf = time.perf_counter()end_time_process = time.process_time()print('Receiving port is: ', port)print('Package num:', count)print('receing time cost:', end_time_perf - start_time_perf) ## print('tcp接收不粘包', buzhanbao)# print('tcp接收粘包', zhanbao)# socketzmq.send(b)socketzmq.close()s.close()tcp_server_socket.close()if __name__ == '__main__':print('Kaishile ')context = zmq.Context() # 这个上下文是真的迷,到底什么情况下要用共同的上下文,什么时候用单独的上下文,找时间测试清楚sub_server_addr = "tcp://115.156.162.123:6000"syncaddr = "tcp://115.156.162.76:5555"down_computer_addr = '115.156.163.107'# down_computer_addr = '127.0.0.1'down_computer_addr = '192.168.127.11'down_computer_addr = '192.168.127.100'down_computer_addr = '127.0.0.1'# sub_server_addr = "tcp://127.0.0.1:6001"sub_server_addr = "tcp://192.168.127.100:6002"# syncaddr = "tcp://127.0.0.1:5555"syncaddr = "tcp://192.168.127.100:5556"port = [5001, 5002, 5003, 5004, 5005, 5006, 5007, 5008, 5009, 5010]tcp_recv_zmq_send(context,sub_server_addr,syncaddr,down_computer_addr,5011)# for i in port:# t2 = threading.Thread(target=tcp_recv_zmq_send,# args=(context, sub_server_addr, syncaddr, down_computer_addr, port))# t2.start()
由于测试中包含大量的xil_print信息,导致实际数据上传的速度并未达到每隔10us上传的速度。
上位机仅仅接收到199个数据包的时候就出现了tcp_write报错,即内存溢出的错误:
第二次测试的结果:
–update- on 2020-06-01
根本原因溯源
我们看到我们串口打印的数据的实际上出现在tcp_write 这句话的函数上面。如下:
进一步查看tcpwrite 中报错具体是哪一句话:
进一步查看tcp_write_check 函数的报错
通过上面图片中的代码,我们可以得出的两点原因如下:
原因1:由于发送的数据太多。
原因2:在未发送或者未确认的队列中的pubfs 的总数,超过了所配置的大小;
我们看一下上面代码中的 TCP_SND_QUEUELEN的定义:
pcb->snd_queuelen >= TCP_SND_QUEUELEN
查看定义:
我们再进而查看:lwip的配置界面:
通是修改memp_n_pbuf的大小,将从原来默认的16,变成1600,再次进行tcp的数据的测试。
情况并没有出现改观。
上网进行查询了一下如下是几个参考链接:
没有结论:=1
这篇转载的的文章提到提高发缓冲区的大小:
这篇blog:
给出了一个比较明确的答案,也跟我们上面的结论是一样的。
修改代码位置:
测试结修改前:16 * TCP_SND_BUF)/TCP_MSS
测试修改后:
代码编译报错:
调整如下大小:
测试结果:
-------------未完待续---------------------
—update on 2020 - 06 -02
.html
这篇blog 中提到了,参数回调的方式。
由于博主之前参考zynq 示例的时候有zynq2018 版本的sdk中,有一个tcp_perf的例程,而其在这个过程中采用的就是函数回调的方式。
/******************************************************************************
*
* Copyright (C) 2018 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************//* Connection handle for a TCP Client session */#include "tcp_perf_client.h"
//pcb = protocol control blockstatic struct tcp_pcb *c_pcb;
static char send_buf[TCP_SEND_BUFSIZE];
static struct perf_stats client;void print_app_header()
{
#if LWIP_IPV6==1xil_printf("TCP client connecting to %s on port %drn",TCP_SERVER_IPV6_ADDRESS, TCP_CONN_PORT);xil_printf("On Host: Run $iperf -V -s -i %d -w 2Mrn",INTERIM_REPORT_INTERVAL);
#elsexil_printf("TCP client connecting to %s on port %drn",TCP_SERVER_IP_ADDRESS, TCP_CONN_PORT);xil_printf("On Host: Run $iperf -s -i %d -w 2Mrn",INTERIM_REPORT_INTERVAL);
#endif /* LWIP_IPV6 */
}static void print_tcp_conn_stats()
{
#if LWIP_IPv6==1xil_printf("[%3d] local %s port %d connected with ",client.client_id, inet6_ntoa(c_pcb->local_ip),c_pcb->local_port);xil_printf("%s port %drn",inet6_ntoa(c_pcb->remote_ip),c_pcb->remote_port);
#elsexil_printf("[%3d] local %s port %d connected with ",client.client_id, inet_ntoa(c_pcb->local_ip),c_pcb->local_port);xil_printf("%s port %drn",inet_ntoa(c_pcb->remote_ip),c_pcb->remote_port);
#endif /* LWIP_IPV6 */xil_printf("[ ID] IntervalttTransfer Bandwidthnr");
}static void stats_buffer(char* outString,double data, enum measure_t type)
{int conv = KCONV_UNIT;const char *format;double unit = 1024.0;if (type == SPEED)unit = 1000.0;while (data >= unit && conv <= KCONV_GIGA) {data /= unit;conv++;}/* Fit data in 4 places */if (data < 9.995) { /* 9.995 rounded to 10.0 */format = "%4.2f %c"; /* #.## */} else if (data < 99.95) { /* 99.95 rounded to 100 */format = "%4.1f %c"; /* ##.# */} else {format = "%4.0f %c"; /* #### */}sprintf(outString, format, data, kLabel[conv]);
}/** The report function of a TCP client session */
static void tcp_conn_report(u64_t diff,enum report_type report_type)
{u64_t total_len;double duration, bandwidth = 0;char data[16], perf[16], time[64];if (report_type == INTER_REPORT) {total_len = client.al_bytes;} else {client.i_report.last_report_time = 0;total_len = al_bytes;}/* Converting duration from milliseconds to secs,* and bandwidth to bits/sec .*/duration = diff / 1000.0; /* secs */if (duration)bandwidth = (total_len / duration) * 8.0;stats_buffer(data, total_len, BYTES);stats_buffer(perf, bandwidth, SPEED);/* On 32-bit platforms, xil_printf is not able to print* u64_t values, so converting these values in strings and* displaying results*/sprintf(time, "%4.1f-%4.1f sec",(double)client.i_report.last_report_time,(double)(client.i_report.last_report_time + duration));xil_printf("[%3d] %s %sBytes %sbits/secnr", client.client_id,time, data, perf);if (report_type == INTER_REPORT)client.i_report.last_report_time += duration;
}/** Close a tcp session */
static void tcp_client_close(struct tcp_pcb *pcb)
{err_t err;if (pcb != NULL) {tcp_sent(pcb, NULL);tcp_err(pcb, NULL);err = tcp_close(pcb);if (err != ERR_OK) {/* Free memory with abort */tcp_abort(pcb);}}
}/** Error callback, tcp session aborted */
static void tcp_client_err(void *arg, err_t err)
{LWIP_UNUSED_ARG(err);u64_t now = get_time_ms();u64_t diff_ms = now - client.start_time;tcp_client_close(c_pcb);c_pcb = NULL;tcp_conn_report(diff_ms, TCP_ABORTED_REMOTE);xil_printf("TCP connection aborted %dnr",err);}static err_t tcp_send_perf_traffic(void)
{err_t err;u8_t apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;if (c_pcb == NULL) {return ERR_CONN;}#ifdef __MICROBLAZE__/* Zero-copy pbufs is used to get maximum performance for Microblaze.* For Zynq A9, ZynqMP A53 and R5 zero-copy pbufs does not give* significant improvement hense not used. */apiflags = 0;
#endifwhile (tcp_sndbuf(c_pcb) > TCP_SEND_BUFSIZE) {send_buf[0]='i';send_buf[1]='a';send_buf[2]='m';send_buf[3]='a';send_buf[4]='g';send_buf[5]='o';send_buf[6]='o';send_buf[7]='d';send_buf[8]='m';send_buf[9]='a';send_buf[10]='n';err = tcp_write(c_pcb, send_buf, TCP_SEND_BUFSIZE, apiflags);if (err != ERR_OK) {xil_printf("TCP client: Error on tcp_write: %drn",err);return err;}err = tcp_output(c_pcb);if (err != ERR_OK) {xil_printf("TCP client: Error on tcp_output: %drn",err);return err;}al_bytes += TCP_SEND_BUFSIZE;client.al_bytes += TCP_SEND_BUFSIZE;}if (d_time || client.port_interval_time) {u64_t now = get_time_ms();if (client.port_interval_time) {if (client.i_report.start_time) {u64_t diff_ms = now - client.i_report.start_time;u64_t rtime_ms = client.port_interval_time;if (diff_ms >= rtime_ms) {tcp_conn_report(diff_ms, INTER_REPORT);client.i_report.start_time = 0;client.al_bytes = 0;}} else {client.i_report.start_time = now;}}if (d_time) {/* this session is time-limited */u64_t diff_ms = now - client.start_time;if (diff_ms >= d_time) {/* time specified is over,* close the connection */tcp_conn_report(diff_ms, TCP_DONE_CLIENT);xil_printf("TCP test passed Successfullynr");tcp_client_close(c_pcb);c_pcb = NULL;return ERR_OK;}}}return ERR_OK;
}static err_t tcp_send_hello_traffic(void)
{err_t err;u8_t apiflags = TCP_WRITE_FLAG_COPY | TCP_WRITE_FLAG_MORE;if (c_pcb == NULL) {return ERR_CONN;}#ifdef __MICROBLAZE__/* Zero-copy pbufs is used to get maximum performance for Microblaze.* For Zynq A9, ZynqMP A53 and R5 zero-copy pbufs does not give* significant improvement hense not used. */apiflags = 0;
#endifsend_buf[0]='h';send_buf[1]='e';send_buf[2]='l';send_buf[3]='l';send_buf[4]='o';send_buf[5]='w';send_buf[6]='o';send_buf[7]='r';send_buf[8]='l';send_buf[9]='d';send_buf[10]='!';err = tcp_write(c_pcb, send_buf, TCP_SEND_BUFSIZE, apiflags);if (err != ERR_OK) {xil_printf("TCP client: Error on tcp_write: %drn",err);return err;}err = tcp_output(c_pcb);if (err != ERR_OK) {xil_printf("TCP client: Error on tcp_output: %drn",err);return err;}al_bytes += TCP_SEND_BUFSIZE;client.al_bytes += TCP_SEND_BUFSIZE;xil_printf("we are sending in hello traffic!");
//
// if (d_time || client.port_interval_time) {
// u64_t now = get_time_ms();
// if (client.port_interval_time) {
// if (client.i_report.start_time) {
// u64_t diff_ms = now - client.i_report.start_time;
// u64_t rtime_ms = client.port_interval_time;
// if (diff_ms >= rtime_ms) {
// tcp_conn_report(diff_ms, INTER_REPORT);
// client.i_report.start_time = 0;
// client.al_bytes = 0;
// }
// } else {
// client.i_report.start_time = now;
// }
// }
//
// if (d_time) {
// /* this session is time-limited */
// u64_t diff_ms = now - client.start_time;
// if (diff_ms >= d_time) {
// /* time specified is over,
// * close the connection */
// tcp_conn_report(diff_ms, TCP_DONE_CLIENT);
// xil_printf("TCP test passed Successfullynr");
// tcp_client_close(c_pcb);
// c_pcb = NULL;
// return ERR_OK;
// }
// }
// }return ERR_OK;
}/** TCP sent callback, try to send more data */
static err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{xil_printf("we have sent the package rn");// return tcp_send_perf_traffic();return ERR_OK;
}/** TCP connected callback (active connection), send data now */
static err_t tcp_client_connected(void *arg, struct tcp_pcb *tpcb, err_t err)
{xil_printf("we are 回调!rn");if (err != ERR_OK) {tcp_client_close(tpcb);xil_printf("Connection errornr");return err;}xil_printf("we have connected to the server!rn");/* store state */c_pcb = tpcb;tcp_nagle_disable(c_pcb);client.start_time = get_time_ms();d_time = TCP_TIME_INTERVAL * 1000; /* ms */client.client_id++;al_bytes = 0;/* report interval time in ms */client.port_interval_time = INTERIM_REPORT_INTERVAL * 1000;client.i_report.last_report_time = 0;client.i_report.start_time = 0;client.al_bytes = 0;print_tcp_conn_stats();/* set callback values & functions */tcp_arg(c_pcb, NULL);tcp_sent(c_pcb, tcp_client_sent);tcp_err(c_pcb, tcp_client_err);/* initiate data transfer */return ERR_OK;
}void transfer_data(void)
{if (client.client_id)//tcp_send_perf_traffic();tcp_send_hello_traffic();
}void start_application(void)
{err_t err;struct tcp_pcb* pcb;ip_addr_t remote_addr;u32_t i;xil_printf("WE ARE AT start appklication!!!rn");
#if LWIP_IPV6==pe= IPADDR_TYPE_V6;err = inet6_aton(TCP_SERVER_IPV6_ADDRESS, &remote_addr);
#elseerr = inet_aton(TCP_SERVER_IP_ADDRESS, &remote_addr);
#endif /* LWIP_IPV6 */if (!err) {xil_printf("Invalid Server IP address: %drn", err);return;}/* Create Client PCB */pcb = tcp_new_ip_type(IPADDR_TYPE_ANY);if (!pcb) {xil_printf("Error in PCB creation. out of memoryrn");return;}err = tcp_connect(pcb, &remote_addr, TCP_CONN_PORT,tcp_client_connected);if (err) {xil_printf("Error on tcp_connect: %drn", err);tcp_client_close(pcb);return;}client.client_id = 0;xil_printf("err status , %drn",err);xil_printf("WE have connected to the server and ready to sendrn");/* initialize data buffer being sent with same as used in iperf */
// for (i = 0; i < TCP_SEND_BUFSIZE; i++)
// send_buf[i] = (i % 10) + 'a';//这个就相当于ascill数据码,发出去的时候,再解析。是不是我每次更新这个sendbuf 就会从新更新
// 当我们将TCP_send_buffsize 设定5 就表示每次发送前面三个字节,它是怎么指导我每次发送多少个呢??????哪个机制导致了我发送的呢???//实际上,我们可以认为这个地方只算是把数据防盗我们的发送缓冲区的部分, 实际上,是由其他的某个地方实现的数据得发送//send_buf[i] = (i % 10) + '0';return;
}
上面是zynq开发板作为perf 客户端
迁移后的echo.c 文件:
/******************************************************************************
*
* Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/#include <stdio.h>
#include <string.h>
#include "sleep.h"#include "lwip/err.h"
#include "lwip/tcp.h"
#if defined (__arm__) || defined (__aarch64__)
#include "xil_printf.h"
#endif
static struct tcp_pcb *connected_pcb = NULL;
char sendBuffer[10]="HELLOWORLD";
volatile unsigned tcp_client_connected = 0;err_t transfer_data() {err_t err;struct tcp_pcb *tpcb = connected_pcb;//xil_printf("we ccan in transfer datarn", err);if (!connected_pcb)return ERR_OK;err = tcp_write(tpcb, sendBuffer, 10, 3);if (err != ERR_OK) {xil_printf("txperf: Error on tcp_write: %drn", err);connected_pcb = NULL;return err;}err = tcp_output(tpcb);if (err != ERR_OK) {xil_printf("txperf: Error on tcp_output: %drn",err);return err;}return ERR_OK;
}
/** Error callback, tcp session aborted */
static void tcp_client_err(void *arg, err_t err)
{xil_printf("TCP connection aborted %dnr",err);}
void print_app_header()
{xil_printf("nrnr-----lwIP TCP echo server ------nr");xil_printf("TCP packets sent to port 6001 will be echoed backnr");
}err_t recv_callback(void *arg, struct tcp_pcb *tpcb,struct pbuf *p, err_t err)
{/* do not read the packet if we are not in ESTABLISHED state */if (!p) {tcp_close(tpcb);tcp_recv(tpcb, NULL);return ERR_OK;}/* indicate that the packet has been received */tcp_recved(tpcb, p->len);/* echo back the payload *//* in this case, we assume that the payload is < TCP_SND_BUF */if (tcp_sndbuf(tpcb) > p->len) {err = tcp_write(tpcb, p->payload, p->len, 1);} elsexil_printf("no space in tcp_sndbufnr");/* free the received pbuf */pbuf_free(p);return ERR_OK;
}/** TCP sent callback, try to send more data */
static err_t tcp_client_sent(void *arg, struct tcp_pcb *tpcb, u16_t len)
{xil_printf("we have sent the package rn");usleep(100);return transfer_data();
// return ERR_OK;
}
err_t accept_callback(void *arg, struct tcp_pcb *newpcb, err_t err)
{static int connection = 1;/* set the receive callback for this connection */tcp_recv(newpcb, recv_callback);/* just use an integer number indicating the connection id as thecallback argument */tcp_arg(newpcb, (void*)(UINTPTR)connection);/* increment for subsequent accepted connections */connection++;//将新这个接收的这个accept 赋值给全局变量,以便我们进行其他的处理,例如主动发送数据connected_pcb = newpcb;//禁用nagle 算法tcp_nagle_disable(connected_pcb);// zhiweitcp_client_connected=1;tcp_arg(connected_pcb, NULL);tcp_sent(connected_pcb, tcp_client_sent);tcp_err(connected_pcb, tcp_client_err);transfer_data();return ERR_OK;
}int start_application()
{struct tcp_pcb *pcb;err_t err;unsigned port = 5011;/* create new TCP PCB structure */pcb = tcp_new();if (!pcb) {xil_printf("Error creating PCB. Out of Memorynr");return -1;}/* bind to specified @port */err = tcp_bind(pcb, IP_ADDR_ANY, port);if (err != ERR_OK) {xil_printf("Unable to bind to port %d: err = %dnr", port, err);return -2;}/* we do not need any arguments to callback functions */tcp_arg(pcb, NULL);/* listen for connections */pcb = tcp_listen(pcb);if (!pcb) {xil_printf("Out of memory while tcp_listennr");return -3;}/* specify callback to use for incoming connections */tcp_accept(pcb, accept_callback);xil_printf("TCP echo server started @ port %dnr", port);return 0;
}
main.c 文件修改后的内容:
/******************************************************************************
*
* Copyright (C) 2009 - 2014 Xilinx, Inc. All rights reserved.
*
* Permission is hereby granted, free of charge, to any person obtaining a copy
* of this software and associated documentation files (the "Software"), to deal
* in the Software without restriction, including without limitation the rights
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
* copies of the Software, and to permit persons to whom the Software is
* furnished to do so, subject to the following conditions:
*
* The above copyright notice and this permission notice shall be included in
* all copies or substantial portions of the Software.
*
* Use of the Software is limited solely to applications:
* (a) running on a Xilinx device, or
* (b) that interact with a Xilinx device through a bus or interconnect.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
* XILINX BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF
* OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
* SOFTWARE.
*
* Except as contained in this notice, the name of the Xilinx shall not be used
* in advertising or otherwise to promote the sale, use or other dealings in
* this Software without prior written authorization from Xilinx.
*
******************************************************************************/#include <stdio.h>#include "xparameters.h"#include "netif/xadapter.h"#include "platform.h"
#include "platform_config.h"
#if defined (__arm__) || defined(__aarch64__)
#include "xil_printf.h"
#endif
#include "sleep.h"#include "lwip/tcp.h"
#include "xil_cache.h"#if LWIP_DHCP==1
#include "lwip/dhcp.h"
#endif/* defined by each RAW mode application */
void print_app_header();
int start_application();
err_t transfer_data();
void tcp_fasttmr(void);
void tcp_slowtmr(void);/* missing declaration in lwIP */
void lwip_init();#if LWIP_DHCP==1
extern volatile int dhcp_timoutcntr;
err_t dhcp_start(struct netif *netif);
#endifextern volatile int TcpFastTmrFlag;
extern volatile int TcpSlowTmrFlag;
extern volatile unsigned tcp_client_connected;
static struct netif server_netif;
struct netif *echo_netif;void
print_ip(char *msg, struct ip_addr *ip)
{print(msg);xil_printf("%d.%d.%d.%dnr", ip4_addr1(ip), ip4_addr2(ip), ip4_addr3(ip), ip4_addr4(ip));
}void
print_ip_settings(struct ip_addr *ip, struct ip_addr *mask, struct ip_addr *gw)
{print_ip("Board IP: ", ip);print_ip("Netmask : ", mask);print_ip("Gateway : ", gw);
}#if defined (__arm__) && !defined (ARMR5)
#if XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 || XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1
int ProgramSi5324(void);
int ProgramSfpPhy(void);
#endif
#endif#ifdef XPS_BOARD_ZCU102
#ifdef XPAR_XIICPS_0_DEVICE_ID
int IicPhyReset(void);
#endif
#endifint main()
{struct ip_addr ipaddr, netmask, gw;err_t tmperr;/* the mac address of the board. this should be unique per board */unsigned char mac_ethernet_address[] ={ 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };echo_netif = &server_netif;
#if defined (__arm__) && !defined (ARMR5)
#if XPAR_GIGE_PCS_PMA_SGMII_CORE_PRESENT == 1 || XPAR_GIGE_PCS_PMA_1000BASEX_CORE_PRESENT == 1ProgramSi5324();ProgramSfpPhy();
#endif
#endif/* Define this board specific macro in order perform PHY reset on ZCU102 */
#ifdef XPS_BOARD_ZCU102IicPhyReset();
#endif//TO enable platform interuptinit_platform();/* initliaze IP addresses to be used */IP4_ADDR(&ipaddr, 192, 168, 127, 202);IP4_ADDR(&netmask, 255, 255, 255, 0);IP4_ADDR(&gw, 192, 168, 127, 254);print_app_header();lwip_init();/* Add network interface to the netif_list, and set it as default */if (!xemac_add(echo_netif, &ipaddr, &netmask,&gw, mac_ethernet_address,PLATFORM_EMAC_BASEADDR)) {xil_printf("Error adding N/W interfacenr");return -1;}netif_set_default(echo_netif);/* now enable interrupts */platform_enable_interrupts();/* specify that the network if is up */netif_set_up(echo_netif);print_ip_settings(&ipaddr, &netmask, &gw);/* start the application (web server, rxtest, txtest, etc..) */start_application();/* receive and process packets */while (1) {if (TcpFastTmrFlag) {tcp_fasttmr();TcpFastTmrFlag = 0;}if (TcpSlowTmrFlag) {tcp_slowtmr();TcpSlowTmrFlag = 0;}//xil_printf("we are sending in while looprn");xemacif_input(echo_netif);
// xemacif_input(echo_netif);
// if (tcp_client_connected) { //连接成功则发送数据
// xil_printf("we are sending in connectrn");// transfer_data();// }}/* never reached */cleanup_platform();return 0;
}
上述的代码:
采用这种类似回调函数的形式,能够正常的工作,但是实际看起zynq的发送的速度很慢。如下是arm平台没有涉恶顶延时的情况得到的结果。
本文发布于:2024-02-02 14:24:07,感谢您对本站的认可!
本文链接:https://www.4u4v.net/it/170685504444393.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
留言与评论(共有 0 条评论) |