You are here

Очереди во FreeRTOS

Source: https://www.freertos.org/Embedded-RTOS-Queues.html

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


[Межзадачное взаимодействие и синхронизация]

[See also Blocking on Multiple RTOS Objects]

Очереди это основная форма межзадачного взаимодействия. Они могут использоваться для пересылки сообщений между задачами, либо между обработчиками прерываний и задачами. В большинстве случаев они используются как потокобезопасный буфер FIFO (First In First Out) с отправкой новых данных в конец очереди, хотя есть возможность отправлять данные и в начало очереди.


Запись в очередь, и чтение из очереди. В этом примере очередь была создана с длиной 5 сообщений, и она никогда не заполняется.

 

Пользовательская модель: максимальная простота, максимальная гибкость...

В модели управления, используемой во FreeRTOS удаётся совместить простоту с гибкостью - свойства, обычно являющиеся взаимоисключающими. Сообщения отправляются через очередь копированием. Это означает, что сами данные копируются в очередь, а не указатель на данные (хотя данные могут таки являться указателем на более объёмные буферы). Это лучший подход, потому что:

  • Сообщения небольшого размера, которые содержатся в переменных языка C (целые, небольшие структуры и т.п.) могут быть переданч через очередь напрямую. При этом нет необходимости выделять буфер для размещения сообщения и копировать в него переменную. Аналогично при чтении сообщения из очереди сообщение напрямую копируется в переменную языка C.
    Далее. Отправка в очередь таким способом позволяет задаче-отправителю сразу же перезаписывать значение переменной или буфера, который был отправлен в очередь, даже когда отправленное сообщение остаётся в очереди. Поскольку данные были скопированы в очередь, сама переменная доступна для дальнейшего использования задачей-отправителем. Нет никаких требований к задаче-отправителю и к задаче-получателю: не важно, какая задача владеет сообщением, и какая задача отвечает за освобождение памяти после того, как сообщение извлечено из очереди.
  • Использование очередей для передачи данных через копирование не препятствует тому, чтобы использовать передачу данных по ссылке. Когда размер пересылаемых сообщений достигает некоторого значения, после которого не оправдано помещение в очередь всего тела сообщения, можно создать очередь, в которой элементы будут указателями на тело сообщения. И тогда в очередь будут копироваться только указатели. Именно так реализация связки FreeRTOS+UDP передаёт большие сетевые буферы  вокруг стека IP FreeRTOS.
  • Ядро выполняет все функции по выделению памяти, используемой в качестве области хранения очереди.
  • Сообщения произвольной длины могут быть переданы, если создать очередь, которая содержит элементы в виде структуры, в которой есть поле-указатель на тело сообщения и поле длины этого сообщения.
  • Одна и та же очередь может быть использована для пересылки разных типов сообщений и сообщений из разных мест. Для этого создаётся очередь, содержащая элементы-структуры, в которых есть поле типа сообщения и другое поле, в котором содержатся данные. При этом поле данных может либо содержать сами данные, либо указатель на данные. То, как данные будут интерпретироваться, определяется значением в поле типа сообщения. Именно так в связке FreeRTOS+UDP IP стека реализована одна очередь для приёма уведомлений от событий таймера ARP, приёма пакетов, принимаемых аппаратным модулем Ethernet, приёма пакетов от приложения, приёма событий network down, и т.д..
  • Реализация естественным образом подходит для использования при работе в защищённом режиме памяти. Задача, которая работает в защищённой области памяти, может передать данные задаче, которой отведена другая защищённая область памяти, потому что активация ядра RTOS путём вызова функций API работы с очередями будет повышать уровень привилегий микроконтроллера. К области хранения данных очереди доступ получает только ядро RTOS (с полными привилегиями).
  • Отдельные функции API используются при вызове из обработчиков прерываний. Разделение функций API на вызываемые из задачи и вызываемые из обработчиков прерываний позволяет избежать проверки контекста при каждом вызове. Использование отдельных функций API для работы из обрабочиков прерываний также делает использование очередей более простым по сравнению с некоторыми другими RTOS.
  • Во всех отношениях API проще.

Дополнительная информация об очередях, бинарных семафорах, мьютексах, счётных семафорах и рекурсивных семафорах, а также простые и хорошо проработанные примеры использования предоставлены в учебнике по FreeRTOS.

Блокировка на очереди

Функции API работы с очередями позволяют указать время блокировки.

Когда задача выполняет попытку прочитать из пустой очереди, она будет переведена в заблокированное состояние (т.е. не будет использовать процессорное время и другие задачи смогут в это время выполняться) до тех пор, пока данные не появятся в очереди, либо не закончится время ожидания.

Когда задача выполняет попытку записи в заполненную очередь, эта задача переводится в заблокированное состояние (т.е. не использует процессорное время, и другие задачи могут быть запущены) до тех пор пока не появится свободное место в очереди или пока не истечёт время ожидания.

Если больше чем одна задача находятся в состоянии блокировки на одной и той же очереди, то задача с наивысшим приоритетом будет задачей, которая разблокируется первой.

Примеры использования

Функции API работы с очередями описаны в разделе управление очередями. А в каталоге FreeRTOS/Demo/Common/Minimal можно найти много примеров их использования.

Не забывайте, что в обработчиках прерывания нельзя использовать функции API, которые не имеют суффикса "FromISR".

Hobby's category: