【ZYNQ MPSoC开发】lwIP TCP发送用于数据缓存的软件FIFO设计

2024-09-02 09:52

本文主要是介绍【ZYNQ MPSoC开发】lwIP TCP发送用于数据缓存的软件FIFO设计,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

设计背景

       任务是在ZYNQ的PS上使用裸机运行lwIP协议栈使用TCP把PL端通过AXI DMA传来的将近100K采样率的ADC数据发送出去,但由于数据带宽很大,有853.3mbps,所以在每一次AXI DMA简单传输结束后,lwIP未必有足够的发送buffer立即把数据发送走,如果是发送完再进行下一次简单传输的思路,则会很大地限制了整个系统的带宽,一个简单的思路是每次传输完成后判断发送buffer是否足够,如果不够,先把数据放进软件FIFO里,等待有buffer时再发出去,如果足够的话,则进行发送,当然必须优先发送FIFO里的数据,而后马上进行下一次简单传输,下面是软件FIFO的代码部分。

软件FIFO代码

       1,FIFO结构体定义如下:

typedef struct {unsigned int *data;int head;int tail;int size;int capacity;int size_max;
} FIFO;

​ data存放FIFO数据放置的地址指针,head头用于读,tail尾用于写,size表示了当前FIFO存放的等待发送出去的数据包的组数(我这里的数据包是8次简单传输的数据量,大家可以根据自己需求定,并不是字节数!!!),capacity是整个FIFO的容量,size_max用于记录FIFO的一定时间间隔内的数组组数的最大值(前期调试用)。

       2,初始化部分如下:

