消息缓冲区(Message Buffer)

消息缓冲区(Message Buffer)

Message Buffer 和 Stream Buffer 的不同点 Message buffer 一次只能传输一个一条完整的 Message。 官方函数文档 Message Buffer API [[FreeRTOS_Reference_Manual_V10.0.0.pdf#page=372&s

Message Buffer 和 Stream Buffer 的不同点

  • Message buffer 一次只能传输一个一条完整的 Message。

官方函数文档

Message Buffer API

[[FreeRTOS_Reference_Manual_V10.0.0.pdf#page=372&selection=4,0,4,18|FreeRTOS_Reference_Manual_V10.0.0, page 372]]


xMessageBufferCreate()

#include "FreeRTOS.h"
#include "message_buffer.h"

MessageBufferHandle_t xMessageBufferCreate( size_t xBufferSizeBytes );

函数说明:

  • 创建一个消息缓冲区传输句柄。

参数:

  • xBufferSizeBytes:消息缓冲区中可以同时存储的总字节数,而不是可以存储的消息数量。洗哦啊西缓冲区的容量是以字节为单位的,即在任何时候消息缓冲区能够保存的最大字节数。

注意:

  • 消息缓冲区的内容,会额外包含一个字节的数据,用来存储消息的长度。

xMessageBufferSend()

#include "FreeRTOS.h"
#include "message_buffer.h"

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

函数说明:

  • 向消息缓冲区发送数据。

参数:

  • xMessageBuffer:消息缓冲区句柄。
  • pvData:存放消息内容的指针。
  • xDataLengthBytes:消息内容长度,单位字节。
  • xTicksToWait:超时等待时长。

返回值:

  • 如果消息发送成功,则返回消息的长度。
  • 如果消息发送因为超时而失败,则返回 0。

xMessageBufferReceive()

#include "FreeRTOS.h"
#include "message_buffer.h"

size_t xMessageBufferReceive( MessageBufferHandle_t xMessageBuffer,
						     const void *pvData,
						     size_t xDataLengthBytes,
						     TickType_t xTicksToWait );

函数说明:

  • 从消息缓冲区接收消息。

参数:

  • xMessageBuffer:消息缓冲区句柄。
  • pvData:存放消息内容的指针。
  • xDataLengthBytes:消息内容长度,单位字节。
  • xTicksToWait:超时等待时长。

返回值:

  • 如果消息接收成功,则返回消息的长度。
  • 如果消息接收因为超时而失败,则返回 0。
  • 如果因为存储消息的指针小于消息的长度,也返回 0。

注意:

  • 接收消息时,如果存储消息内容的指针容量消息消息的大小,则不会接收该消息

示例代码

#include <stdio.h>
#include <string.h>
#include <inttypes.h>
#include "sdkconfig.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_flash.h"
#include "esp_system.h"
#include "freertos/event_groups.h"
#include "freertos/message_buffer.h"

// 创建消息句柄
static MessageBufferHandle_t message_handle;

void task_send(void *pvPara)
{
    char *tx_message = (char *)malloc(100); // 存储消息的指针,虽然分配了100字节的容量,但是实际发送长度是根据实际消息长度来决定的
    memset(tx_message, 0, 100);

    size_t message_len = 0;
    size_t message_sent_len = 0;

    for (int i = 0; i < 3; i++) {
	    // 将消息内容存储到指针中
        message_len = sprintf(tx_message, "Hello, it's message NO.%d.", i);

		// 发送消息,并获取发送的消息长度
        message_sent_len = xMessageBufferSend(message_handle, tx_message, message_len, portMAX_DELAY);
        // 获取消息句柄剩余可用空间
        printf("[TASK SEND]: Available spaces = %d.\n", xMessageBufferSpacesAvailable(message_handle));
        printf("[TASK SEND]: message_len = %d, message_sent_len = %d, message: %s\n", message_len, message_sent_len, tx_message);
    }

    vTaskDelete(NULL);
}

void task_receive(void *pvPara)
{
    vTaskDelay(pdMS_TO_TICKS(1000));

    char *rx_message = (char *)malloc(100);
    memset(rx_message, 0, 100);

    size_t message_received_len = 0;

    while (true) {
		// 阻塞 5s ,等待发送任务完成
        vTaskDelay(pdMS_TO_TICKS(5000));

		// 接收并存储消息到指针,同时获取接收到的消息长度
        message_received_len = xMessageBufferReceive(message_handle, rx_message, 100, portMAX_DELAY);
        printf("[TASK RECEIVE]: Available spaces = %d.\n", xMessageBufferSpacesAvailable(message_handle));
        printf("[TASK RECEIVE]: message_received_len = %d, message: %s\n", message_received_len, rx_message);
    }
}

void app_main(void)
{
	// 创建消息缓冲区,大小为 30 字节
    message_handle = xMessageBufferCreate(30);

    xTaskCreate(task_send, "Task Send", 2048, NULL, 1, NULL);
    xTaskCreate(task_receive, "Task Receive", 2048, NULL, 1, NULL);
}

示例输出

![[MessageBuffer.gif]]

Task Send 先开始发送消息,等待 Task Receive 接收,因为 Task Receive 要 5s 的时间才能接收一个消息,所以阻塞了 Task Send,即便如此,Message Buffer 也只是在每次发送一个消息。
另外,消息长度是 25,但是显示剩余可用空间为 1,因为消息缓冲区句柄中的消息长度定义,占据了 4 个字节的内存。

Comment