【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设计
设计背景 任务是在ZYNQ的PS上使用裸机运行lwIP协议栈使用TCP把PL端通过AXI DMA传来的将近100K采样率的ADC数据发送出去,但由于数据带宽很大,有853.3mbps,所以在每一次AXI DMA简单传输结束后,lwIP未必有足够的发送buffer立即把数据…...
【TVM 教程】在 Relay 中使用外部库
Apache TVM 是一个端到端的深度学习编译框架,适用于 CPU、GPU 和各种机器学习加速芯片。更多 TVM 中文文档可访问 → https://tvm.hyper.ai/ 作者:Masahiro Masuda,Truman Tian 本文介绍如何将 cuDNN 或 cuBLAS 等外部库与 Relay 一起使用。…...
2024最新大厂面试:汇川嵌入式面试题及参考答案
目录 结合汇川业务,谈谈你对嵌入式开发的理解。 你使用过哪些芯片?请介绍它们的架构,例如 CORTEX-M3。 请描述项目的软件架构及其难点。 请介绍 SPI 的驱动和时序,包括 CS 拉低后到 CLK 第一个跳变沿的时间。同时,也请简要介绍数据链路层的相关知识。 栈溢出的原理是…...
tcp 流量控制
TCP流量控制是TCP/IP协议中用于控制发送方和接收方之间数据传输速率的一种机制,以防止网络拥塞和确保网络资源的有效利用。流量控制主要通过调整TCP窗口大小来实现,确保发送方不会发送超出接收方处理能力的数据量。以下是TCP流量控制的关键概念和工作原理…...

linux离线安装nacos
1、打开 Nacos-GitHub ,点击 Release 可以看到 Nacos 的各版本跟新信息和安装包之类的 点击下载nacos-server-2.4.1.tar.gz,在linux创建nacos文件夹,把下载好的文件上传到nacos文件夹,并通过命令解压:tar -zxvf nacos-server-2.4.…...

云原生 | 在 Kubernetes 中使用 Cilium 替代 Calico 网络插件实践指南!
[ 知识是人生的灯塔,只有不断学习,才能照亮前行的道路 ] 0x00 简述介绍 什么是 Cilium? Cilium 是一款开源软件,它基于一种名为eBPF的新的Linux内核技术提供动力,用于透明地保护使用 Docker 和 Kubernetes 等Linux 容器管理平台中部署的应用程序服务之间的网络连接,Ciliu…...

【重学 MySQL】十一、SQL 概述
【重学 MySQL】十一、SQL 概述 SQL 背景知识产生与发展主要特点主要应用SQL语言的发展趋势 SQL 语言排行榜SQL 分类数据查询语言(DQL, Data Query Language)数据操纵语言(DML, Data Manipulation Language)数据定义语言࿰…...

(一)模式识别——基于SVM的道路分割实验(附资源)
写在前面:本报告所有代码公开在附带资源中,无法下载代码资源的伙伴私信留下邮箱,小编24小时内回复 一、实验目的 1、实验目标 学习掌握SVM(Support Vector Machine)算法思想,利用MATLAB的特定工具箱和库函…...

Python | Leetcode Python题解之第391题完美矩形
题目: 题解: class Solution:def isRectangleCover(self, rectangles: List[List[int]]) -> bool:area, minX, minY, maxX, maxY 0, rectangles[0][0], rectangles[0][1], rectangles[0][2], rectangles[0][3]cnt defaultdict(int)for rect in rec…...

Rust模块std::thread
【图书介绍】《Rust编程与项目实战》-CSDN博客 《Rust编程与项目实战》(朱文伟,李建英)【摘要 书评 试读】- 京东图书 (jd.com) Rust到底值不值得学,之一 -CSDN博客 Rust到底值不值得学,之二-CSDN博客 Rust多线程编程概述-CSDN博客 12.…...
Leetcode Day20 打家劫舍
198 最基础 class Solution:def rob(self, nums: List[int]) -> int:dp1 [0] * len(nums)dp2 [0] * len(nums)# dp1指第i天偷了, dp2指第i天没有偷dp1[0] nums[0]for i in range(1, len(nums)):dp1[i] dp2[i - 1] nums[i]dp2[i] max(dp1[i - 1], dp2[i - 1])return m…...

云计算之数据库
目录 一、RDS产品介绍及排障思路 1.1 云RDS数据库及其特点 1.2 云RDS数据库-规格 1.3 云RDS数据库-存储 1.4 云RDS数据库-安全 1.5 云RDS数据库-整体架构 1.6 RDS常见问题排查 1.6.1 如何解决无法链接RDS实例的问题 1.6.2 RDS实例存储空间使用率高,怎…...
开发软件,什么类型的重要信息的日志要存到数据库表里面
在开发软件时,选择将哪些类型的重要信息日志存储到数据库表里面,主要取决于这些日志的用途、查询需求、性能考虑以及系统架构。以下是一些通常会选择存储到数据库表中的重要信息日志类型: 1. 业务日志: 交易记录:记录…...
websocket和轮询的区别?
问: websocket和轮询的区别? 回答: WebSocket 和定时轮询(每隔几秒发送一次请求)是两种不同的实时通信方法,各有优缺点,适用于不同的场景。以下是它们的主要区别及适用场景: WebSo…...

2024 年全国大学生数学建模竞赛(国赛)浅析
需要完整资料,请关注WX:“小何数模”! (需要完整B、C和E题资料请关注WX:“小何数模”,获取资料链接!) 本次万众瞩目的全国大学生数学建模赛题已正式出炉,无论是赛题难度…...

