1 引言
有了上一讲的基础知识后,本篇进行基于SoC的PL与PS侧协同完成通过网口SGMII的udp传输,本教程为全网第一篇关于ZCU106开发板的教程,先上视频看效果。
ZCU106与PC的UDP通讯
2 实验内容
1、实验任务:通过ZCU106的SGMII网口与PC机完成基于UDP协议的数据传输
2、实验软件:Vivado 2019.1、Vivado SDK 2019.1、网络调试助手(自行下载)、友善串口调试助手
实验硬件:ZCU106、网线1一条
3、实验过程:
step1:建立项目工程:udp_test_ps
step2:建立PS侧设计,就和simulink一样搭建模块
step3:添加ZYNQ+支持
直接双击,界面就出现了芯片,然后点击下图的自动运行模块
然后变成了这样
我们双击后在左侧的PS-PL configuration的search搜索hpm,ba AXI HPM1 FPD的钩子去掉。
再次使用search搜索irq(中断信号),把IRQ0[0-7]改成0,然后直接点击OK
step4:修改ddr属性,这个可能每个开发板不一样。我的开发板必须设置成这个样子才能运行。
然后点击校验按钮,没问题后变成了这样:
step5:输出产品,创建HDL WARRP
step6:生存bit文件,并将bit文件输出到sdk中,然后直接店家Launch SDK按钮。
step7:建立app_cpu0程序并设置为server服务。
step8:删除下面红框两个文件,并修改main.c文件,并添加sys_intr.c、sys_intr.h、user_udp.c、user_udp.h这4个文件。
1、main.c
//--------------------------------------------------
// Company: 东北电力大学
// Engineer: Yang Zheng
//--------------------------------------------------
#include "sleep.h"
#include "user_udp.h"
#include "sys_intr.h"
#include "lwip/ip.h"
extern unsigned udp_connected_flag;
static XScuGic Intc; //GIC
static struct netif server_netif;
struct netif *netif;
int main(void)
{
ip_addr_t ipaddr, netmask, gw;
/* 开发板MAC地址 */
unsigned char mac_ethernet_address [] =
{0x00, 0x0a, 0x35, 0x00, 0x01, 0x02};
/* 开启中断系统 */
Init_Intr_System(&Intc);
Setup_Intr_Exception(&Intc);
netif = &server_netif;
xil_printf("Configuring default IP of 172.168.1.10\r\n");
IP4_ADDR(&(netif->ip_addr), 172, 168, 1, 10);
IP4_ADDR(&(netif->netmask), 255, 255, 255, 0);
IP4_ADDR(&(netif->gw), 172, 168, 1, 1);
ipaddr.addr = netif->ip_addr.addr;
gw.addr = netif->gw.addr;
netmask.addr = netif->netmask.addr;
lwip_init(); //初始化lwIP库
/* 添加网络接口并将其设置为默认接口 */
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);
netif_set_up(netif); //启动网络
user_udp_init(); //初始化UDP
while(1)
{
/* 将MAC队列中的包传输的LwIP/IP栈中 */
xemacif_input(netif);
if (udp_connected_flag) { //发送
xil_printf("udp con is successed\r\n");
sleep(10);
udp_printf();
}
}
return 0;
}
2、 sys_intr.c
//--------------------------------------------------
// Company: 东北电力大学
// Engineer: Yang Zheng
//--------------------------------------------------
#include "sys_intr.h"
//---------------------------------------------------------
// 设置中断异常
//---------------------------------------------------------
void Setup_Intr_Exception(XScuGic * IntcInstancePtr)
{
Xil_ExceptionInit();
Xil_ExceptionRegisterHandler(XIL_EXCEPTION_ID_INT,
(Xil_ExceptionHandler)XScuGic_InterruptHandler,
(void *)IntcInstancePtr);
Xil_ExceptionEnable();
}
//---------------------------------------------------------
// 初始化中断系统
//---------------------------------------------------------
int Init_Intr_System(XScuGic * IntcInstancePtr)
{
int Status;
XScuGic_Config *IntcConfig;
IntcConfig = XScuGic_LookupConfig(INTC_DEVICE_ID);
if (NULL == IntcConfig) {
return XST_FAILURE;
}
Status = XScuGic_CfgInitialize(IntcInstancePtr, IntcConfig,
IntcConfig->CpuBaseAddress);
if (Status != XST_SUCCESS) {
return XST_FAILURE;
}
return XST_SUCCESS;
}
3、sys_intr.h
//--------------------------------------------------
// Company: 东北电力大学
// Engineer: Yang Zheng
//--------------------------------------------------
#ifndef SYS_INTR_H_
#define SYS_INTR_H_
#include "xparameters.h"
#include "xil_exception.h"
#include "xdebug.h"
#include "xscugic.h"
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
int Init_Intr_System(XScuGic * IntcInstancePtr);
void Setup_Intr_Exception(XScuGic * IntcInstancePtr);
#endif /* SYS_INTR_H_ */
4、user_udp.c
//--------------------------------------------------
// Company: 东北电力大学
// Engineer: Yang Zheng
//--------------------------------------------------
#include "user_udp.h"
#include "lwip/ip.h"
//---------------------------------------------------------
// 变量定义
//---------------------------------------------------------
struct udp_pcb *connected_pcb = NULL;
static struct pbuf *pbuf_to_be_sent = NULL;
static unsigned local_port = 7; //本地端口
static unsigned remote_port = 8080; //远程端口
volatile unsigned udp_connected_flag = 0; //连接标志
//---------------------------------------------------------
// UDP连接初始化函数
//---------------------------------------------------------
int user_udp_init(void)
{
struct udp_pcb *pcb;
ip_addr_t ipaddr;
err_t err;
udp_connected_flag = 0;
/* 创建UDP控制块 */
pcb = udp_new();
if (!pcb) {
xil_printf("Error Creating PCB.\r\n");
return -1;
}
/* 绑定本地端口 */
err = udp_bind(pcb, IP_ADDR_ANY, local_port);
if (err != ERR_OK) {
xil_printf("Unable to bind to port %d\r\n", local_port);
return -2;
}
/* 连接远程地址 */
IP4_ADDR(&ipaddr, 172, 168, 1, 100);
err = udp_connect(pcb, &ipaddr, remote_port);
if (err != ERR_OK) {
xil_printf("Unable to connect remote port.\r\n");
return -3;
}
else {
xil_printf("Connected Success.\r\n");
connected_pcb = pcb;
udp_connected_flag = 1;
}
return 0;
}
//---------------------------------------------------------
// UDP发送数据函数
//---------------------------------------------------------
void udp_printf(void)
{
err_t err;
char send_buff[512] = "hello world! author: Yang Zheng\r\n"; //待发送字符
struct udp_pcb *tpcb = connected_pcb;
if (!tpcb) {
xil_printf("error connect.\r\n");
}
/* 申请pbuf资源 */
pbuf_to_be_sent = pbuf_alloc(PBUF_TRANSPORT, 512, PBUF_POOL);
memset(pbuf_to_be_sent->payload, 0, 512);
memcpy(pbuf_to_be_sent->payload, (u8 *)send_buff, 512);
/* 发送字符串 */
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); //释放pbuf
}
5、user_udp.h
//--------------------------------------------------
// Company: 东北电力大学
// Engineer: Yang Zheng
//--------------------------------------------------
#ifndef SRC_USER_UDP_H_
#define SRC_USER_UDP_H_
#include "lwip/err.h"
#include "lwip/udp.h"
#include "lwip/init.h"
#include "lwipopts.h"
#include "lwip/err.h"
#include "lwipopts.h"
#include "netif/xadapter.h"
#include "xil_printf.h"
int user_udp_init(void);
void udp_printf(void);
#endif /* SRC_USER_UDP_H_ */
step9:由步骤8可知,PC的ip地址为172.168.1.100,端口为8080;FPGA的ip地址为172.168.1.10,端口为7。