流数据缓冲区(Stream Buffer)

流数据缓冲区(Stream Buffer)

流数据 最典型的流数据就是音频数据。 Stream Buffer API 函数官方文档 Stream Buffer API [[FreeRTOS_Reference_Manual_V10.0.0.pdf#page=348&selection=4,0,4,17|FreeRTOS_Reference_M

流数据

最典型的流数据就是音频数据。

Stream Buffer API 函数官方文档

Stream Buffer API

[[FreeRTOS_Reference_Manual_V10.0.0.pdf#page=348&selection=4,0,4,17|FreeRTOS_Reference_Manual_V10.0.0, page 348]]


xStreamBufferCreate()

#include "FreeRTOS.h"
#include "stream_buffer.h"

StreamBufferHandle_t xStreamBufferCreate( size_t xBufferSizeBytes, size_t xTriggerLevelBytes );

函数说明:

  • 用灵活可变的空间来创建一个流数据句柄

参数:

  • xBufferSizeBytes:流数据的尺寸大小。
  • xTriggerLevelBytes:当任务在阻塞状态时,要发送xTriggerLevelBytes定义的的数据量,才会对任务解除阻塞。

返回值:

  • NULL:流数据句柄因为堆内存不足而无法创建。
  • 返回句柄。

xStreamBufferSend()

#include "FreeRTOS.h"
#include "stream_buffer.h"

size_t xStreamBufferSend( StreamBufferHandle_t xStreamBuffer,
						  const void *pvTxData,
						  size_t xDataLengthBytes,
						  TickType_t xTicksToWait );

函数说明:

  • 向流数据句柄发送数据。所有数据都被复制到目标句柄内。

参数:

  • xStreamBuffer:发送数据的句柄。
  • pvTxData:存储要发送的数据指针。
  • xDataLengthBytes:发送数据的长度。
  • xTicksToWait:阻塞时间。

返回值:

  • 发送数据的总量。

注意:

  • FreeRTOS 设计的流数据方案一般仅支持存在 一个发送方 和 一个接收方。如果存在多个 发送/接收 方,会导致数据传输不安全。
  • 若要由多个任务需要同时进行 数据收发 操作,请确保其 API 函数在关键区域(临界区)内,并设置其超时等待时长为 0。
  1. 多个发送方:
taskENTER_CRITICAL();
xStreamBufferSend( buffer, data, length, 0 );
taskEXIT_CRITICAL();
  1. 多个接收方:
taskENTER_CRITICAL();
xStreamBufferReceive(buffer, data, length, 0);
taskEXIT_CRITICAL();

示例代码

#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/stream_buffer.h"

static StreamBufferHandle_t stream_buffer; // 创建流数据句柄

void task_send(void *pvPara)
{
    printf("[TASK SEND]: Send action.\n");

    char tx_buffer[50];
    int count = 0;
    size_t buffer_len = 0;
    size_t sent_byte = 0;

    while (true) {
        buffer_len = sprintf(tx_buffer, "Hello, World! %d.", count);
        count++;

		// 发送数据,返回发送的数据量
        sent_byte = xStreamBufferSend(stream_buffer, (void *)tx_buffer, buffer_len, portMAX_DELAY);
        printf("[TASK SEND]: sent_byte = %d, buffer_len = %d\n", sent_byte, buffer_len);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void task_receive(void *pvPara)
{
    printf("[TASK RECEIVE]: Receive action.\n");

    char rx_buffer[50];
    size_t receive_byte = 0;
    memset(rx_buffer, 0, 50);

    while (true) {
		// 接收数据,获取接收到的数据量
        receive_byte = xStreamBufferReceive(stream_buffer, (void *)rx_buffer, 50, portMAX_DELAY);
        printf("[TASK RECEIVE]: received buffer = %s, received length = %d\n", rx_buffer, receive_byte);

        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

void app_main(void)
{
    stream_buffer = xStreamBufferCreate(1000, 10); // 流数据大小 1000,解除阻塞数据量 10 
    xTaskCreate(task_send, "Task Send", 2048 * 2, NULL, 1, NULL);
    xTaskCreate(task_receive, "Task Receive", 2048 * 2, NULL, 1, NULL);
}
Comment