Zynq-LWIP上行传输大批量数据方法说明

2023-11-10

        此篇是我在学习中做的归纳与总结,其中如果存在版权或知识错误或问题请直接联系我,欢迎留言。
PS:本着知识共享的原则,此篇博客可以转载,但请标明出处!

目录

1.项目简介:

1.1 完成功能:

1.1 使用工具:

2. LWIP141+DMA上行传输数据

2.1 LWIP141

2.2 PS端代码开发

2.3 PC端网络配置

3. 高速数字系统时钟设计-AD9516

4. 高速ADC--ADS62P49

5. 测试

MATLAB读取TXT数据文件的频谱分析--FFT:


1.项目简介:

1.1 完成功能:

  Zynq控制高速高精度ADC(ADS62P49)完成250MSPS采样率模数转换功能,并将采集的大批量数据(100000x14x2bit)通过DMA传输至DDR3,而后经过网口传输至PC机做后续处理。

1.1 使用工具:

Vivado2017.4;

北京太速科技ZYNQ板卡:(XC7Z100)核心处理器及外设通用板卡;

双通道高速高精密ADDA子卡(ADS62P49、AD9122)

2. LWIP141+DMA上行传输数据

上行传输整体实现框图:

与DMA-FIFO对接需要使用AXI接口形式将数据传输至FIFO中,因此掌握AXI-FIFO的数据流传输机制是非常关键的,在此针对AXI接口传输具体实现细节不做描述,具体实现代码如下:

module data(
    output  [31:0]      S_AXIS_tdata ,
    output  [3:0]       S_AXIS_tkeep,
    output              S_AXIS_tlast,
    input               S_AXIS_tready,
    output              S_AXIS_tvalid,
    input               gpio_rtl_tri_o,
    input               peripheral_aresetn,
    input               FCLK_CLK0_0 ,
    output              s_axis_aclk,
    output              s_axis_aresetn
    );
    
 reg [31:0]S_AXIS_tdata;
 reg  S_AXIS_tlast;
 reg S_AXIS_tvalid; 
 wire FCLK_CLK0_0;
 wire s_axis_aclk;
 wire s_axis_aresetn;
 wire [3:0]S_AXIS_tkeep;
 wire S_AXIS_tready;
 wire [0:0]gpio_rtl_tri_o;
 wire [0:0]peripheral_aresetn;
reg [1:0] state;
 
assign S_AXIS_tkeep = 4'b1111;  
assign s_axis_aclk =  FCLK_CLK0_0;
assign s_axis_aresetn = peripheral_aresetn;
  
