PS端开发UDP通信,完成网口助手收发一致


前言

最近在做PS与PL的数据交互传输,目前先调通PS端以太网UDP传输,在此记录并备份
暂存,等这部分做完写一个汇总正式文件

PS端以太网,网上没有UDP的开发发送接收,vitis进去大多数都是TCP的,我需要用的是UDP,自定义加上用户端IP地址和端口,故作次修改,已实现UDP收发一致以供大家学习参考。

一、原程序

#include <stdio.h>
#include "xscugic.h"
#include "xparameters.h"
#include "sleep.h"
#include "xscutimer.h"
#include "lwip/err.h"
#include "lwip/udp.h"
#include "lwip/init.h"
#include "lwipopts.h"
#include "netif/xadapter.h"
#include "lwipopts.h"
#include "lwip/priv/tcp_priv.h"


#define GIC_ID 						XPAR_PS7_SCUGIC_0_DEVICE_ID

#define TCP_RXBUFFER_BASE_ADDR  	0x10000000


int initSwIntr();
int initudp(struct netif *netif);
int udp_recv_init();
void udp_recv_callback(void *arg, struct udp_pcb *tpcb,struct pbuf *p, struct ip4_addr *addr, u16_t port);
void send_received_data();

static XScuGic ScuGic;

static XScuGic_Config * ScuGicCfgPtr;

XScuTimer Timer;
XScuTimer_Config  *Config;

volatile int TcpTmrFlag;
int flag;
int rec_cnt;

static unsigned local_port = 5010;
static unsigned remote_port = 32770;
struct udp_pcb *connected_pcb;
u8 *udp_rx_buffer;
static struct pbuf *pbuf_to_be_sent = NULL;
struct ip4_addr ipaddress;
volatile u32 file_length;


int main()
{
	int status;
	struct netif *netif, server_netif;
	netif = &server_netif;
	status = initSwIntr();
	status = initudp(netif);
	if(status != XST_SUCCESS){
		return status;
	}
	udp_recv_init();
	while(1){

		xemacif_input(netif);//将MAC队列里的packets传输到你的LwIP/IP stack里

		/* if connected to the server and received start command,
		 * start receiving data from PL through AXI DMA,
		 * then transmit the data to the PC using TCP
		 * */
		if(flag == 1)
			send_received_data();
	}
	return 0;
}


/*因为用到了UDP接收中断,所以需要初始化GUI中断控制器*/
int initSwIntr(){
	int status;
	Xil_ExceptionInit();
	ScuGicCfgPtr = XScuGic_LookupConfig(GIC_ID);
	status = XScuGic_CfgInitialize(&ScuGic,ScuGicCfgPtr,ScuGicCfgPtr->CpuBaseAddress);
	if(status != XST_SUCCESS){
		return status;
	}
	Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,(Xil_ExceptionHandler)XScuGic_InterruptHandler,&ScuGic);
	Xil_ExceptionEnable();

	return XST_SUCCESS;
}

/*UDP协议的初始化*/
int initudp(struct netif *netif){
	struct ip4_addr ipaddr, netmask, gw;
	/* the mac address of the board. this should be unique per board */
	unsigned char mac_ethernet_address[] = { 0x00, 0x0a, 0x35, 0x00, 0x01, 0x02 };
	/*local ip address*/
	IP4_ADDR(&ipaddr,  192, 168,   1,  10);
	IP4_ADDR(&netmask, 255, 255, 255,  0);
	IP4_ADDR(&gw,      192, 168,   2,  1);
	/*lwip library init*/
	lwip_init();
	/* Add network interface to the netif_list, and set it as default */
	if (!xemac_add(netif, &ipaddr, &netmask, &gw, mac_ethernet_address, XPAR_XEMACPS_0_BASEADDR)) {
		xil_printf("Error adding N/W interface\r\n");
		return -1;
	}
	netif_set_default(netif);
	/* specify that the network if is up */
	netif_set_up(netif);
	return XST_SUCCESS;
}


int udp_recv_init(){
	err_t err;

	udp_rx_buffer = (u8 *)TCP_RXBUFFER_BASE_ADDR;
	connected_pcb = udp_new();
	if (!connected_pcb) {
		xil_printf("txperf: Error creating PCB. Out of Memory\r\n");
		return -1;
	}
	err = udp_bind(connected_pcb, IP_ADDR_ANY, local_port);
	/* connect to tcp server */
	IP4_ADDR(&ipaddress,  192, 168,   1, 103);		/* tcp server address */
	err = udp_connect(connected_pcb, &ipaddress, remote_port);
	if (err != ERR_OK) {
		xil_printf("txperf: tcp_connect returned error: %d\r\n", err);
		return err;
	}

	udp_recv(connected_pcb, (udp_recv_fn)udp_recv_callback, NULL);
	return XST_SUCCESS;
}