持续集成与持续部署(CI/CD)的深入探讨
在现代软件开发中,持续集成(CI)和持续部署(CD)已成为不可或缺的实践。这些方法旨在加快软件交付的速度,同时提高软件的质量和稳定性。通过CI/CD,开发团队可以频繁地将代码更改集成到主分支&…...

hyperf json-rpc
安装 安装docker hyperf 安装 hyperf-rpc-server-v8 (服务端) docker run --name hyperf-rpc-server-v8 \ -v /www/docker/hyperf-rpc-server:/data/project \ -w /data/project \ -p 9508:9501 -it \ --privileged -u root \ --entrypoint /bin/sh \…...

基于SpringBoot的外卖点餐系统
你好呀,我是计算机学姐码农小野!如果有相关需求,可以私信联系我。 开发语言:Java 数据库:MySQL 技术:SpringBootJSP 工具:IDEA/Eclipse、Navicat、Maven、Tomcat 系统展示 首页 用户管理界…...

网络编程day02(字节序、TCP编程)
目录 【1】字节序 1》大小端转换 2》端口转换 3》IP地址转换 主机字节序转换为网络字节序 (小端序->大端序) 网络字节序转换为主机字节序(大端序->小端序) 【2】TCP编程 1》流程 2》函数接口 1> socket 2> …...
萌新6:临场发挥(区间dp)
题目描述 小x和室友总共 nnn 人,组团去打一款游戏,总共有 nnn 台电脑供他们使用,一人一台,最开始,第 iii 个人使用第 iii 台电脑。 小x评估了每个人的能力值和临场发挥值。 第 iii 个人的能力值为 aia_iai。 而他们…...
uni-app学习笔记二十二---使用vite.config.js全局导入常用依赖
在前面的练习中,每个页面需要使用ref,onShow等生命周期钩子函数时都需要像下面这样导入 import {onMounted, ref} from "vue" 如果不想每个页面都导入,需要使用node.js命令npm安装unplugin-auto-import npm install unplugin-au…...

无法与IP建立连接,未能下载VSCode服务器
如题,在远程连接服务器的时候突然遇到了这个提示。 查阅了一圈,发现是VSCode版本自动更新惹的祸!!! 在VSCode的帮助->关于这里发现前几天VSCode自动更新了,我的版本号变成了1.100.3 才导致了远程连接出…...

聊聊 Pulsar:Producer 源码解析
一、前言 Apache Pulsar 是一个企业级的开源分布式消息传递平台,以其高性能、可扩展性和存储计算分离架构在消息队列和流处理领域独树一帜。在 Pulsar 的核心架构中,Producer(生产者) 是连接客户端应用与消息队列的第一步。生产者…...

什么是库存周转?如何用进销存系统提高库存周转率?
你可能听说过这样一句话: “利润不是赚出来的,是管出来的。” 尤其是在制造业、批发零售、电商这类“货堆成山”的行业,很多企业看着销售不错,账上却没钱、利润也不见了,一翻库存才发现: 一堆卖不动的旧货…...

Keil 中设置 STM32 Flash 和 RAM 地址详解
文章目录 Keil 中设置 STM32 Flash 和 RAM 地址详解一、Flash 和 RAM 配置界面(Target 选项卡)1. IROM1(用于配置 Flash)2. IRAM1(用于配置 RAM)二、链接器设置界面(Linker 选项卡)1. 勾选“Use Memory Layout from Target Dialog”2. 查看链接器参数(如果没有勾选上面…...

uniapp微信小程序视频实时流+pc端预览方案
方案类型技术实现是否免费优点缺点适用场景延迟范围开发复杂度WebSocket图片帧定时拍照Base64传输✅ 完全免费无需服务器 纯前端实现高延迟高流量 帧率极低个人demo测试 超低频监控500ms-2s⭐⭐RTMP推流TRTC/即构SDK推流❌ 付费方案 (部分有免费额度&#x…...

智能仓储的未来:自动化、AI与数据分析如何重塑物流中心
当仓库学会“思考”,物流的终极形态正在诞生 想象这样的场景: 凌晨3点,某物流中心灯火通明却空无一人。AGV机器人集群根据实时订单动态规划路径;AI视觉系统在0.1秒内扫描包裹信息;数字孪生平台正模拟次日峰值流量压力…...

微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据
微软PowerBI考试 PL300-在 Power BI 中清理、转换和加载数据 Power Query 具有大量专门帮助您清理和准备数据以供分析的功能。 您将了解如何简化复杂模型、更改数据类型、重命名对象和透视数据。 您还将了解如何分析列,以便知晓哪些列包含有价值的数据,…...
Android第十三次面试总结(四大 组件基础)
Activity生命周期和四大启动模式详解 一、Activity 生命周期 Activity 的生命周期由一系列回调方法组成,用于管理其创建、可见性、焦点和销毁过程。以下是核心方法及其调用时机: onCreate() 调用时机:Activity 首次创建时调用。…...

使用LangGraph和LangSmith构建多智能体人工智能系统
现在,通过组合几个较小的子智能体来创建一个强大的人工智能智能体正成为一种趋势。但这也带来了一些挑战,比如减少幻觉、管理对话流程、在测试期间留意智能体的工作方式、允许人工介入以及评估其性能。你需要进行大量的反复试验。 在这篇博客〔原作者&a…...