Потоковый буфер FreeRTOS. Stream Buffer.

В предыдущей заметке затронул тему очередей и их использование для передачи информации из одной задачи (или прерывания) в другую. Здесь будет рассмотрен похожий, но немного другой функционал - потоковые буферы.

По сути данная статья будет являть некоторой адаптацией официального мануала расположенного здесь (RTOS Stream Buffers )

Вот что пишут о них:

Потоковые буферы позволяют передавать поток байтов из подпрограммы обработки прерываний в задачу или из одной задачи в другую. Поток байтов может иметь произвольную длину и не обязательно иметь начало или конец. Любое количество байтов может быть записано за один раз, и любое количество байтов может быть прочитано за один раз. Данные передаются путем копирования - данные копируются в буфер отправителем и из буфера считываются.

В отличие от большинства других коммуникационных примитивов FreeRTOS, потоковые буферы оптимизированы для сценариев с одним устройством записи для одного читателя, таких как передача данных из подпрограммы обработки прерываний в задачу или из одного ядра микроконтроллера в другое на двухъядерном ЦП.

Для работы с потоковыми буферами необходимо.

Подключить заголовочный файл:

#include "stream_buffer.h"              // ARM.FreeRTOS::RTOS:Stream Buffer

Объявить переменную-потоковый буфер:

static StreamBufferHandle_t stream_buffer_ex   = NULL;

Сразу определяем его как NULL - это нам в последствии поможет.

Теперь объявляем функцию для создания буфера, можно сделать это и просто строчкой в какой-то общей функции, например из которой передаются данные, но далее будет понятно зачем мы её создаем. Здесь BUFF_SIZE - это размер буфера, 24 - порог разблокировки задачи которая использует буфер, если в буфере будет 24 и более байт данных, задача перейдет из заблокированного состояния - продолжит работу.

#define BUFF_SIZE       (64 * 5)

static __inline void EX_CreateBuffer( void )   
{
    if (stream_buffer_ex == NULL) stream_buffer_ex = xStreamBufferCreate( BUFF_SIZE, 24); 
}

Для записи данных в буфер используется функция xStreamBufferSend:

EX_CreateBuffer();
xStreamBufferSend (stream_buffer_ex, (void *) data,   sizeof (data),     0);

Считывание выполняем в другой задаче операционной систиемы с помощью функции xStreamBufferReceive следующим образом:

static uint8_t buff[ BUFF_SIZE ];

// ...

EX_CreateBuffer();
uint32_t length  = xStreamBufferReceive (stream_buffer_ex, (void *) buff, sizeof (buff), portMAX_DELAY);
if ( length > 0 )
{
    ///< ЗДЕСЬ ВЫПОЛНЯЕМ ДЕЙСТВИЯ С ДАННЫМИ В БУФЕРЕ buff
}

Можно заметить, что и при записи и считывании используется функция EX_CreateBuffer. Сделано это для защиты от невнимательности и от доступа к неинициализированному буферу, что может закончиться весьма долгой отладкой, особенно при большом количестве кода, файлов и всего остального.

Надеюсь помог. Приятного кодинга 😀