14.FreeRTOS 消息缓存 Message Buffer

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

介绍


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

什么是消息缓存?

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

消息缓存的工作原理

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

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

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

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

c 复制代码
#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 函数:

c 复制代码
MessageBufferHandle_t xMessageBufferCreate(size_t xBufferSizeBytes);

参数

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

返回值

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

示例:

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

2. 发送消息到消息缓存

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

c 复制代码
size_t xMessageBufferSend(MessageBufferHandle_t xMessageBuffer, const void *pvTxData, size_t xDataLengthBytes, TickType_t xTicksToWait);

参数

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

返回值

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

示例:

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

3. 从消息缓存接收消息

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

c 复制代码
size_t xMessageBufferReceive(MessageBufferHandle_t xMessageBuffer, void *pvRxData, size_t xBufferLengthBytes, TickType_t xTicksToWait);

参数

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

返回值

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

示例:

c 复制代码
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

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

c 复制代码
MessageBufferHandle_t xMessageBufferCreateStatic(size_t xBufferSizeBytes, uint8_t *pucMessageBufferStorageArea, StaticMessageBuffer_t *pxStaticMessageBuffer);

参数

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

返回值

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

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

c 复制代码
BaseType_t xMessageBufferReset(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

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

示例:

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

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

c 复制代码
size_t xMessageBufferSpacesAvailable(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

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

示例:

c 复制代码
size_t spaceAvailable = xMessageBufferSpacesAvailable(xMessageBuffer);
Serial.print("Space available: ");
Serial.println(spaceAvailable);
4. xMessageBufferNextLengthBytes

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

c 复制代码
size_t xMessageBufferNextLengthBytes(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

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

示例:

c 复制代码
size_t nextMessageLength = xMessageBufferNextLengthBytes(xMessageBuffer);
Serial.print("Next message length: ");
Serial.println(nextMessageLength);
5. vMessageBufferDelete

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

c 复制代码
void vMessageBufferDelete(MessageBufferHandle_t xMessageBuffer);

参数

  • xMessageBuffer:消息缓存的句柄。

返回值

  • 无返回值。

示例:

c 复制代码
vMessageBufferDelete(xMessageBuffer);

总结

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

相关推荐
Code out the future7 分钟前
【C++——临时对象,const T&】
开发语言·c++
小猪写代码7 分钟前
STM32 水质水位检测项目 (调试模块)和(延时模块)
stm32·单片机·嵌入式硬件
sam-zy27 分钟前
MFC用List Control 和Picture控件实现界面切换效果
c++·mfc
御风_2138 分钟前
STM32单片机使用CAN协议进行通信
stm32·单片机·嵌入式硬件
aaasssdddd961 小时前
C++的封装(十四):《设计模式》这本书
数据结构·c++·设计模式
发呆小天才O.oᯅ1 小时前
YOLOv8目标检测——详细记录使用OpenCV的DNN模块进行推理部署C++实现
c++·图像处理·人工智能·opencv·yolo·目标检测·dnn
qincjun2 小时前
文件I/O操作:C++
开发语言·c++
逝灮2 小时前
【蓝桥杯——物联网设计与开发】拓展模块3 - 温度传感器模块
驱动开发·stm32·单片机·嵌入式硬件·物联网·蓝桥杯·温度传感器
星语心愿.2 小时前
D4——贪心练习
c++·算法·贪心算法
汉克老师2 小时前
2023年厦门市第30届小学生C++信息学竞赛复赛上机操作题(三、2023C. 太空旅行(travel))
开发语言·c++