流数据
最典型的流数据就是音频数据。
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。
- 多个发送方:
taskENTER_CRITICAL();
xStreamBufferSend( buffer, data, length, 0 );
taskEXIT_CRITICAL();
- 多个接收方:
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);
}