14.FreeRTOS 消息缓存 Message Buffer

FreeRTOS 消息缓存(Message Buffer)的使用

介绍


在实时操作系统(RTOS)中,任务之间的通信是一个非常重要的方面。FreeRTOS 提供了多种机制来实现任务间通信,其中之一就是消息缓存(Message Buffer)。消息缓存非常适合传递长度可变的消息,并且在性能和灵活性方面提供了很大的优势。

什么是消息缓存?

消息缓存是 FreeRTOS 提供的一种数据结构,用于在任务之间传递变长消息。与队列不同,队列适合固定长度的数据项,而消息缓存可以处理长度可变的消息。这使得消息缓存非常适用于需要传递不同长度消息的场景,比如传输字符串或结构化数据。

消息缓存的工作原理

消息缓存的基本操作包括创建、发送和接收消息。以下是其主要操作:

  1. 创建消息缓存:使用 xMessageBufferCreate 函数创建一个新的消息缓存。
  2. 发送消息到消息缓存:任务使用 xMessageBufferSend 将消息发送到缓存中。
  3. 从消息缓存接收消息:任务使用 xMessageBufferReceive 从缓存中接收消息。

实例:使用 FreeRTOS 消息缓存进行任务通信

下面是一个使用消息缓存在两个任务之间传递消息的完整示例。在这个示例中,一个任务负责发送消息,另一个任务负责接收消息。

