Потоковый буфер 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
. Сделано это для защиты от невнимательности и от доступа к неинициализированному буферу, что может закончиться весьма долгой отладкой, особенно при большом количестве кода, файлов и всего остального.
Надеюсь помог. Приятного кодинга 😀