Компоненты и технологии • №2 '2011 компоненты



Pdf көрінісі
бет52/129
Дата28.09.2023
өлшемі4.1 Mb.
#478975
1   ...   48   49   50   51   52   53   54   55   ...   129
Kurniz

portMAX_DELAY), то возврат значения 
errQUEUE_FULL говорит о том, что 
тайм-аут завершен и никакая другая за-
дача или прерывание не записали эле-
мент в очередь.
Как и в случае с записью элемента 
в очередь, API-функции xQueueReceive() 
и xQueuePeek() нельзя вызывать из тела об-
работчика прерывания. Для этих целей слу-
жит API-функция xQueueReceiveFromISR()
которая будет описана в следующих публи-
кациях.
Состояние очереди
Получить текущее количество записанных 
элементов в очереди можно с помощью API-
функции uxQueueMessagesWaiting():
unsigned portBASE_TYPE uxQueueMessagesWaiting(xQueueHan
dle xQueue);
Назначение параметров и возвращаемое 
значение:
xQueue
• 
— дескриптор очереди, состояние 
которой необходимо получить. Дескриптор 
очереди может быть получен при ее созда-
нии API-функцией xQueueCreate().
Возвращаемое значение — количество эле-
• 
ментов, которые хранит очередь в момент 
вызова uxQueueMessagesWaiting(). Если 
очередь пуста, то возвращаемым значени-
ем будет «0».
Как и в случаях с чтением и запи-
сью элемента в очередь, API-функцию 
uxQueueMessagesWaiting() нельзя вызывать 
из тела обработчика прерывания. Для этих 
целей служит API-функция uxQueueMessage
sWaitingFromISR().
Удаление очереди
Если в программе использована схема рас-
пределения памяти, допускающая удаление 
задач [1, КиТ № 5], то полезной окажется 
возможность удалить и очередь, которая ис-
пользовалась для взаимодействия с удален-
ной задачей. Для удаления очереди служит 
API-функция vQueueDelete(). Ее прототип:
void vQueueDelete(xQueueHandle xQueue);
Единственный аргумент — это дескриптор 
удаляемой очереди. При успешном заверше-
нии API-функция vQueueDelete() освободит 
всю память, выделенную как для размеще-
ния служебной структуры управления очере-
дью, так и для размещения самих элементов 
очереди.
Рассмотреть процесс обмена сообщениями 
между несколькими задачами можно на при-
мере учебной программы № 2, в которой реа-
лизована очередь для хранения элементов 
типа long. Данные в очередь записывают две 
задачи-передатчика, а считывает данные одна 
задача-приемник.
#include
#include
#include
#include “FreeRTOS.h”
#include “task.h”
#include “queue.h”
/* Объявить переменную-дескриптор очереди. 
* Эта переменная будет использоваться
* для работы с очередью из тела всех трех задач. */
xQueueHandle xQueue;
/*------------------------------------------------------------------------*/
/* Функция, реализующая задачи-передатчики */
void vSenderTask(void *pvParameters) {
/* Переменная, которая будет хранить значение, передаваемое 
* в очередь */
long 
lValueToSend;
/* Переменная, которая будет хранить результат выполнения 
* xQueueSendToBack() */
portBASE_TYPE 
xStatus;
/* Будет создано несколько экземпляров задачи. В качестве 
* параметра задачи выступает число, которое задача будет 
* записывать в очередь */
lValueToSend = (long) pvParameters;
/* Бесконечный цикл */
for (;;) {
/* Записать число в конец очереди.
* 1-й параметр — дескриптор очереди, в которую будет 
* производиться запись, очередь создана до запуска 
* планировщика, и ее дескриптор сохранен в глобальной \
* переменной xQueue.
* 2-й параметр — указатель на переменную, которая будет 
* записана в очередь, в данном случае — lValueToSend.
* 3-й параметр — продолжительность тайм-аута. 
* В данном случае задана равной 0, что соответствует
* отсутствию времени ожидания, если очередь полна. 
* Однако из-за того, что задача-приемник сообщений имеет 
* более высокий приоритет, чем задачи-передатчики, 
* в очереди не может находиться более одного элемента.
* Таким образом, запись нового элемента будет всегда 
* возможна. */
xStatus = xQueueSendToBack(xQueue, &lValueToSend, 0);
if (xStatus != pdPASS) {
/* Если попытка записи не была успешной —
* индицировать ошибку. */
puts(“Could not send to the queue.\r\n”);
}
/* Сделать принудительный вызов планировщика, позволив, 
* таким образом, выполняться другой задаче-передатчику.
* Переключение на другую задачу произойдет быстрее, 
* чем окончится текущий квант времени. */
taskYIELD();
}
}
/*------------------------------------------------------------------------*/
/* Функция, реализующая задачу-приемник */
void vReceiverTask(void *pvParameters) {
/* Переменная, которая будет хранить значение, полученное 
* из очереди */
long 
lReceivedValue;
/* Переменная, которая будет хранить результат выполнения 
* xQueueReceive() */
portBASE_TYPE 
xStatus;
/* Бесконечный цикл */
for (;;) {
/* Индицировать состояние, когда очередь пуста */
if (uxQueueMessagesWaiting(xQueue) != 0) {
puts(“Queue should have been empty!\r\n”);
}
/* Прочитать число из начала очереди.
* 1-й параметр — дескриптор очереди, из которой будет 
* происходить чтение, очередь создана до запуска 
* планировщика, и ее дескриптор сохранен в глобальной 

переменной 
xQueue.
* 2-й параметр — указатель на буфер, в который будет 
* помещено число из очереди.
* В данном случае — указатель на переменную lReceivedValue.
* 3-й параметр — продолжительность тайм-аута, в течение 

которого 
задача 
будет находиться в блокированном 
* состоянии, пока очередь пуста. В данном случае 
* макроопределение portTICK_RATE_MS используется 
* для преобразования времени 100 мс в количество

системных 
квантов.
*/
xStatus = xQueueReceive(xQueue, &lReceivedValue, 100 / 
portTICK_RATE_MS);
if (xStatus == pdPASS) {
/* Число успешно принято, вывести его на экран */
printf(“Received 

%ld\r\n”, 
lReceivedValue);




Достарыңызбен бөлісу:
1   ...   48   49   50   51   52   53   54   55   ...   129




©dereksiz.org 2024
әкімшілігінің қараңыз

    Басты бет