// 初始化FIFO
void sending_fifo_init(FIFO *fifo, int capacity)
{
//    fifo->data = (unsigned int *)malloc(capacity * MY_TCP_SEND_BUFSIZE);
//    if (!fifo->data) {
//        perror("Failed to allocate memory for FIFO");
//        exit(EXIT_FAILURE);
//    }fifo->data = (unsigned int *)SEND_FIFO_BASE;fifo->head = 0;		//头部fifo->tail = 0;		//尾部fifo->size = 0;		//当前数据大小fifo->size_max = 0;	//每个时间间隔size最大值fifo->capacity = capacity;		//总容量if(capacity > FIFO_SIZE_MAX){fifo->capacity = FIFO_SIZE_MAX;   }else{fifo->capacity = capacity;}}

       这里需要注意的是没有采用malloc去动态分配内存,这主要是因为在ZYNQ这样的嵌入式设备特别是跑裸机时,这样分配很容易报错。

       3,与size相关的函数

​       一是检查FIFO是否已满,1为满,0为不满。

bool fifo_is_full(FIFO *fifo)
{return fifo->size == fifo->capacity;
}

       二是检查FIFO是否为空,1为空,0为不空。

bool fifo_is_empty(FIFO *fifo)
{return fifo->size == 0;
}

       更灵活的,也给出直接获取size用于打印以及其他辅助调试。

int fifo_get_size(FIFO *fifo)
{return fifo->size;
}

       由于我是每5s打印一次这个时间段的带宽,在调试阶段也想看看FIFO的使用情况,就有了以下的记录fifo最大值的函数,然后在每次打印报告时给最大size清零。

void fifo_record_max_size(FIFO *fifo)
{int size_current = fifo_get_size(fifo);if (size_current > fifo->size_max){fifo->size_max = size_current;}}

       4,整个FIFO部分最重要的部分就是入队与出队的操作,入队代码如下:

bool fifo_enqueue(FIFO *fifo,char *lwip_array_ptr)
{if (fifo_is_full(fifo)) {printf("FIFO is full, cannot enqueue\r\n");return;}memcpy((fifo->data + fifo->tail * MY_TCP_SEND_BUFSIZE / 4), lwip_array_ptr, MY_TCP_SEND_BUFSIZE);fifo->tail = (fifo->tail + 1) % fifo->capacity;  // 循环队列处理fifo->size++;fifo_record_max_size(fifo);}

       首先入队必须要保证FIFO是不为满的,其次是在使用memcpy函数拷贝数据时,注意第一个参数的结果是个什么类型,从而保证每组数据之间是在内存上连续的,不清楚的话,可以先按自己的理解给一个递进制,直接debug看看再进行修改。整个FIFO的运行逻辑是充分利用开辟出来的内存,做一个循环队列处理,而不是size = x的数据放在固定的位置。

​       出队同理:

// 出队操作
bool fifo_dequeue(FIFO *fifo,char *lwip_array_ptr)
{if (fifo_is_empty(fifo)) {printf("FIFO is empty, cannot dequeue\r\n");return false;}memcpy(lwip_array_ptr, (fifo->data + fifo->head * MY_TCP_SEND_BUFSIZE / 4), MY_TCP_SEND_BUFSIZE);fifo->head = (fifo->head + 1) % fifo->capacity;  // 循环队列处理fifo->size--;return true;}

​       5,后面如果FIFO不用了,可以进行销毁:

// 销毁FIFO
void fifo_destroy(FIFO *fifo)
{free(fifo->data);fifo->data = NULL;fifo->head = fifo->tail = fifo->size = fifo->capacity = 0;
}

这篇关于【ZYNQ MPSoC开发】lwIP TCP发送用于数据缓存的软件FIFO设计的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1129639

相关文章

大模型研发全揭秘:客服工单数据标注的完整攻略

在人工智能(AI)领域,数据标注是模型训练过程中至关重要的一步。无论你是新手还是有经验的从业者,掌握数据标注的技术细节和常见问题的解决方案都能为你的AI项目增添不少价值。在电信运营商的客服系统中,工单数据是客户问题和解决方案的重要记录。通过对这些工单数据进行有效标注,不仅能够帮助提升客服自动化系统的智能化水平,还能优化客户服务流程,提高客户满意度。本文将详细介绍如何在电信运营商客服工单的背景下进行

不懂推荐算法也能设计推荐系统

本文以商业化应用推荐为例,告诉我们不懂推荐算法的产品,也能从产品侧出发, 设计出一款不错的推荐系统。 相信很多新手产品,看到算法二字,多是懵圈的。 什么排序算法、最短路径等都是相对传统的算法(注:传统是指科班出身的产品都会接触过)。但对于推荐算法,多数产品对着网上搜到的资源,都会无从下手。特别当某些推荐算法 和 “AI”扯上关系后,更是加大了理解的难度。 但,不了解推荐算法,就无法做推荐系

基于MySQL Binlog的Elasticsearch数据同步实践

一、为什么要做 随着马蜂窝的逐渐发展,我们的业务数据越来越多,单纯使用 MySQL 已经不能满足我们的数据查询需求,例如对于商品、订单等数据的多维度检索。 使用 Elasticsearch 存储业务数据可以很好的解决我们业务中的搜索需求。而数据进行异构存储后,随之而来的就是数据同步的问题。 二、现有方法及问题 对于数据同步,我们目前的解决方案是建立数据中间表。把需要检索的业务数据,统一放到一张M

这15个Vue指令,让你的项目开发爽到爆

1. V-Hotkey 仓库地址: github.com/Dafrok/v-ho… Demo: 戳这里 https://dafrok.github.io/v-hotkey 安装: npm install --save v-hotkey 这个指令可以给组件绑定一个或多个快捷键。你想要通过按下 Escape 键后隐藏某个组件,按住 Control 和回车键再显示它吗?小菜一碟: <template

关于数据埋点,你需要了解这些基本知识

产品汪每天都在和数据打交道,你知道数据来自哪里吗? 移动app端内的用户行为数据大多来自埋点,了解一些埋点知识,能和数据分析师、技术侃大山,参与到前期的数据采集,更重要是让最终的埋点数据能为我所用,否则可怜巴巴等上几个月是常有的事。   埋点类型 根据埋点方式,可以区分为: 手动埋点半自动埋点全自动埋点 秉承“任何事物都有两面性”的道理:自动程度高的,能解决通用统计,便于统一化管理,但个性化定

Hadoop企业开发案例调优场景

需求 (1)需求:从1G数据中,统计每个单词出现次数。服务器3台,每台配置4G内存,4核CPU,4线程。 (2)需求分析: 1G / 128m = 8个MapTask;1个ReduceTask;1个mrAppMaster 平均每个节点运行10个 / 3台 ≈ 3个任务(4    3    3) HDFS参数调优 (1)修改:hadoop-env.sh export HDFS_NAMENOD

使用SecondaryNameNode恢复NameNode的数据

1)需求: NameNode进程挂了并且存储的数据也丢失了,如何恢复NameNode 此种方式恢复的数据可能存在小部分数据的丢失。 2)故障模拟 (1)kill -9 NameNode进程 [lytfly@hadoop102 current]$ kill -9 19886 (2)删除NameNode存储的数据(/opt/module/hadoop-3.1.4/data/tmp/dfs/na

异构存储(冷热数据分离)

异构存储主要解决不同的数据,存储在不同类型的硬盘中,达到最佳性能的问题。 异构存储Shell操作 (1)查看当前有哪些存储策略可以用 [lytfly@hadoop102 hadoop-3.1.4]$ hdfs storagepolicies -listPolicies (2)为指定路径(数据存储目录)设置指定的存储策略 hdfs storagepolicies -setStoragePo

Hadoop集群数据均衡之磁盘间数据均衡

生产环境,由于硬盘空间不足,往往需要增加一块硬盘。刚加载的硬盘没有数据时,可以执行磁盘数据均衡命令。(Hadoop3.x新特性) plan后面带的节点的名字必须是已经存在的,并且是需要均衡的节点。 如果节点不存在,会报如下错误: 如果节点只有一个硬盘的话,不会创建均衡计划: (1)生成均衡计划 hdfs diskbalancer -plan hadoop102 (2)执行均衡计划 hd

嵌入式QT开发:构建高效智能的嵌入式系统

摘要: 本文深入探讨了嵌入式 QT 相关的各个方面。从 QT 框架的基础架构和核心概念出发,详细阐述了其在嵌入式环境中的优势与特点。文中分析了嵌入式 QT 的开发环境搭建过程,包括交叉编译工具链的配置等关键步骤。进一步探讨了嵌入式 QT 的界面设计与开发,涵盖了从基本控件的使用到复杂界面布局的构建。同时也深入研究了信号与槽机制在嵌入式系统中的应用,以及嵌入式 QT 与硬件设备的交互,包括输入输出设