• 14.FreeRTOS 消息缓存 Message Buffer


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

    介绍


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

    什么是消息缓存?

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

    消息缓存的工作原理

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

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

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

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

    #include 
    #include 
    #include 
    
    // 消息缓存句柄
    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 消息缓存通过在发送和接收消息时记录和读取消息长度,确保了消息的完整传递。这样的设计使得发送的数据和接收的数据大小相等,从而保证了任务间通信的一致性和可靠性。

  • 相关阅读:
    选择护眼台灯的标准,教大家如何挑选护眼灯
    PDF格式转换为翻页电子书,这种形式太酷辣!
    数据库中的范式:第一范式,第二范式,第三范式
    专家呼吁:家长应承担起数字时代家庭教育新责任
    GBASE 8s 如何并行执行update statistics
    一款强大的红队信息收集和资产收集工具(Kscan)
    【SLAM】LVI-SAM解析——综述
    基于yolov5+deepsort的智能售货机商品目标检测种类识别计数
    C语言--输出1-100以内同时能被3和5整除的数
    Multitor:一款带有负载均衡功能的多Tor实例创建工具
  • 原文地址:https://blog.csdn.net/m0_60134435/article/details/139398570