always@(posedge FCLK_CLK0_0) begin
       if(!peripheral_aresetn) begin
           S_AXIS_tvalid <= 1'b0;
           S_AXIS_tdata <= 32'd0;
           S_AXIS_tlast <= 1'b0;
           state <=0;
       end else begin
          case(state)
            0: begin
                if(gpio_rtl_tri_o&& S_AXIS_tready) begin
                   S_AXIS_tvalid <= 1'b1;
                   state <= 1;
                end else begin
                   S_AXIS_tvalid <= 1'b0;
                   state <= 0;
                end
              end
            1:begin
                 if(S_AXIS_tready) begin
                     S_AXIS_tdata <= S_AXIS_tdata + 1'b1;
                     if(S_AXIS_tdata == 32'd100000) begin
                        S_AXIS_tlast <= 1'b1;
                        state <= 2;
                     end else begin
                        S_AXIS_tlast <= 1'b0;
                        state <= 1;
                     end
                 end
                 else begin
                    S_AXIS_tdata <= S_AXIS_tdata;                   
                    state <= 1;
                 end
              end       
            2:begin
                 if(!S_AXIS_tready) begin
                    S_AXIS_tvalid <= 1'b1;
                    S_AXIS_tlast <= 1'b1;
                    S_AXIS_tdata <= S_AXIS_tdata;
                    state <= 2;
                 end else begin
                    S_AXIS_tvalid <= 1'b0;
                    S_AXIS_tlast <= 1'b0;
                    S_AXIS_tdata <= 32'd0;
                    state <= 0;
                 end
              end
           default: state <=0;
           endcase
       end              
   end  

endmodule

DMA数据流传输部分仿真数据图:

2.1 LWIP141

LWIP配置

phy_link_speed中不建议使用Autodetect模式,容易出现问题!建议根据自身的Zynq网口、网线、PC网口速率配置,本项目选择使用100M速率网络通信。

2.2 PS端代码开发

PS端上行传输代码功能:        1、完成所需设备初始化;

                                                 2、将PS端DDR3中数据上传至PC机

PS端程序开发同时也适用于Zynq-7010、Zynq-7020等。

工程目录表如下所示:

每次启动函数:XAxiDma_SimpleTransfer()时,传输10000组ADC采集数据,分十次发送。

tcp_transmission.c


#include <stdio.h>
#include <string.h>

#include "lwip/err.h"
#include "lwip/tcp.h"
#include "lwipopts.h"
#include "xaxidma.h"
#include "xil_cache.h"
#include "xil_printf.h"
#include "sleep.h"


#define SEND_SIZE (40000)
#define PAKET_LENGTH (40048)

static struct tcp_pcb *connected_pcb = NULL;

volatile unsigned tcp_client_connected = 0;
static int tcp_trans_done = 0;
static unsigned first_trans_start = 0;

static u32_t packet_index = 0;

extern XAxiDma AxiDma;
extern u16 *RxBufferPtr[4];
extern u8_t packet_trans_done;

void send_received_data()
{
#if __arm__
	int copy = 1;
#else
	int copy = 0;
#endif
	err_t err;
	int Status;
	struct tcp_pcb *tpcb = connected_pcb;

	/*initial the first axdma transmission, only excuse once*/
	if(!first_trans_start)
	{
		Status = XAxiDma_SimpleTransfer(&AxiDma, (u32)RxBufferPtr[packet_index],
				(u32)(PAKET_LENGTH), XAXIDMA_DEVICE_TO_DMA);
		if (Status != XST_SUCCESS)
		{
			xil_printf("axi dma failed! 0 %d\r\n", Status);
			return;
		}
		/*set the flag, so this part of code will not excuse again*/
		first_trans_start = 1;
	}

	/*if the last axidma transmission is done, the interrupt triggered, then start TCP transmission*/
	if(packet_trans_done)
	{
		if (!connected_pcb)
			return;

		/* if tcp send buffer has enough space to hold the data we want to transmit from PL, then start tcp transmission*/
		if (tcp_sndbuf(tpcb) > SEND_SIZE)
		{
			/*transmit received data through TCP*/
			err = tcp_write(tpcb, RxBufferPtr[packet_index], SEND_SIZE, copy);
			if (err != ERR_OK) {
				xil_printf("txperf: Error on tcp_write: %d\r\n", err);
				connected_pcb = NULL;
				return;
			}
			err = tcp_output(tpcb);
			if (err != ERR_OK) {
				xil_printf("txperf: Error on tcp_output: %d\r\n",err);
				return;
			}

			packet_index++ ;

//			/*clear the axidma done flag*/
			packet_trans_done = 0;
			first_trans_start = 0;

			/*initial the other axidma transmission when the current transmission is done*/
//			Status = XAxiDma_SimpleTransfer(&AxiDma, (u32)RxBufferPtr[(packet_index + 1)&1],
//						(u32)(PAKET_LENGTH), XAXIDMA_DEVICE_TO_DMA);
//			if (Status != XST_SUCCESS)
//			{
//				xil_printf("axi dma %d failed! %d \r\n", (packet_index + 1), Status);
//				return;
//			}

		}
	}
}


/*this fuction just used to count the tcp transmission times*/
static err_t
tcp_sent_callback(void *arg, struct tcp_pcb *tpcb, u16_t len)
{
	err_t err;
	tcp_trans_done = 1;
	err = tcp_output(tpcb);
	if (err != ERR_OK)
        {
		xil_printf("txperf: Error on tcp_output: %d\r\n",err);
		return -1;
	}
	return ERR_OK;
}


static err_t
tcp_connected_callback(void *arg, struct tcp_pcb *tpcb, err_t err)
{
	xil_printf("txperf: Connected to iperf server\r\n");

	/* store state */
	connected_pcb = tpcb;

	/* set callback values & functions */
	tcp_arg(tpcb, NULL);
	tcp_sent(tpcb, tcp_sent_callback);
	//tcp_recv(tpcb, tcp_recv_callback);
	tcp_nagle_disable(tpcb);

	if(!tcp_nagle_disabled(tpcb))
        {
		xil_printf("tcp nagle disable failed!\r\n");
        }
	tcp_client_connected = 1;

	/* initiate data transfer */
	return ERR_OK;
}


int tcp_send_init()
{
	struct tcp_pcb *pcb;
	struct ip_addr ipaddr;
	err_t err;
	u16_t port;
	port = 7;					/* iperf default port */

	/* create new TCP PCB structure */
	pcb = tcp_new();
	if (!pcb) {
		xil_printf("txperf: Error creating PCB. Out of Memory\r\n");
		return -1;
	}

	/* connect to iperf tcp server */
	IP4_ADDR(&ipaddr,  192, 168,   1, 209);		/* iperf server address */

    tcp_client_connected = 0;
    first_trans_start = 0;
    packet_trans_done = 0;
    packet_index = 0;

	err = tcp_connect(pcb, &ipaddr, port, tcp_connected_callback);
	if (err != ERR_OK) {
		xil_printf("txperf: tcp_connect returned error: %d\r\n", err);
		return err;
	}


	return 0;
}



main函数:


#include "dma_intr.h"
#include "timer_intr.h"
#include "sys_intr.h"
#include "xgpio.h"

#include "lwip/err.h"
#include "lwip/tcp.h"
#include "lwipopts.h"
#include "netif/xadapter.h"
#include "lwipopts.h"


static  XScuGic Intc; //GIC
static  XScuTimer Timer;//timer
XAxiDma AxiDma;
u16 *RxBufferPtr[10];  /* ping pong buffers*/

volatile u32 RX_success;
volatile u32 TX_success;

volatile u32 RX_ready=1;
volatile u32 TX_ready=1;

#define TIMER_LOAD_VALUE    XPAR_CPU_CORTEXA9_0_CPU_CLK_FREQ_HZ / 8 //0.5S
#define AXIDMA_DEV_ID		XPAR_AXIDMA_0_DEVICE_ID

extern void send_received_data(void);
extern unsigned tcp_client_connected;


static XGpio Gpio;

#define AXI_GPIO_DEV_ID	        XPAR_AXI_GPIO_0_DEVICE_ID

int init_intr_sys(void)
{
	DMA_Intr_Init(&AxiDma,AXIDMA_DEV_ID);//initial interrupt system
	Timer_init(&Timer,TIMER_LOAD_VALUE,TIMER_DEVICE_ID);
	Init_Intr_System(&Intc); // initial DMA interrupt system
	Setup_Intr_Exception(&Intc);
	DMA_Setup_Intr_System(&Intc,&AxiDma,0,RX_INTR_ID);//setup dma interrpt system
	Timer_Setup_Intr_System(&Intc,&Timer,TIMER_IRPT_INTR);
	DMA_Intr_Enable(&Intc,&AxiDma);
}

int main(void)
{
	int Status;
	struct netif *netif, server_netif;
	struct ip_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 };

	/* Initialize the ping pong buffers for the data received from axidma */
	RxBufferPtr[0] = (u16 *)RX_BUFFER0_BASE;
	RxBufferPtr[1] = (u16 *)RX_BUFFER1_BASE;
	RxBufferPtr[2] = (u16 *)RX_BUFFER2_BASE;
	RxBufferPtr[3] = (u16 *)RX_BUFFER3_BASE;
	RxBufferPtr[4] = (u16 *)RX_BUFFER4_BASE;
	RxBufferPtr[5] = (u16 *)RX_BUFFER5_BASE;
	RxBufferPtr[6] = (u16 *)RX_BUFFER6_BASE;
	RxBufferPtr[7] = (u16 *)RX_BUFFER7_BASE;
	RxBufferPtr[8] = (u16 *)RX_BUFFER8_BASE;
	RxBufferPtr[9] = (u16 *)RX_BUFFER9_BASE;

	XGpio_Initialize(&Gpio, AXI_GPIO_DEV_ID);
	XGpio_SetDataDirection(&Gpio, 1, 0);
	init_intr_sys();
	TcpTmrFlag = 0;

	netif = &server_netif;

	IP4_ADDR(&ipaddr,  192, 168,   1,  10);
	IP4_ADDR(&netmask, 255, 255, 255,  0);
	IP4_ADDR(&gw,      192, 168,   1,  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);

	/* initialize tcp pcb */
	tcp_send_init();

	XGpio_DiscreteWrite(&Gpio, 1, 1);
	//oled_fresh_en();// enable oled
	Timer_start(&Timer);

	while (1)
	{
		/* call tcp timer every 250ms */
		if(TcpTmrFlag) {
			tcp_tmr();
			TcpTmrFlag = 0;
		}
		/*receive input packet from emac*/
		xemacif_input(netif);
		/* if connected to the server, start receive data from PL through axidma, then transmit the data to the PC software by TCP*/
		if(tcp_client_connected){
			send_received_data();
		}
		if(packet_trans_done) {
			XGpio_DiscreteWrite(&Gpio, 1, 0);
		}
	}
	return 0;
}


2.3 PC端网络配置

关掉电脑网络防火墙!!!!

下载PS程序(debug下载方式)

打开网络调试助手(TCP Server;地址:192.168.1.209)

3. 高速数字系统时钟设计-AD9516

https://blog.csdn.net/m0_37779673/article/details/118459908

4. 高速ADC--ADS62P49

高速高精密ADC数据采集-ADS62P49:https://blog.csdn.net/m0_37779673/article/details/118460370

5. 测试

MATLAB读取TXT数据文件的频谱分析--FFT:

        https://blog.csdn.net/m0_37779673/article/details/119285146

10MHz正弦波采集测试:

50MHz正弦波采集测试:

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

Zynq-LWIP上行传输大批量数据方法说明 的相关文章

  • antd中Form.useForm()使用方式

    这里写自定义目录标题 onRow 表单Form useForm onRow table table record 点击后获取的数据对象 onRow record gt return event获取当前列元素节点 可用 event targe
  • 聚类算法4——DBSCAN密度聚类(算法步骤及matlab代码)

    看了西关书的聚类算法 算法原理很容易明白 接下来就是整理成自己的理解思路 然后一步一步来实现算法 那么就来做吧 DensityClustering算法 概念 从样本密度的角度考察样本之间的可连接性 样本分布的紧密程度刻画聚类结构 术语 核心
  • el-table实现指定列合并

    table传入span method方法可以实现合并行或列 方法的参数是一个对象 里面包含当前行row 当前列column 当前行号rowIndex 当前列号columnIndex四个属性 该函数可以返回一个包含两个元素的数组 第一个元素代
  • Datax-HdfsWriter如何实现支持decimal类型数据写入

    一 问题背景 之前在做Datax数据同步时 发现源端binary decimal等类型的数据无法写入hive字段 看了一下官网文档 DataX HdfsWriter 插件文档 是1 2年前的 当初看过部分源码其实底层hadoop是支持这些类

随机推荐

  • 摸鱼周报年终总结

    今年摸鱼周报的发展超出预期的顺利 离不开各位编辑小伙伴的帮助和读者的支持 非常感谢大家 到了年后最后一周就休刊一期发一个总结吧 今年有很多有趣的事值得再回顾下 编程学习资料点击免费领取 梦开始的地方 最开始的想法 开始写摸鱼周报是因为社群建
  • 华为OD机试 - 字符串变换最小字符串 - (Java 2022Q4 100分)

    目录 一 题目描述 二 输入描述 三 输出描述 四 解题思路 五 Java算法源码 六 效果展示 1 输入 2 输出 华为OD机试 2023B卷题库疯狂收录中 刷题点这里 一 题目描述 给定一个字符串s 最多只能进行一次变换 返回变换后能得
  • 数据分析和可视化必备的几大软件,你用过几个?

    本文主要是面向数据分析初学者 因此分享的基本是一些免编程的可视化工具 详细介绍了7款工具 推荐大家使用 主要是让初学数据分析的朋友知道可视化工具大概有哪些 流行的有哪些 Power BI Power BI是微软开发的商业分析工具 用户可以在
  • 单片机与电脑接口(TTL与RS232电平模拟转换)电路及工作原理分析

    RS232接口概述 RS232接口又称DB9接口 是现在主流的串行通信接口之一 由于RS232接口标准出现较早 难免有不足之处 主要有以下四点 1 接口的信号电平值较高 易损坏接口电路的芯片 又因为与TTL电平不兼容故需使用电平转换电路方能
  • Hibernate缓存机制

    原文地址 http www iteye com topic 249465 缓存是位于应用程序与物理数据源之间 用于临时存放复制数据的内存区域 目的是为了减少应用程序对物理数据源访问的次数 从而提高应用程序的运行性能 Hibernate在查询
  • Pandas必会的方法汇总,用Python做数据分析更加如鱼得水!(附代码)

    用Python做数据分析光是掌握numpy和matplotlib可不够 Pandas是必须要掌握的一个重点 numpy虽然能够帮我们处理处理数值型数据 但是这还不够 很多时候 我们的数据除了数值之外 还有字符串 还有时间序列等 今天来分享一
  • 2022快速计算机视觉EI国际会议汇总

    本文不包含刚举办两三年的国内水会 主要收录了一些或许比较容易中且快速出结果的真正意义上的国际会议 可能存在编辑错误 最终以各会议官网为准 随缘更新 Abbr Name Submission Deadline Notification of
  • 整数在内存中如何存储

    整数在内存中的存储 在计算机内存中 整数一律采用补码的形式来存储 这意味着 当读取整数时还要采用逆向的转换 也就是将补码转换为原码 将补码转换为原码也很简单 先减去 1 再将数值位取反即可 我们先来解以下几个概念 原码 将一个整数转换成二进
  • 刷脸签到系统的设计与实现python+flask+mysql

    刷脸签到系统的设计与实现 语言 工具 html css ajax pyhotn Flask框架 bootstrap框架 SQLAlchemy mysql数据库 介绍 利用Python语言 Flask框架 Dlib库 MySQL数据库等工具设
  • Java线程:线程的调度-守护线程

    本文转载至 http lavasoft blog 51cto com 62575 221845 Java线程 线程的调度 守护线程 守护线程与普通线程写法上基本么啥区别 调用线程对象的方法setDaemon true 则可以将其设置为守护线
  • 贵阳市职称计算机报名时间,贵州贵阳市2013年职称计算机考试报名时间

    一 考试科目 科 目备 注 1中文Windows XP操作系统 2Word 2003中文字处理 3Excel 2003中文电子表格考生任选其一 金山表格2005 4PowerPoint 2003中文演示文稿考生任选其一 金山演示2005 5
  • hping 详解_hping3使用

    简介 hping3是一款免费的数据包生成器和分析器 可用于安全审计 防火墙规则测试 网络测试 端口扫描 性能测试 压力测试 DOS 几乎可以发送任意类型的TCP IP数据包 功能强大但是每次只能向一个IP地址发送数据包 还能够在两个相互包含
  • spring应用从多个properties文件中加载数据的问题

  • arch linux 文档下载_CASTEP的Linux 安装

    CASTEP http www castep org 是一款电子结构软件 可以计算Kohn Sham框架下的平面波DFT 能够完成VASP能够完成的大部分计算 相比于VASP有几个优势 能够完成基本所有VASP能实现的功能和一些VASP不能
  • golang中的随机数rand

    1 math rand 随机数从资源生成 包水平的函数都使用的默认的公共资源 该资源会在程序每次运行时都产生确定的序列 如果需要每次运行产生不同的序列 应使用Seed函数进行初始化 默认资源可以安全的用于多go程并发 关于种子seed 程序
  • nginx实现路由重定向功能 避免服务器出现 404 Not Found

    首先 到服务器上 vue react等项目路由的重定向已解决不了带后缀的访问 这个重定向需要 nginx 来实现 我们先执行 scp r 用户名 如果没设置过就是root 服务器公网地址 etc nginx nginx conf E 拷贝地
  • Java基础最新教程-小白到大神,从api层面到底层原理解抛

    JavaSe JDK JRE JVM是什么 JDK Java Development Kit JRE Java Runtime Environment JVM Java Virtual Machine Java跨平台核心是使用Jvm 在不同
  • Java基础学习之函数式编程Comsumer接口(JDK8)

    前言 从毕业到现在正好三年 高难度的项目做了不少 但是基础这个东西一段时间不接触就会忘得一干二净 话不多说 开始今天的学习 1 Consumer接口 接触过 消费者 生产者 模式的同学 肯定对这个单词不陌生 在java8函数式编程和lamb
  • mcd, lm, VS lx

    LED常识之 mcd lm w的关系 转载自 http 1198 vip blog 163 com blog static 202177117201211624535412 LED 亮度是指发光体 反光体 表面发光 反光 强弱的物理量 人眼
  • Zynq-LWIP上行传输大批量数据方法说明

    此篇是我在学习中做的归纳与总结 其中如果存在版权或知识错误或问题请直接联系我 欢迎留言 PS 本着知识共享的原则 此篇博客可以转载 但请标明出处 目录 1 项目简介 1 1 完成功能 1 1 使用工具 2 LWIP141 DMA上行传输数据