You are here

FreeRTOS ИПП: xQueueCreateSet()

Перевод может содержать ошибки. Читайте первоисточник: FreeRTOS Queue Set API Functions - xQueueCreateSet()

Назад: [FreeRTOS Home] Вверх: [ИПП: Наборы очередей] Вперёд: [xQueueAddToSet()]

 

xQueueCreateSet()

Функция объявляется в файле queue.h

QueueSetHandle_t xQueueCreateSet
               (
                   const UBaseType_t uxEventQueueLength
               );

Настройка configUSE_QUEUE_SETS в файле FreeRTOSConfig.h должна быть установлена в 1 для включения в код функций работы с наборами очередей.

Наборы очередей предоставляют механизм, позволяющий задачам РТОС блокироваться на чтении из нескольких очередей и семафоров РТОС одновременно. Заметьте, что есть более простая альтернатива использованию набора очередей (см. примечания).

Набор очередей должен быть явно создан с помощью вызова xQueueCreateSet(), прежде чем его можно будет использовать. После создания к набору можно добавлять стандартные очереди РТОС и семафоры с помощью вызова xQueueAddToSet(). После этого вызов xQueueSelectFromSet() может быть использован для определения того, какая из очередей или семафоров, содержащихся в наборе, находится в состоянии, в котором операция чтения из очереди или получения семафора, была бы успешной.

Примечания:

  • Существует более простая альтернатива использованию набора очередей. Более подробная информация находится на странице "Блокировка на нескольких объектах".
  • Очереди и семафоры должны быть пусты, когда они добавляются в набор очередей. Обратите особое внимание на добавление таких объектов, как двоичные семафоры, которые при создании могут быть выданы автоматически - это в случае, когда семафор создаётся с помощью макроса vSemaphoreCreateBinary(). Предпочтительно использовать функцию xSemaphoreCreateBinary(), которая не выполняет автоматической выдачи семафора при создании.
  • Блокировка на наборе очередей, содержащем мьютекс, не приведёт к наследованию владельцем мьютекса приоритета заблокированной задачи.
  • Дополнительные 4 байта ОЗУ требуются для каждого места в каждой очереди, добавляемой к набору. Поэтому счётный семафор с большим максимальным значением счётчика не должен добавляться к набору очередей.
  • Операция извлечения из очереди или получения семафора не должна выполняться для членов набора очередей, если вызов xQueueSelectFromSet() не вернул хэндлер для этого члена набора очередей.

Параметры

uxEventQueueLength Наборы очередей хранят события, происходящие в очередях и семафорах, входящих в набор. Параметр uxEventQueueLength определяет максимально возможное количество событий, которые могут быть поставлены в очередь одновременно.

Чтобы быть абсолютно уверенным, что события не потеряны, uxEventQueueLength должен быть задан как сумма длин очередей и семафоров, добавленных в набор. При этом длина двоичных семафоров и мьютексов принимается равной 1, а длина счетных семафоров имеет длину, заданную максимальным значением их счётчика. Например:

  • Если набор очередей включает в себя одну очередь длиной 5, другую очередь длиной 12 и двоичный семафор, то uxEventQueueLength должен быть равен (5 + 12 + 1), т.е. 18.
  • Если набор очередей содержит три двоичных семафора, то uxEventQueueLength должен быть равен (1 + 1 + 1), т.е. 3.
  • Если набор очередей содержит счётный семафор с максимальным значением счётчика равным 5 и счётный семафор с максимальным значением счётчика равным 3, то параметр uxEventQueueLength должен быть равен (5 + 3), т.е. 8.

Возвращаемое значение

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

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

/*----------------------------------------------------------------------------*/
/* Определяем длины очередей, которые будут добавлены к набору очередей. */
#define QUEUE_LENGTH_1		10
#define QUEUE_LENGTH_2		10

/* Двоичные семафоры имеют эффективную длину 1. */
#define BINARY_SEMAPHORE_LENGTH	1

/* Определяем размер элементов очередей 1 и 2 соответственно. Эти значения
используются в демонстрационных целях. */
#define ITEM_SIZE_QUEUE_1	sizeof( uint32_t )
#define ITEM_SIZE_QUEUE_2	sizeof( something_else_t )

/* Итоговая длина двух очередей и двоичного семафора, которые будут добавлены
к набору очередей. */
#define COMBINED_LENGTH ( QUEUE_LENGTH_1 +
                          QUEUE_LENGTH_2 +
                          BINARY_SEMAPHORE_LENGTH )

void vAFunction( void )
{
static QueueSetHandle_t xQueueSet;
QueueHandle_t xQueue1, xQueue2, xSemaphore;
QueueSetMemberHandle_t xActivatedMember;
uint32_t xReceivedFromQueue1;
something_else_t xReceivedFromQueue2;

    /* Создаём набор очередей с длиной, достаточной для размещения событий
    по всему объёму всех очередей и семафоров, добавляемыми в набор. */

    xQueueSet = xQueueCreateSet( COMBINED_LENGTH );

    /* Создаём очереди, которые будут добавлены в набор очередей. */
    xQueue1 = xQueueCreate( QUEUE_LENGTH_1, ITEM_SIZE_QUEUE_1 );
    xQueue2 = xQueueCreate( QUEUE_LENGTH_2, ITEM_SIZE_QUEUE_2 );

    /* Создаём семафор, который будет добавлен в набор очередей. */
    xSemaphore = xSemaphoreCreateBinary();

    /* Проверяем создание всех объектов. */
    configASSERT( xQueueSet );
    configASSERT( xQueue1 );
    configASSERT( xQueue2 );
    configASSERT( xSemaphore );

    /* Добавляем очереди и семафоры к набору очередей. В этот момент
    очереде должны быть пусты, а семафор не выдан. После добавления
    чтение из этих очередей и получение семафоров могут выполняться
    только после того, как xQueueSelectFromSet() вернёт указатель на
    очередь или семафор. */
    xQueueAddToSet( xQueue1, xQueueSet );
    xQueueAddToSet( xQueue2, xQueueSet );
    xQueueAddToSet( xSemaphore, xQueueSet );

    for( ;; )
    {
        /* Блокировка для ожидания доступности чего-либо из очередей
        или семафоров, добавленных в набор. Блокировка не более чем
        на 200мс. */
        xActivatedMember = xQueueSelectFromSet( xQueueSet,
                                                200 / portTICK_PERIOD_MS );

        /* Проверяем, какой элемент набора был выбран. Можно указывать
        нулевое время блокировки, т.к. xQueueSelectFromSet() не вернул бы
        соответствующий дескриптор, если бы в объекте отсутствовали
        доступные элементы. */
        if( xActivatedMember == xQueue1 )
        {
            xQueueReceive( xActivatedMember, &xReceivedFromQueue1, 0 );
            vProcessValueFromQueue1( xReceivedFromQueue1 );
        }
        else if( xActivatedMember == xQueue2 )
        {
            xQueueReceive( xActivatedMember, &xReceivedFromQueue2, 0 );
            vProcessValueFromQueue2( &xReceivedFromQueue2 );
        }
        else if( xActivatedMember == xSemaphore )
        {
            /* Забираем семафор, чтобы убедиться, что он может быть снова выдан. */
            xSemaphoreTake( xActivatedMember, 0 );
            vProcessEventNotifiedBySemaphore();
            break;
        }
        else
        {
            /* Истекло время блокировки (200мс), и за это время не появилось
            одной очереди или семафора, готовых к обработке. */
        }
    }
}
/*----------------------------------------------------------------------------*/
Hobby's category: