【STM32 FreeRTOS】队列和缓冲区

队列简介

队列是任务到任务、任务到中断、中断到任务数据交流的一种机制。

队列可以容纳有限数量的固定大小的数据项。一个队列可以容纳的最大项目数称为它的长度。

  • 数据入队出队方式:队列通常用作先进先出(FIFO)缓冲区,其中数据被写入队列的末尾,并从队列的头部删除。FreeRTOS中也可以配置为“后进先出”的方式。
  • 数据传递方式:FreeRTOS中队列采用实际值传递,即将数据拷贝到队列中进行传递,FreeRTOS采用拷贝数据传递,也可以传递指针,所以在传递较大数据的时候采用指针传递。
  • 多任务访问:队列不属于某个任务,任何任务和中断都可以向队列发送/读取消息。
  • 可阻塞:当任务向一个队列发送消息时,可以指定一个阻塞时间,假设此时当队列已满无法入队,若阻塞时间为0,直接返回不会等待;若阻塞时间为0~port_MAX_DELAY,则等待设定的阻塞时间,若在该时间内还无法入队,超时后直接返回不再等待;若阻塞时间为port_MAX_DELAY,则一直等到可以入队为止。出队阻塞与入队阻塞类似。

当一个任务试图从队列中读取数据时,它可以指定一个“阻塞”时间。

队列为空的时候无法读取,这个时候就会阻塞,当另一个任务或中断将数据放入队列中时,处于阻塞态的任务将自动移动到就绪态。如果指定的阻塞时间到了,还是没有数据,任务也将自动移到就绪态。

可能存在多个任务读取队列,因此单个队列上可能阻塞了多个等待数据的任务。在这种情况下,当有数据时,只有一个任务将被解除阻塞。被解除阻塞的任务将始终是等待数据的任务中优先级最高的那个任务。如果阻塞的任务具有相同的优先级,则等待数据时间最长的任务将被解除阻塞。

队列使用

 BaseType_t xQueueSend(QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);BaseType_t xQueueSend(QueueHandle_t xQueue,const void * pvItemToQueue,TickType_t xTicksToWait);BaseType_t xQueueSendFromISR(QueueHandle_t xQueue,const void *pvItemToQueue,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueueReceive(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait
);BaseType_t xQueueReceiveFromISR(QueueHandle_t xQueue,void *pvBuffer,BaseType_t *pxHigherPriorityTaskWoken);BaseType_t xQueuePeek(QueueHandle_t xQueue,void *pvBuffer,TickType_t xTicksToWait);BaseType_t xQueuePeekFromISR(QueueHandle_t xQueue,void *pvBuffer,);

这些函数的使用就不做实例了,可以直接参考官网。我们重点进入下一章节。

为什么要有xQueueSendFromISR函数

xQueueSendFromISR执行完后不会立即进入任务调度,而是会标记,等退出中断后再进行任务调度。这样做的原因是中断服务程序的执行时间需要尽可能短,以避免影响其他中断的处理和任务的执行。

此外,xQueueSendFromISR函数在发送消息时不需要设置阻塞时间值,因为它是在中断服务程序中调用的,而不是在任务中。如果队列已满,xQueueSendFromISR会返回错误码errQUEUE_FULL,否则返回pdTRUE表示消息发送成功。

在实际应用中,使用FromISR函数时需要注意以下几点:

  • 中断函数的执行时间应尽可能短,避免影响其他中断的响应。
  • 推荐不在中断中处理消息,而是在中断服务程序中发送消息通知任务,在任务重处理消息,以保证中断的实时响应。

流缓冲区简介

流缓冲区专用于传输流式数据,如音频和视频等大数据块。它通过一个环形缓冲区来存储数据。流缓冲区允许将字节流从中断服务函数传递到任务重,或从一个任务传递到另一个任务重。字节流可以是任意长度,并且不一定具有开头或结尾。可以一次写入任意数量的字节,并且可以一次读取任意数量的字节。数据通过复制传递,数据有发送发复制到缓冲区中,并通过读取从缓冲区中复制出来。
触发级别是指定在缓冲区中必须有多少字节数据时,因等待数据而阻塞的任务会被解除阻塞。流缓冲区针对单一生产者和单一消费者场景进行了优化。如果有多个不同的写入者或读取者,应用程序设计者必须确保每次对流缓冲区的访问都在临界区内,并使用非阻塞调用 。流缓冲区在每次发送和接收操作完成后可以执行回调函数。这些回调函数可以通过sbSEND_COMPLETED和sbRECEIVE_COMPLETED宏进行自定义实现。

// 创建流缓冲区
// xBufferSizeBytes表示流缓冲区容量(字节)
// xTriggerLevelBytes读取等待字节数(触发等级),如果写0会被重置为1
StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );// 删除流缓冲区
void vStreamBufferDelete( StreamBufferHandle_t xStreamBuffer );// 向流缓冲区写数据,如果空间不足无法写入将阻塞直至超时
// pvTxData为要写入的消息首指针
// xDataLengthBytes为要写入的消息长度,写入时会额外占用sizeof(size_t)字节空间,对于32架构来说将额外占用4字节
// 返回写入字节数
size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait );
// 写数据中断版本,不会阻塞
size_t xStreamBufferSendFromISR( StreamBufferHandle_t xStreamBuffer, const void *pvTxData, size_t xDataLengthBytes, BaseType_t *pxHigherPriorityTaskWoken );// 从流缓冲区读数据,如果没有数据可读取将阻塞直至超时
// pvRxData为要接收数据的数组首指针
// xBufferLengthBytes接收消息的数组长度
// 返回读取字节数
size_t xStreamBufferReceive( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait );
// 读数据中断版本,不会阻塞
size_t xStreamBufferReceiveFromISR( StreamBufferHandle_t xStreamBuffer, void *pvRxData, size_t xBufferLengthBytes, BaseType_t *pxHigherPriorityTaskWoken );// 返回缓冲区可读字节数
size_t xStreamBufferBytesAvailable( StreamBufferHandle_t xStreamBuffer );
// 返回缓冲区可写字节数
size_t xStreamBufferSpacesAvailable( StreamBufferHandle_t xStreamBuffer );
// 查看缓冲区是否为空
BaseType_t xStreamBufferIsEmpty( StreamBufferHandle_t xStreamBuffer );
// 查看缓冲区是否已满
BaseType_t xStreamBufferIsFull( StreamBufferHandle_t xStreamBuffer );// 设置缓冲区触发等级
BaseType_t xStreamBufferSetTriggerLevel( StreamBufferHandle_t xStreamBuffer, size_t xTriggerLevel );
// 将缓冲区重置为空,只有缓冲区没有在使用时才可设置
BaseType_t xStreamBufferReset( StreamBufferHandle_t xStreamBuffer );

消息缓冲区简介

消息缓冲区(Message Buffer)是一种用于在任务或中断服务例程之间传递变长离散消息的数据结构。与流缓冲区(Stream Buffer)不同,消息缓冲区在存储消息内容之前,会先存储消息的长度信息,这样在读取时就必须以完整的消息为单位进行。
发送消息到消息缓冲区时,可以使用xMessageBufferSend函数,该函数允许发送任意长度的消息,只要缓冲区有足够的空间。当消息被写入时,会先写入消息的长度,然后再写入消息内容本身。消息的长度信息通常占用4个字节(这取决于架构,32位架构上通常为4字节)。
开发者在使用消息缓冲区时,应根据具体需求调整缓冲区大小,并优化数据处理流程,以实现最佳性能。消息缓冲区适用于需要按消息包进行传输的场景,例如长度为10、20和123字节的消息都可以在同一个消息缓冲区写入或读取。发送和接收完成回调函数可以通过sbSEND_COMPLETED和sbRECEIVE_COMPLETED宏进行定义。

// 创建消息缓冲区
MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );// 删除消息缓冲区
void vMessageBufferDelete( MessageBufferHandle_t xMessageBuffer );// 向消息缓冲区写数据,如果空间不足无法写入将阻塞直至超时
// pvTxData为要写入的消息首指针
// xDataLengthBytes为要写入的消息长度,每次写入时会额外占用sizeof(size_t)字节空间,对于32架构来说将额外占用4字节
size_t xMessageBufferSend( MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait );
// 写数据中断版本,不会阻塞
size_t xMessageBufferSendFromISR( MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t xDataLengthBytes, BaseType_t *pxHigherPriorityTaskWoken );// 从消息冲区读数据,如果没有数据可读取将阻塞直至超时
// pvRxData为要接收数据的数组首指针
// xBufferLengthBytes接收消息的数组长度
// 返回读取字节数
// 从消息缓冲区中读取数据是以一个个消息为单位进行读取的
size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait );
// 读数据中断版本,不会阻塞
size_t xMessageBufferReceiveFromISR( MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t xBufferLengthBytes, BaseType_t *pxHigherPriorityTaskWoken );// 返回缓冲区可写字节数
size_t xMessageBufferSpacesAvailable( MessageBufferHandle_t xMessageBuffer );
// 查看缓冲区是否为空
BaseType_t xMessageBufferIsEmpty( MessageBufferHandle_t xMessageBuffer );
// 查看缓冲区是否已满
BaseType_t xMessageBufferIsFull( MessageBufferHandle_t xMessageBuffer );// 将缓冲区重置为空,只有缓冲区没有在使用时才可设置
BaseType_t xMessageBufferReset( MessageBufferHandle_t xMessageBuffer );

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/pingmian/51882.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

强大的接口测试可视化工具:Postman Flows

Postman Flows是一种接口测试可视化工具,可以使用流的形式在Postman工作台将请求接口、数据处理和创建实际流程整合到一起。如下图所示 Postman Flows是以API为中心的可视化应用程序开发界面。它提供了一个无限的画布用于编排和串连API,数据可视化来显示…

html转vue项目

HTML是一种用于构建网页的标记语言,而Vue是一种用于构建用户界面的JavaScript框架。在HTML中使用Vue可以提供更加灵活和动态的用户界面功能。本文将介绍如何将HTML代码转换为Vue,并提供具体的代码示例。 首先,我们需要在项目中引入Vue框架。…

30. 串联所有单词的子串【 力扣(LeetCode) 】

一、题目描述 给定一个字符串 s 和一个字符串数组 words。 words 中所有字符串 长度相同。 s 中的 串联子串 是指一个包含 words 中所有字符串以任意顺序排列连接起来的子串。 例如,如果 words [“ab”,“cd”,“ef”], 那么 “abcdef”,…

配置oss cdn加速静态资源访问 阿里云

效果对比 配置cdn下载速度对比 步骤 1: 登录阿里云控制台控制台主页,找到并点击“对象存储 OSS” 创建存储空间(Bucket) 设置权限 步骤 2: 获取外网访问地址 步骤 3 在 CDN 中使用该地址 复制该外网访问地址 打开全站加速 DCDN/域名管理 添…

thinkphp8 定时任务

在ThinkPHP8中创建定时任务通常涉及到Cron作业调度或者操作系统的定时任务功能(如cronjob)。以下是一个使用操作系统的cronjob的例子。 创建一个命令: // app/Command/ExampleCommand.php namespace app\Command;use think\console\Command; …

社群机器人的崛起:重塑社群管理的智慧未来

在数字化浪潮的推动下,社群作为连接人与人、促进信息交流与情感共鸣的桥梁,其重要性日益凸显。然而,随着社群规模的日益庞大和成员需求的多元化,传统的人工管理方式已难以满足高效、精准的管理需求。此时,社群机器人的…

P9750 [CSP-J 2023] 一元二次方程

[题目通道]([CSP-J 2023] 一元二次方程 - 洛谷) #include<bits/stdc.h> using namespace std; int T,m,a,b,c,d,k,t; int gcd(int a,int b){return b?gcd(b,a%b):a; } void kkksc03(){cin>>a>>b>>c;if(a<0)a-a,b-b,c-c;db*b-4*a*c,k1;if(d<0)…

Shell——读取命令read

在 Shell 编程中&#xff0c;read 命令用于从标准输入&#xff08;通常是键盘&#xff09;读取数据并将其存储在变量中。它非常适合用于交互式脚本&#xff0c;让用户能够输入数据。 基本用法 以下是 read 命令的基本用法&#xff1a; #!/bin/bashecho "请输入您的名字…

STM32 PWR电源控制 与 低功耗模式 详解

目录 STM32 PWR电源控制 与 低功耗模式 详解 1. PWR 电源控制 简介 2. PWR 电源控制 框图 3. 上电复位和掉电复位 与 可编程电压检测器&#xff08;PVD&#xff09; 3.1 内嵌复位与电源控制模块特性图 3.2 上电复位和掉电复位 3.3 可编程电压检测器&#xff08;PVD&…

微分方程(Blanchard Differential Equations 4th)中文版Section1.6

平衡点与相直线 给定一个微分方程 d y d t = f ( t , y ) , \frac{dy}{dt} = f(t, y), dtdy​=f(t,y), 我们可以通过绘制斜率场和勾勒图形来大致了解解的行为,或者使用欧拉法计算近似解。有时我们甚至可以推导出解的显式公式并绘制结果。所有这些技术都需要相当多的工作,无…

Python酷库之旅-第三方库Pandas(089)

目录 一、用法精讲 376、pandas.Series.list.flatten方法 376-1、语法 376-2、参数 376-3、功能 376-4、返回值 376-5、说明 376-6、用法 376-6-1、数据准备 376-6-2、代码示例 376-6-3、结果输出 377、pandas.Series.list.__getitem__魔法方法 377-1、语法 377-…

数据仓库: 3- ETL过程

目录 3- ETL过程3.1 数据抽取&#xff08;Extract&#xff09;3.1.1 数据抽取的挑战3.1.2 数据抽取的方式3.1.2.1 全量抽取3.1.2.2 增量抽取3.1.2.3 实时抽取 3.1.3 数据抽取的技术3.1.4 数据抽取工具3.1.5 总结 3.2 数据转换&#xff08;Transform&#xff09;3.2.1 定义3.2.2…

24.8.19学习笔记(MNIST,)

pytorch MNIST手写数字识别&#xff1a; import torch import torch.nn as nn import torch.optim as optim from torchvision import datasets, transforms# 设定随机种子以保证结果可复现 torch.manual_seed(0)# 定义超参数 batch_size 32 learning_rate 0.001 num_epochs…

机器学习第十一章--特征选择与稀疏学习

一、子集搜索与评价 我们将属性称为 “特征”(feature&#xff09;&#xff0c;对当前学习任务有用的属性称为 “相关特征”(relevant feature&#xff09;、没什么用的属性称为 “无关特征”(irrelevant feature)&#xff0e;从给定的特征集合中选择出相关特征子集的过程&…

C++竞赛初阶L1-13-第五单元-循环嵌套(29~30课)535: T456454 数字统计

题目内容 请统计某个给定范围 [L,R] 的所有整数中&#xff0c;数字 2 出现的次数。 比如给定范围 [2,22]&#xff0c;数字 2 在数 2 中出现了 1 次&#xff0c;在数 12 中出现 1 次&#xff0c;在数 20 中出现 1 次&#xff0c;在数 21 中出现 1 次&#xff0c;在数 22 中出现…

【开发语言】编译型语言和解释性语言有啥区别?

作为一名从业多年的程序员,对于编译型语言和解释型语言之间的区别有着深入的理解。这两种类型的编程语言在将源代码转换成可执行代码的过程中采用了不同的机制,这导致了它们在执行效率、跨平台性、安全性以及开发效率等方面存在一些差异。 编译型语言(Compiled Languages)…

Java项目集成RocketMQ

文章目录 1.调整MQ的配置1.进入bin目录2.关闭broker和namesrv3.查看进程确认关闭4.编辑配置文件broker.conf&#xff0c;配置brokerIP15.开放端口109116.重新启动1.进入bin目录2.启动mqnamesrv和mqbroker1.启动 NameServer 并将输出重定向到 mqnamesrv.log2.**启动 Broker 并将…

easyexcel--导入导出实现自定义格式转换

自定义格式 我们在数据库设计的时候经常会有枚举类型&#xff0c;如0表示普通用户&#xff0c;1表示VIP用户等&#xff0c;这在excel导入的时候&#xff0c;我们会填普通用户而不是0&#xff0c;这样就需要用到自定义格式把普通用户转换成0&#xff0c;我写了一个通用的抽象类…

深度学习基础—RMSprop算法与Adam 优化算法

1.RMSprop算法 1.1.算法流程 除了动量梯度下降法&#xff0c;RMSprop算法也可以加快梯度下降&#xff0c;这个算法的算法流程如下&#xff1a;深度学习基础—动量梯度下降法http://t.csdnimg.cn/zeGRo 1.2.算法原理 和动量梯度下降不同的是&#xff0c;对dW和db的变成了平方项…

什么是视频比特率?与视频时长是什么关系

​ ‌比特率是指单位时间内传输或处理的比特的数量&#xff0c;单位为‌bps(‌bit per second)。‌ 比特率经常用于描述在电信和计算领域中数据传输的速度&#xff0c;也可以作为衡量音频和视频文件数据率的指标。比特率越高&#xff0c;传送的数据越大&#xff0c;音频或视频…