Если вы используете оповещения задач (RTOS task notifications) [2] для реализации поведения двоичного семафора или семафора со счетчиком, то используйте более простую API-функцию xTaskNotifyGive() вместо xTaskNotify().
BaseType_t xTaskNotify(TaskHandle_t xTaskToNotify,
uint32_t ulValue,
eNotifyAction eAction);
BaseType_t xTaskNotifyIndexed(TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction);
Значение оповещения (notification value). У каждой задачи есть массив 'оповещений задачи' (или просто 'оповещений'), в каждом таком оповещении хранится состояние и 32-битное значение. Направление задаче оповещения это событие, отправляемое в задачу напрямую, которое может разблокировать эту принимающую задачу, и опционально обновить одно из значений оповещения принимающей задачи, что можно сделать различными способами. Напртимер, оповещение может перезаписать одно из значений оповещений задачи, или просто установить один или большее количество бит в одном из значений оповешения задачи.
Функция xTaskNotify() используется для отправки события напрямую, и потенциально может разблокировать задачу RTOS, и опционально обновить одно из значений оповещения задачи одним из следующих способов:
· Запись 32-битного числа в значение оповещения. · Добавление единицы (инкремент) к значению оповещения. · Установка одного или большего количества бит в значении оповещения. · Оставляя значение оповещения не измененным.
Функции xTaskNotify() и xTaskNotifyIndexed() эквивалентны - единственное их отличие в том, что xTaskNotifyIndexed() может работать с любым из значений оповещения массива (по указанному индексу), а xTaskNotify() всегда работает со значением оповещения в массиве по индексу 0.
Функция xTaskNotify() не должна использоваться для вызова из обработчика прерывания (interrupt service routine, ISR). Для этого предназначена специальная функция xTaskNotifyFromISR().
Чтобы эти функции были доступны, опция конфигурации configUSE_TASK_NOTIFICATIONS (в файле FreeRTOSConfig.h) должна быть установлена 1 (или должна оставаться не определенной). Константа configTASK_NOTIFICATION_ARRAY_ENTRIES установит количество элементов (индексов) в массиве значений оповещения каждой задачи.
Информация для обратной совместимости: до появления версии FreeRTOS V10.4.0 у каждой задачи было только одно "notification value", и все API-функции работали с этим значением. Замена одного значения оповещения на массив потребовало нового набора API-функций, которые могли бы адресовать определенные оповещения в этом массиве. Функция xTaskNotify() это оригинальная API-функция, которая была оставлена для обеспечения обратной совместимости по исходному коду, и она работает со значением оповещения по индексу 0 в массиве. Таким образом, вызов xTaskNotify() эквивалентен вызову xTaskNotifyIndexed() с параметром uxIndexToNotify, установленным в 0.
Параметры:
xTaskToNotify Дескриптор (handle) задачи RTOS, которой придет оповещение (это целевая задача, target task). Чтобы получить дескриптор задачи, создайте её вызовом xTaskCreate() и используйте параметр pxCreatedTask, или создайте задачу вызовом xTaskCreateStatic(), и тогда используйте возвращенное из неё значение, или используйте для получения дескриптора результат вызова функции xTaskGetHandle(), в которую передайте имя задачи. Дескриптор текущей выполняющейся задачи можно получить вызовом функции xTaskGetCurrentTaskHandle().
uxIndexToNotify Индекс в массиве оповещений целевой задачи, куда отправляется оповещение. Значение uxIndexToNotify должно быть меньше configTASK_NOTIFICATION_ARRAY_ENTRIES. У функции xTaskNotify() нет этого параметра, и она всегда посылает оповещения в массив по индексу 0.
ulValue Используется для обновления значения оповещения целевой задачи. См. ниже описание параметра eAction.
eAction Перечисляемый тип, который может принимать одно из значений, перечисленных в таблице ниже, чтобы выполнить определенное действие над значением оповещения.
Значение eAction |
Выполняемое действие |
eNoAction |
Целевая задача получит событие, но её значение оповещения не будет обновлено. В этом случае параметр ulValue не используется. |
eSetBits |
Значение оповещения целевой задачи будет побитной операцией OR (ИЛИ) со значением ulValue. Например, если значение ulValue установлено в 0x01, то бит 0 в значении оповещения целевой задачи будет установлен в 1. Подобным образом, если значение ulValue 0x04, то тогда будет установлен бит 2 значения оповещения целевой задачи. Этим методом механизм оповещений задач RTOS может использоваться как облегченная альтернатива группе событий [5]. |
eIncrement |
Значение оповещения целевой задачи будет инкрементировано на единицу, что делает вызов xTaskNotify() эквивалентным вызову xTaskNotifyGive(). В этом случае параметр ulValue не используется. |
eSetValueWithOverwrite |
Значение оповещения целевой задачи будет безусловно установлено в ulValue. Этим методом механизм оповещений задач RTOS может использоваться как облегченная альтернатива xQueueOverwrite() [6]. |
eSetValueWithoutOverwrite |
Если у целевой задачи пока еще нет ожидающего обработки значения оповещения, то её значение оповещения будет установлено в ulValue. Если же у целевой задачи уже есть оповещения, ожидающее обработки, то её значение оповещения не будет обновлено, так как это привело бы к перезаписи предыдущего, еще не обработанного значения. В этом случае вызов xTaskNotify() считается неудачным, и будет возвращено значение pdFALSE. В этом случает механизм оповещения задач используется как облегченная альтернатива xQueueSend() [7] на очереди длиной 1. |
Возвращаемое значение:
pdPASS будет возвращено во всех случаях, кроме случая, когда eAction установлено в eSetValueWithoutOverwrite, значение оповещения целевой задачи не может быть обновлено из-за того, что эта задача еще не успела обработать свое предуыдущее оповещение.
/* Установка бита 8 в 0-ом значении оповещения задачи, на которую производится
ссылка по дескриптору xTask1Handle. */
xTaskNotifyIndexed(xTask1Handle, 0, (1UL << 8UL), eSetBits);
/* Отправка оповещения задаче с дескриптором xTask2Handle, что потенциально
выведет задачу из состояния Blocked, но без обновления значения оповещения. */
xTaskNotify(xTask2Handle, 0, eNoAction);
/* Установка в 0x50 значения оповещения задачи с дескриптором xTask3Handle,
даже если задача еще не успела прочитать предыдущее значение оповещения. */
xTaskNotify( xTask3Handle, 0x50, eSetValueWithOverwrite );
/* Установка в 0xfff значения оповещения задачи с дескриптором xTask4Handle,
но только если оно не перезапишет предыдущее значение оповещения задачи,
которое целевая задача должна была бы перед этим получить (вызовом
xTaskNotifyWait() или ulTaskNotifyTake()). */
if(xTaskNotify(xTask4Handle, 0xfff, eSetValueWithoutOverwrite) == pdPASS)
{
/* Значение оповещения целевой задачи было обновлено. */
...
}
else
{
/* Значение оповещения целевой задачи не было обновлено. */
...
}
[Ссылки]
1. xTaskNotify / xTaskNotifyIndexed site:freertos.org. 2. FreeRTOS: оповещения задач. 3. FreeRTOS: семафоры со счетчиком и оповещения задач. 4. ESP-IDF FreeRTOS Task API. 5. Event Bits (or flags) and Event Groups site:freertos.org. 6. xQueueOverwrite site:freertos.org. 7. xQueueSend site:freertos.org. |