#include <Arduino.h>
#include <FreeRTOS.h>
#include <message_buffer.h>// 消息缓存句柄
MessageBufferHandle_t xMessageBuffer;// 发送任务
void vSenderTask(void *pvParameters) {const char *message = "Hello, FreeRTOS!";while (1) {// 发送消息size_t bytesSent = xMessageBufferSend(xMessageBuffer, message, strlen(message), pdMS_TO_TICKS(1000));if (bytesSent < strlen(message)) {Serial.println("Failed to send complete message");}// 每 2 秒发送一次vTaskDelay(pdMS_TO_TICKS(2000));}
}// 接收任务
void vReceiverTask(void *pvParameters) {char buffer[50];while (1) {// 接收消息size_t bytesReceived = xMessageBufferReceive(xMessageBuffer, buffer, sizeof(buffer), portMAX_DELAY);if (bytesReceived > 0) {buffer[bytesReceived] = '\0'; // 确保字符串以 NULL 结尾Serial.print("Received: ");Serial.println(buffer);} else {Serial.println("Failed to receive message");}}
}void setup() {// 初始化串口Serial.begin(115200);while (!Serial) {}// 创建消息缓存xMessageBuffer = xMessageBufferCreate(1024);if (xMessageBuffer == NULL) {Serial.println("Failed to create message buffer");while (1) {}}// 创建发送和接收任务xTaskCreate(vSenderTask, "Sender", 1024, NULL, 1, NULL);xTaskCreate(vReceiverTask, "Receiver", 1024, NULL, 1, NULL);// 启动调度器vTaskStartScheduler();
}void loop() {// 主循环应为空,因为 FreeRTOS 任务在运行
}

API

1. 创建消息缓存

要创建一个消息缓存,使用 xMessageBufferCreate 函数:

MessageBufferHandle_t xMessageBufferCreate(size_t xBufferSizeBytes);

参数

  • xBufferSizeBytes:消息缓存的大小(字节数)。

返回值

  • 成功时返回消息缓存的句柄(非 NULL);失败时返回 NULL。

示例:

MessageBufferHandle_t xMessageBuffer = xMessageBufferCreate(1024);
if (xMessageBuffer == NULL) {// 创建失败,处理错误
}

2. 发送消息到消息缓存

使用 xMessageBufferSend 将消息发送到缓存中:

size_t xMessageBufferSend(MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait);

参数

  • xMessageBuffer:消息缓存的句柄。
  • pvTxData:要发送的消息指针。
  • xDataLengthBytes:发送的消息长度(字节数)。
  • xTicksToWait:等待时间(滴答数)。

返回值

  • 成功发送的字节数。如果返回值小于 xDataLengthBytes,则表示在 xTicksToWait 时间内没有足够的空间发送所有消息。

示例:

const char *message = "Hello, FreeRTOS!";
size_t bytesSent = xMessageBufferSend(xMessageBuffer, message, strlen(message), portMAX_DELAY);
if (bytesSent < strlen(message)) {// 发送的数据不完整,处理错误
}

3. 从消息缓存接收消息

使用 xMessageBufferReceive 从缓存中接收消息:

size_t xMessageBufferReceive(MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait);

参数

  • xMessageBuffer:消息缓存的句柄。
  • pvRxData:接收消息的缓冲区指针。
  • xBufferLengthBytes:接收缓冲区的大小(字节数)这设置了可以接收的消息的最大长度。
  • xTicksToWait:等待时间(滴答数)。

返回值

  • 成功接收的字节数。如果返回值小于 xBufferLengthBytes,则表示在 xTicksToWait 时间内没有接收到足够的消息。

示例:

char buffer[50];
size_t bytesReceived = xMessageBufferReceive(xMessageBuffer, buffer, sizeof(buffer), portMAX_DELAY);
if (bytesReceived > 0) {buffer[bytesReceived] = '\0'; // 确保字符串以 NULL 结尾Serial.println(buffer);
} else {// 接收失败,处理错误
}

其他消息缓存 API

1. xMessageBufferCreateStatic

创建一个静态分配的消息缓存。

MessageBufferHandle_t xMessageBufferCreateStatic(size_t xBufferSizeBytes, uint8_t *pucMessageBufferStorageArea, StaticMessageBuffer_t *pxStaticMessageBuffer);

参数

  • xBufferSizeBytes:消息缓存的大小(字节数)。
  • pucMessageBufferStorageArea:指向预先分配的缓存存储区。
  • pxStaticMessageBuffer:指向预先分配的 StaticMessageBuffer_t 结构。

返回值

  • 成功时返回消息缓存的句柄(非 NULL);失败时返回 NULL。
2. xMessageBufferReset

重置消息缓存,使其变为空。

BaseType_t xMessageBufferReset(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

  • 如果成功重置消息缓存,则返回 pdPASS;如果在消息缓存上有任务阻塞,则返回 pdFAIL。

示例:

if (xMessageBufferReset(xMessageBuffer) == pdPASS) {// 重置成功
} else {// 重置失败,处理错误
}
3. xMessageBufferSpacesAvailable

获取消息缓存中可用的空闲空间(字节数)。

size_t xMessageBufferSpacesAvailable(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

  • 消息缓存中当前可用的空闲空间,以字节为单位。

示例:

size_t spaceAvailable = xMessageBufferSpacesAvailable(xMessageBuffer);
Serial.print("Space available: ");
Serial.println(spaceAvailable);
4. xMessageBufferNextLengthBytes

获取消息缓存中下一个消息的长度(字节数)。

size_t xMessageBufferNextLengthBytes(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

  • 下一个消息的长度,以字节为单位。

示例:

size_t nextMessageLength = xMessageBufferNextLengthBytes(xMessageBuffer);
Serial.print("Next message length: ");
Serial.println(nextMessageLength);
5. vMessageBufferDelete

删除消息缓存,释放分配的内存。

void vMessageBufferDelete(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

  • 无返回值。

示例:

vMessageBufferDelete(xMessageBuffer);

总结

FreeRTOS 消息缓存通过在发送和接收消息时记录和读取消息长度,确保了消息的完整传递。这样的设计使得发送的数据和接收的数据大小相等,从而保证了任务间通信的一致性和可靠性。

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

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

相关文章

【IC验证】一文速通多通道数据整型器(MCDF)

目录 01 README 02 MCDF设计结构 2.1 功能描述 2.2 设计结构 2.3 接口与时序 2.3.1 系统信号接口 2.3.2 通道从端接口 2.3.3 整形器接口 2.3.4 控制寄存器接口 2.3.4.1 接口时序图 2.3.4.2 各数据位信息 03 验证框图 3.1 reg_pkg 3.1.1 reg_trans 3.1.2 reg_driv…

【一刷《剑指Offer》】面试题 27:二叉搜索树与双向链表

牛客对应题目链接&#xff1a;二叉搜索树与双向链表_牛客题霸_牛客网 (nowcoder.com) 力扣对应题目链接&#xff1a;LCR 155. 将二叉搜索树转化为排序的双向链表 - 力扣&#xff08;LeetCode&#xff09; 一、《剑指 Offer》对应内容 二、分析题目 上面力扣上的这道题目和牛客…

AGM DAP-LINK 离线烧录报错信息分析

DAP-LINK 支持离线烧录。 即&#xff1a;先把要烧录的bin 烧录到DAP-LINK 中&#xff1b;然后DAP-LINK 可以脱离PC&#xff0c;上电后通过按键对目标板进行烧录。 CMSIS-DAP模式 跳线JGND断开&#xff0c;状态LED D4快闪&#xff0c;D3常亮&#xff08;串口状态&#xff09;。…

deepin开发web前端:探索、挑战与无限可能

deepin开发web前端&#xff1a;探索、挑战与无限可能 在数字化浪潮汹涌的时代&#xff0c;Web前端作为连接用户与数字世界的桥梁&#xff0c;其重要性日益凸显。而deepin作为一款优秀的开源操作系统&#xff0c;为Web前端开发者提供了广阔的舞台。本文将围绕deepin开发Web前端…

接口设计的最佳实践-下篇

大多数程序员&#xff0c;做得最多的事&#xff0c;也不过是写接口这件事而已。 今天继续总结下接口设计需要注意的点。尽量每种都给出具体的场景、案例等&#xff0c;希望大家能有所收获。 1、接口幂等 幂等性&#xff1a;是指一个操作或者一个服务&#xff0c;无论执行多少…

小程序怎样进行本地存储的读、写、删、清?

小程序进行本地存储的读、写、删、清操作&#xff0c;可以通过微信小程序提供的API来实现。这些API分为同步和异步两种类型&#xff0c;以满足不同的使用场景和需求。 同步操作 同步操作会阻塞后续的代码执行&#xff0c;直到操作完成。 写入本地缓存&#xff08;写&#xf…

Vue3 - Mac系统用文本编辑写html不显示效果的坑

平时在win系统下&#xff0c;可以直接对文本进行编辑&#xff0c;非常的舒服。 在mac系统中&#xff0c;也有类似的功能&#xff0c;就是文本编辑&#xff0c;没想到居然还有坑。 这是我mac系统中创建的html文件&#xff0c;想着没有几行代码&#xff0c;就没有开编辑器了&am…

C语言 | Leetcode C语言题解之第125题验证回文串

题目&#xff1a; 题解&#xff1a; bool isalumn(char c) {return (c > a && c < z) || (c > A && c < Z) || (c > 0 && c < 9); }bool isPalindrome(char* s) {for (int left 0, right strlen(s) - 1; left < right; left, …

【数据库系统概论】事务

概述 在数据库系统中&#xff0c;事务&#xff08;Transaction&#xff09;是指一组作为单个逻辑工作单元执行的操作。这些操作要么全部成功&#xff08;提交&#xff09;&#xff0c;要么全部失败&#xff08;回滚&#xff09;。事务的主要目的是确保数据库的完整性和一致性&…

AI与NLP的完美结合:揭秘ChatGPT

AI与NLP的完美结合&#xff1a;揭秘ChatGPT 一、AI大模型的发展历程 AI大模型的发展可追溯到早期的深度学习技术。深度学习通过多层神经网络处理复杂的数据模式&#xff0c;显著提升了图像识别、语音识别等领域的性能。随后&#xff0c;研究人员将注意力转向NLP&#xff0c;开…

【传知代码】多视图3D目标检测位置嵌入变换(论文复现)

前言&#xff1a;三维目标检测技术正逐渐成为计算机视觉领域的重要研究方向。特别是在自动驾驶、增强现实&#xff08;AR&#xff09;、虚拟现实&#xff08;VR&#xff09;以及机器人导航等应用中&#xff0c;对三维空间内目标的精准检测与定位显得尤为重要。然而&#xff0c;…

人脸解锁优化关键过程

一.人脸解锁的关键过程 1. 按下power键 2. 屏幕点亮 3. 打开前摄 4. 获取第一帧并传给算法 5. 算法完成并返回结果 6. 解锁完成并关闭相机 二. 相机优化点 1. 定制人脸解锁自己的pipeline,去掉不必要的node,理论上只需要一个preview的pipeline 2. 使用AE warm up&#xff0c;减…

SAP_SD模块-销售交货并开票后发现物料没维护价格的完整处理方法(含POD功能)

销售流程完结后&#xff0c;发现物料价格没维护时&#xff0c;如何处理 一、业务背景&#xff1a; 1、问题发现时间&#xff1a;2024年6月2日&#xff1b; 2、问题描述&#xff1a; 2024年5月份的单据业务存在交货成本和开票成本为0的单据&#x…

【JavaScript脚本宇宙】揭秘HTTP请求库:深入理解它们的特性与应用

深度揭秘&#xff1a;六大HTTP请求库的比较与应用 前言 在这篇文章中&#xff0c;我们将探讨六种主要的HTTP请求库。这些库为处理网络请求提供了不同的工具和功能&#xff0c;包括Axios、Fetch API、Request、SuperAgent、Got和Node-fetch。通过本文&#xff0c;你将对每个库…

PyCharm如何更换解析器为Anaconda,如何自己切换python环境

自己使用了Anaconda创建了一个环境&#xff1a; 如何在工具PyCharm中切换自定义的python环境呢&#xff1f; 1. 点击 设置 2. 项目&#xff1a;python - Python解析器 此时会发现&#xff0c;只有一个默认的版本。 3. 点击 添加解析器 - 添加本地解析器 4. 选择 conda 环境…

AI智能语音机器人系统如何对接科大讯飞接口

关于AI语音机器人的介绍有很多&#xff0c;但是由于商业化&#xff0c;没有一个能真正说明白的&#xff0c;当然&#xff0c;我们搭建的AI智能机器人系统也是商业化的&#xff0c;毕竟业务是做这方面的&#xff0c;但是价格绝对是公道的&#xff0c;废话不多说了&#xff0c;我…

探索API接口:技术深度解析与应用实践

在当今的软件开发和数据交换领域&#xff0c;API&#xff08;应用程序编程接口&#xff09;已经成为了一个不可或缺的工具。它允许不同的软件应用程序或组件之间进行交互和通信&#xff0c;从而实现了数据的共享和功能的扩展。本文将深入探讨API接口的技术原理、设计原则以及在…

Qt各发布版本介绍与选择

一.Qt各个主要版本介绍 1.Qt4 Qt4的第一个版本是Qt 4.0&#xff0c;发布于2005年6月1日。 Qt 4的最后一个版本是Qt 4.8.7&#xff0c;发布时间是2015年6月10日。 2.Qt5 &#xff08;1&#xff09;Qt5的第一个版本是Qt 5.0&#xff0c;发布于2012年12月19日。 &#xff08;2&…

ubuntu安装notion

一、背景&#xff1a; 不用windwos系统&#xff0c;完全可以&#xff0c;然后基本软件都有&#xff0c;怎么安装notion呢 二、步骤 1. 更新源 echo "deb [trustedyes] https://apt.fury.io/notion-repackaged/ /" | sudo tee /etc/apt/sources.list.d/notion-repa…

基于字典树可视化 COCA20000 词汇

COCA20000 是美国当代语料库中最常见的 20000 个词汇&#xff0c;不过实际上有一些重复&#xff0c;去重之后大概是 17600 个&#xff0c;这些单词是很有用&#xff0c;如果能掌握这些单词&#xff0c;相信会对英语的能力有一个较大的提升。我很早就下载了这些单词&#xff0c;…