/*UDP协议的接收中断服务函数*/
void udp_recv_callback(void *arg, struct udp_pcb *tpcb,struct pbuf *p, struct ip4_addr *addr, u16_t port)
{

	struct pbuf *q;
	u32 remain_length;
	flag = 1;
	q = p;
	rec_cnt = q->tot_len;
	/*if received ip fragment packets*/
    if(q->tot_len > q->len){
    	remain_length = q->tot_len;
    	file_length = 0;
    	while(remain_length > 0){
			memcpy(udp_rx_buffer + file_length, q->payload, q->len);
			file_length += q->len;
			remain_length -= q->len;
			/*go to next pbuf pointer*/
			q = q->next;
    	}
	}
    	/*if received no ip fragment packets*/
    else{
    	memcpy(udp_rx_buffer, q->payload, q->len);
    }
    //xil_printf("udp data come in!%d, %d\r\n", p->tot_len, p->len);

	pbuf_free(p);
}

/*UDP协议发送数据函数*/
void send_received_data(){
	err_t err;
	flag = 0;
	struct udp_pcb *tpcb = connected_pcb;
	if(rec_cnt < 18){
		pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, 18, PBUF_POOL);
		memset(pbuf_to_be_sent->payload, 0, 18);
	}
	else{
		pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, rec_cnt, PBUF_POOL);
	}
	memcpy(pbuf_to_be_sent->payload, (u8 *)udp_rx_buffer, rec_cnt);
	err = udp_send(tpcb, pbuf_to_be_sent);
	if (err != ERR_OK){
		xil_printf("Error on udp_send: %d\r\n", err);
		pbuf_free(pbuf_to_be_sent);
		return;
	}
	pbuf_free(pbuf_to_be_sent);

}



但是会出现网口助手发送数据与接收数据“位”没对齐,研究一下代码,展出问题设置部分进行修改

2.适当修改

	pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, rec_cnt, PBUF_POOL);
	/*
	if(rec_cnt < 18){
		pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, 18, PBUF_POOL);
		memset(pbuf_to_be_sent->payload, 0, 18);
	}
	else{
		pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, rec_cnt, PBUF_POOL);
	}
	*/

现在网口助手是收发一致了


总结

PS端以太网,网上没有UDP的开发发送接收,vitis进去大多数都是TCP的,我需要用的是UDP,自定义加上用户端IP地址和端口,故作次修改,以供参考。

  • 15
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
Zynq是一种基于Xilinx的可编程逻辑器件(FPGA)和ARM处理器(Cortex-A9)集成在一起的芯片。它提供了一种灵活且高性能的解决方案,可用于嵌入式系统的设计和开发。 在Zynq芯片中,UDP协议是一种基于IP协议的传输层协议,用于在网络中进行无连接的数据传输。UDP协议通过UDP套接字实现数据的收发。 要在Zynq上实现UDP网口收发,首先需要配置FPGA的硬件设计。可以使用Xilinx提供的Vivado开发环境进行设计,选择合适的IP核来实现UDP收发功能。然后,将设计完成的BIT文件加载到Zynq芯片上。 之后,通过在ARM处理器上运行的操作系统(比如Linux)中的网络配置,将网口与指定的IP地址和口进行绑定。可以使用Linux提供的命令行工具(如ifconfig和route)进行网络配置。 在应用程序中,可以使用任何支持UDP协议的编程语言来进行UDP数据的收发操作。例如,在C语言中,可以使用socket函数库来创建UDP套接字,并使用sendto和recvfrom函数来发送和接收UDP数据包。 需要注意的是,使用UDP进行数据传输时,由于UDP是无连接的,因此没有对数据的完整性和可靠性进行验证。这意味着在收发数据时,需要特别注意丢包和数据错误的情况。 总之,通过配置FPGA的硬件设计,配置网络参数,并在应用程序中使用适当的函数库,我们可以在Zynq芯片上实现UDP网口收发功能。这样,我们可以在网络中快速传输数据,并实现实时应用程序的通信和控制。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值