Замечание: если вы используете оповещения задач (RTOS task notifications) для реализации поведения двоичного семафора или семафора со счетчиком, то используйте более простую API-функцию ulTaskNotifyTake() вместо xTaskNotifyWait().
Заголовочный файл: task.h.
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t *pulNotificationValue,
TickType_t xTicksToWait );
BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn,
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t *pulNotificationValue,
TickType_t xTicksToWait );
У каждой задачи есть массив оповещений, 'task notifications' (или просто 'оповещения'), каждое из оповещений имеет состояние и 32-битное значение. Уведомление об оповещении задачи это событие, отправляемое непосредственно принимающей событие задаче, чтобы разблокировать её, и опционально обновить одно из значений оповещения принимающей событие задачи несколькими разными способами. Например, оповещение может перезаписать одно из значений оповещения принимающей задачи, или просто установить один или большее количество бит в одном из значений оповещения принимающей задачи.
Функция xTaskNotifyWait() ждет в вызывающей задаче, в течение опционального таймаута, поступления оповещения. Если принимающая задача RTOS была уже в состоянии Blocked, ожидая поступления оповещения, то принимающая задача будет удалена из состояния Blocked, и оповещение очищается.
Замечание: каждое оповещение в массиве работает независимо – задача может быть заблокирована одновременно только на одном оповещении в массиве, и не будет разблокирована оповещением, отправленным по другому индексу в массиве.
xTaskNotifyWait() и xTaskNotifyWaitIndexed() это эквивалентные макросы - единственное их отличие в том, что xTaskNotifyWaitIndexed() может работать на любом оповещении в массиве, а xTaskNotifyWait() всегда работает с оповещением в массиве по индексу 0.
xTaskNotifyGive() не должна вызываться из обработчика прерывания для этого предназначена специальная версия функции выдачи оповещения vTaskNotifyGiveFromISR().
Константа конфигурации времени компиляции configUSE_TASK_NOTIFICATIONS в файле FreeRTOSConfig.h должна быть установлена в 1 (или просто не должна быть определена), чтобы эти макросы были доступны. Константа configTASK_NOTIFICATION_ARRAY_ENTRIES установит количество индексов в каждом массиве оповещений задачи.
Информация для обратной совместимости: до версии FreeRTOS V10.4.0 каждая задача имела единственное "notification value", и все API-функции оповещений задачи работали только с этим одним значением. Замена одиночного значения оповещения массивом потребовала нового набора API-функций, которые могли бы адресовать оповещения в массиве. xTaskNotifyWait() это оригинальная API-функция, и она оставляет возможность обратной совместимости, работая со значением оповещения в массиве по индексу 0. Вызов xTaskNotifyWait() эквивалентен вызову xTaskNotifyWaitIndexed() с установленным в 0 параметром uxIndexToWaitOn.
Параметры:
uxIndexToWaitOn Индекс в массиве значений уведомлений вызывающей задачи, по которому вызывающая задача ожидает получения уведомления. Значение uxIndexToWaitOn должно быть меньше значения опции конфигурации configTASK_NOTIFICATION_ARRAY_ENTRIES. У xTaskNotifyWait() нет этого параметра, и она всегда ждет поступления оповещения на значении с индексом 0.
ulBitsToClearOnEntry Любой набор бит, установленный в ulBitsToClearOnEntry, будет очищен в значении оповещения вызывающей функции (перед тем, как задача начнет ждать нового оповещения) при входе в xTaskNotifyWait(), при условии, что уведомление еще не ожидает при условии, что уведомление еще не ожидает вызова xTaskNotifyWait(). Например, если ulBitsToClearOnEntry 0x01, то бит 0 в значении оповещения задачи будет очищен при входе в функцию. Установка ulBitsToClearOnEntry в 0xffffffff (ULONG_MAX) очистит все биты значения оповещения, что дает эффект обнуления значения оповещения.
ulBitsToClearOnExit Любой набор бит, установленный в ulBitsToClearOnExit, будет очищен в значении оповещения вызывающей задачи перед выходом из функции xTaskNotifyWait(), если оповещение было получено. Биты очищаются после того, как значение оповещения было сохранено в *pulNotificationValue (см. далее описание параметра pulNotificationValue). Например, если ulBitsToClearOnExit 0x03, то бит 0 и бит 1 значения оповещения будут очищены перед выходом из функции. Установка ulBitsToClearOnExit в 0xffffffff (ULONG_MAX) очистит все биты значения оповещения, что дает эффект обнуления значения оповещения.
pulNotificationValue Используется для передачи наружу значения оповещения задачи. Значение, скопированное в * pulNotifityValue, является значением уведомления задачи RTOS, как и до того, как какие-либо биты были очищены из-за настройки ulBitsToClearOnExit. Если значение оповещения не используется, то установите pulNotificationValue в NULL.
xTicksToWait Максимальное время ожидания, в течение которого вызывающая задача находится в состоянии Blocked, ожидая получения оповещения, если если уведомление еще не ожидается при вызове xTaskNotifyWait(). Задача RTOS не потребляет никакое время CPU, когда находится в состоянии Blocked. Время ожидания указывается в тиках RTOS. Может использоваться макрос pdMS_TO_TICKS() для преобразования в тики указанного времени в миллисекундах.
Возвращаемое значение:
pdTRUE, если оповещение было получено, или если уже ожидается вызов оповещения от вызова xTaskNotifyWait(). pdFALSE, если вызов xTaskNotifyWait() завершился по таймауту до получения оповещения.
/* Эта задача показывает биты в значении оповещения задачи RTOS, которое используется
для передачи различных событий задаче таким же способом, как для той же цели могут
использоваться флаги группы событий (event group flags). */
void vAnEventProcessingTask( void *pvParameters )
{
uint32_t ulNotifiedValue;
for( ;; )
{
/* Бесконечная блокировка (без таймаута, так что не нужно проверять
значение возврата из функции) в ожидании оповещения.
Биты в этом значении оповещения устанавливаются оповещающими задачами
и обработчиками прерывания, чтобы оповестить задачу о возникновении
событий. */
xTaskNotifyWaitIndexed( 0, /* Ожидание на 0-ом значении оповещения. */
0x00, /* Не очищать никакие биты на входе. */
ULONG_MAX, /* Сбрасывать значение оповещения на 0 при выходе. */
&ulNotifiedValue, /* Значение оповещения передается наружу
в ulNotifiedValue. */
portMAX_DELAY ); /* Ожидать бесконечно. */
/* Обработка любых событий, которые были защелкнуты в значении оповещения. */
if( ( ulNotifiedValue & 0x01 ) != 0 )
{
/* Был установлен бит 0 - обработать все, что соответствует биту 0. */
prvProcessBit0Event();
}
if( ( ulNotifiedValue & 0x02 ) != 0 )
{
/* Был установлен бит 1 - обработать все, что соответствует биту 1. */
prvProcessBit1Event();
}
if( ( ulNotifiedValue & 0x04 ) != 0 )
{
/* Был установлен бит 2 - обработать все, что соответствует биту 2. */
prvProcessBit2Event();
}
/* И так далее. */
...
}
}
Другие примеры можно посмотреть на страничке с описанием оповещений задач [2].
[Ссылки]
1. xTaskNotifyWait / xTaskNotifyWaitIndexed site:freertos.org. 2. FreeRTOS: оповещения задач. 3. FreeRTOS: семафоры со счетчиком и оповещения задач. 4. ESP-IDF FreeRTOS Task API. 5. FreeRTOS: указатели в TLS. |