You are here

Подробнее о буферах сообщений

Source: https://freertos.org/RTOS-message-buffer-example.html

Перевод может содержать ошибки. Читайте первоисточник.


[Буферы потоков и сообщений]

RTOS Message Buffers - Подробнее о буферах сообщений

Оглавление страницы

  1. Введение
  2. Первые шаги
  3. Определение размера буфера сообщений
  4. Блокирующее чтение и запись
  5. Макросы завершения отправки и завершения приёма (for multicore use)

Введение

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

Данные передаются буфером сообщений через копирование - данные копируются в буфер отправителем и забираются из буфера при чтении.

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

Функционал буфера сообщений подключается добавкой к проекту исходного файла FreeRTOS/source/stream_buffer.c.

Реализация буфера сообщений использует уведомления. Следовательно, вызов функций API для работы с буфером сообщений, которые переводят вызывающую задачу в заблокированное состояние, может изменять состояние уведомления и значение в поле уведомления.

ВАЖНОЕ ЗАМЕЧАНИЕ: Уникальность среди объектов FreeRTOS заключается в том, что буфер потока (а также буфер сообщений, т.к. он работает поверх буфера потока) предполагает, что есть только одна задача, которая пишет в буфер потока, и только одна задача, которая читает из буфера потока. Расположение "писателя" и "читателя" в разных задачах или обработчиках прерывания безопасно, но в отличие от большинства других объектов FreeRTOS небезопасно иметь несколько "писателей" либо несколько "читателей". Если всё же в приложении имеется несколько различных "писателей", каждый вызов функций API для записи в буфер (таких как xStreamBufferSend()) необходимо оборачивать в критическую секцию и использовать параметр send block time = 0. Аналогично если имеется несколько "читателей", то каждый вызов функций API для чтения из буфера (таких как xStreamBufferReceive()) необходимо оборачивать в критическую секцию и использовать параметр receive block time = 0.

Первые шаги

Исходный файл FreeRTOS/Demo/Common/Minimal/MessageBufferAMP.c содержит хорошо комментированный пример использования буфера сообщений для передачи данных различной длины от одного микропроцессорного ядра другому в многоядерном микроконтроллере. Это усложнённый пример, но механизмы создания буфера сообщений, отправки данных и их получения аналогичны более простым одноядерным сценариям, но в отличие от этого примера, для одноядерных сценариев нет необходимости переопределять макрос sbSEND_COMPLETE().

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

Определение размера буфера сообщений

Чтобы позволить буферам управлять сообщениями с различной длиной, перед телом сообщения в буфер записывается его длина (это выполняется внутри функций API). Длина сохраняется в виде переменной типа size_t, которая имеет размер 4 байта для 32-битной архитектуры микроконтроллерного ядра. Следовательно, например, запись 10-байтного сообщения в буфер сообщений будет фактически использовать 14 байт в буфере. Аналогично сообщение размером 100 байт в буфере фактически займёт 104 байта.

Блокирующее чтение и запись

xMessageBufferReceive() используется  для чтения данных из буфера сообщений из задачи RTOS. xMessageBufferReceiveFromISR() используется для чтения данных из буфера сообщений из обработчика прерываний. xMessageBufferSend() используется для отправки данных в буфер сообщений из задачи RTOS. xMessageBufferSendFromISR() используется для отправки данных в буфер сообщений из обработчика прерываний.

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

Если задача использует вызов xMessageBufferSend()  с не нулевым временем ожидания для записи в буфер сообщений, который оказывается заполненным на момент вызова, то задача переходит в заблокированное состояние до тех пор, пока в буфере не появится свободное место, либо пока не истечёт указанное время ожидания.

Макросы завершения отправки и завершения приёма

Поскольку буферы соощений реализованы на базе буферов потока, макросы sbSEND_COMPLETE() и sbRECEIVE_COMPLETE() для буферов сообщений имеют то же смысл, что и для буферов потока.

Hobby's category: