Блокировка при записи в очередь




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

До тех пор, пока какая-либо другая задача не прочитает данные из очереди, задача, которая пишет в очередь, будет «ожидать», находясь в блокированном состоянии.

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


Работа с очередями

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

Создание очереди

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

xQueueCreate() служит для создания очереди, она возвращает переменную типа

xQueueHandle в случае успешного создания очереди:

1. xQueueHandle xQueueCreate(unsigned portBASE_TYPE uxQueueLength,

2. unsigned portBASE_TYPE uxItemSize);

 

Ее параметры и возвращаемое значение:

· uxQueueLength — определяет размер очереди, то есть максимальное количество элементов, которые может хранить очередь.

· uxItemSize — задает размер одного элемента очереди в байтах, его легко получить с помощью оператора sizeof().

· Возвращаемое значение — дескриптор очереди. Равен NULL, если очередь не создана по причине отсутствия достаточного объема памяти в куче FreeRTOS. Ненулевое значение свидетельствует об успешном создании очереди, в этом случае оно должно быть сохранено в переменной типа xQueueHandle для дальнейшего обращения к очереди.

Запись элемента в очередь

Для записи элемента в конец очереди используется API - функция xQueueSendToBack(), для записи элемента в начало очереди — xQueueSendToFront().

Так как запись в конец очереди применяется гораздо чаще, чем в начало, то вызов API-функции xQueueSend() эквивалентен вызову xQueueSendToBack(). Прототипы у всех трех API-функций одинаковы:

1. portBASE_TYPE xQueueSendXXXX (xQueueHandle xQueue,

2. const void * pvItemToQueue,

3. portTickType xTicksToWait);

Назначение параметров и возвращаемое значение:

· xQueue — дескриптор очереди, в которую будет записан элемент. Дескриптор очереди может быть получен при ее создании API-функцией xQueueCreate().

· pvItemToQueue — указатель на элемент, который будет записан в очередь. Размер элемента зафиксирован при создании очереди, так что для побайтового копирования элемента достаточно иметь указатель на него.

· xTicksToWait — максимальное количество квантов времени, в течение которого задача может пребывать в блокированном состоянии, если очередь полна и записать новый элемент невозможно. Установка xTicksToWait равным константе portMAX_DELAY приведет к тому, что выхода из блокированного состояния по истечении тайм-аута не будет. Задача будет сколь угодно долго «ожидать» возможности записать элемент в очередь, пока такая возможность не появится. При этом макроопределение INCLUDE_vTaskSuspend в файле FreeRTOSConfig.h должно быть равно «1».

 

· Возвращаемое значение — может возвращать 2 значения:

o pdPASS — означает, что данные успешно записаны в очередь. Если определена продолжительность тайм-аута (параметр xTicksToWait не равен «0»), то возврат значения pdPASS говорит о том, что свободное место в очереди появилось до истечения тайм-аута и элемент был помещен в очередь.

o errQUEUE_FULL — означает, что данные не записаны в очередь, так как очередь заполнена. Если определена продолжительность тайм-аута (параметр xTicksToWait не равен «0» или portMAX_DELAY), то возврат значения errQUEUE_FULL говорит о том, что тайм-аут завершен и свободное место в очереди так и не появилось.

Следует отметить, что API-функции xQueueSendToBack() и xQueueSendToFront() нельзя вызывать из тела обработчика прерывания. Для этой цели служат специальные версии этих функций: xQueueSendToBackFromISR() и xQueueSendToFrontFromISR() соответственно.



Поделиться:




Поиск по сайту

©2015-2024 poisk-ru.ru
Все права принадлежать их авторам. Данный сайт не претендует на авторства, а предоставляет бесплатное использование.
Дата создания страницы: 2020-05-09 Нарушение авторских прав и Нарушение персональных данных


Поиск по сайту: