文章目录
前言
最近在做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地址和端口,故作次修改,以供参考。