本文在PS的Standalone程序中使用lwip库通过UDP协议实现网络数据传输。
包含UDP Server和UDP Client两种形式
本文主要参考lwip的SDK内部说明和工程模板,xapp1026, xapp1306, SDK以及两篇博客:
https://www.cnblogs.com/54zorb/p/9609021.html
https://www.cnblogs.com/54zorb/p/9609111.html
本文配套源码已上传至
https://download.csdn.net/download/botao_li/10997950
Block Design
建立zcu102的Vivado工程,新建Block Design,并且添加zynq模块
运行Run Block Automation,双击打开zynq模块配置查看GEM接口配置
GEM3的配置与ug1182一致
保留UART和GEM3,关闭其它外设接口以及PS-PL接口
确保TTC 0已使能
保存后依次运行Generate Output Products和Create HDL Wrapper
在Flow Navigator中选择Generate Bitstream,完成后先Export Hardware,再Launch SDK
PS程序
在SDK中可以使用lwip模板新建包含lwip库示例代码的模板工程
注意zuc102开发板生成的模板工程会在IicPhyReset()函数编译出错,将此函数注释掉,用开发板上下电代替复位(试验中发现即使不上下电能正常工作)
建完首个工程后,其它工程建立时可以选择使用已有BSP工程
本文新建空工程用于试验
建立工程后SDK进行自动编译,完成之后在BSP工程配置lwip库(否则可能出现不可理解的异常错误)
在BSP工程上,右键菜单选择Board Support Package Settings
进入Settings窗口,在Overview界面选中lwip库(如果建立的是lwip模板工程,则BSP工程已自动添加lwip库)
配置完成后点击OK
打开BSP工程中的system.mss文件,可以在最下方发现lwip库,选择Documentation可以打开说明文档
在工作工程的src文件夹上右键菜单新建C Source File
进入文件main.c,双击打开main.c文件,写入以下代码
#include <stdio.h>
#include "xparameters.h"
#include "netif/xadapter.h"
#include "lwipopts.h"
#include "xil_printf.h"
#include "sleep.h"
#include "lwip/priv/tcp_priv.h"
#include "lwip/init.h"
#include "lwip/inet.h"
#include "lwip/ip_addr.h"
#include "lwip/udp.h"
#include "xil_cache.h"
#include "xscugic.h"
#include "xttcps.h"
//定时器相关定义***************************************************
static XTtcPs TimerInstance;
static u16 Interval;
static u8 Prescaler;
#define INTC_DEVICE_ID XPAR_SCUGIC_SINGLE_DEVICE_ID
#define TIMER_DEVICE_ID XPAR_XTTCPS_0_DEVICE_ID
#define TIMER_IRPT_INTR XPAR_XTTCPS_0_INTR
#define INTC_BASE_ADDR XPAR_SCUGIC_0_CPU_BASEADDR
#define INTC_DIST_BASE_ADDR XPAR_SCUGIC_0_DIST_BASEADDR
#define PLATFORM_TIMER_INTR_RATE_HZ (4)
//中断响应函数与main函数都访问的变量,加volatile前缀,不进入cache
volatile int TcpFastTmrFlag = 0;
volatile int TcpSlowTmrFlag = 0;
void platform_clear_interrupt( XTtcPs * TimerInstance )
{
u32 StatusEvent;
StatusEvent = XTtcPs_GetInterruptStatus(TimerInstance);
XTtcPs_ClearInterruptStatus(TimerInstance, StatusEvent);
}
void timer_callback(XTtcPs * TimerInstance)
{
/* we need to call tcp_fasttmr & tcp_slowtmr at intervals specified
* by lwIP. It is not important that the timing is absoluetly accurate.
*/
static int odd = 1;
TcpFastTmrFlag = 1;
odd = !odd;
if (odd)
{
TcpSlowTmrFlag