Source: https://www.freertos.org/RTOS_Task_Notification_As_Event_Group.html
Перевод может содержать ошибки. Читайте первоисточник.
[Task Notifications - Уведомления]
Группа флагов - это множество отдельных флагов, каждый из которых разработчик имеет возможность использовать в различных произвольных целях. Задача RTOS может перейти в заблокированное состояние на время ожидания перехода в активное состояние одного или нескольких флагов внутри группы. Задача RTOS не использует процессорное время, пока находится в заблокированном состоянии.
Когда уведомления используются вместо группы флагов, поле уведомления задачи-получателя используется вместо группы флагов. Биты внутри поля уведомления используются как флаги, а функция API xTaskNotifyWait() используется вместо функции API xEventGroupWaitBits().
Аналогично биты устанавливаются с использованием функций API xTaskNotify() и xTaskNotifyFromISR() со значением параметра eAction == eSetBits вместо функций API xEventGroupSetBits() и xEventGroupSetBitsFromISR().
xTaskNotifyFromISR() имеет значительное преимущество в производительности по сравнению с xEventGroupSetBitsFromISR(), поскольку xTaskNotifyFromISR() выполняется полностью и обработчике прерывания, тогда как xEventGroupSetBitsFromISR() должна отложить часть выполнения до передачи управления задаче-демону RTOS. (Т.е. до передачи управления ядру ОС? Оригинал: ...defer some processing to the RTOS daemon task).
Есть и существенное отличие от использования группы флагов. В случае группы флагов задача-получатель может указать, что она хочет оставаться в заблокированном состоянии до тех пор, пока состояние флагов группы не придёт к некоторой заданной комбинации. А если в качестве группы флагов используются уведомления, то задача-получатель разблокируется, когда любой бит уведомления становится активным. И в этом случае задача-получатель должна сама анализировать состояние всех интересуемых бит в поле уведомления.
/*----------------------------------------------------------------------------*/ /* Этот пример демонстрирует использование одной задачи RTOS для обработки флагов, которые выставляются из двух отдельных обработчиков прерывания: один флаг из прерывания по отправке данных, а второй флаг из прерывания по приёму данных. Следует заметить, что во многих периферийных устройствах используется одно и то же прерывание для обработки различных действий. В этом случае можно просто выполнять операцию "побитовое ИЛИ" для вычисления нового значения уведомления для задачи-получателя. */ /* Определяем биты для представления каждого из источников прерывания. */ #define TX_BIT 0x01 #define RX_BIT 0x02 /* Дескриптор задачи, которая получит уведомление из прерывания. Дескриптор был получен при создании задачи RTOS. */ static TaskHandle_t xHandlingTask; /*----------------------------------------------------------------------------*/ /* Реализация обработчика прерывания по отправке данных. */ void vTxISR( void ) { /* Переменная xHigherPriorityTaskWoken должна быть инициализирована значением pdFALSE. Если вызов функции API с суффиксом "FromISR" разблокирует задачу, приоритет которой выше, чем приоритет текущей запущенной задачи, то xHigherPriorityTaskWoken после вызова этой функции будет установлена в значение pdTRUE. */ BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* Сбрасываем флаг прерывания. */ prvClearInterrupt(); /* Уведомляем задачу-получатель о прерывании по отправке данных установкой бита TX_BIT в поле уведомления. */ xTaskNotifyFromISR( xHandlingTask, TX_BIT, eSetBits, &xHigherPriorityTaskWoken ); /* Если значение xHigherPriorityTaskWoken изменилось на pdTRUE, необходимо выполнить переключение контекста, чтобы выход из обработчика прерывания был осуществлён непосредственно в задачу с наивысшим приоритетом из числа разблокированных. Макрос, используемый для этого, зависит от порта для вашего процессора, и может называться portEND_SWITCHING_ISR. */ portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } /*----------------------------------------------------------------------------*/ /* Реализация обработчика прерывания по приёму данных идентична реализации обработчика прерывания по передаче данных, за исключением бита, устанавливаемого в уведомлении. */ void vRxISR( void ) { /* Переменная xHigherPriorityTaskWoken должна быть инициализирована значением pdFALSE. Если вызов функции API с суффиксом "FromISR" разблокирует задачу, приоритет которой выше, чем приоритет текущей запущенной задачи, то xHigherPriorityTaskWoken после вызова этой функции будет установлена в значение pdTRUE. */ BaseType_t xHigherPriorityTaskWoken = pdFALSE; /* Сбрасываем флаг прерывания. */ prvClearInterrupt(); /* Уведомляем задачу-получатель о прерывании по приёму данных установкой бита RX_BIT в поле уведомления. */ xTaskNotifyFromISR( xHandlingTask, RX_BIT, eSetBits, &xHigherPriorityTaskWoken ); /* Если значение xHigherPriorityTaskWoken изменилось на pdTRUE, необходимо выполнить переключение контекста, чтобы выход из обработчика прерывания был осуществлён непосредственно в задачу с наивысшим приоритетом из числа разблокированных. Макрос, используемый для этого, зависит от порта для вашего процессора, и может называться portEND_SWITCHING_ISR. */ portYIELD_FROM_ISR( xHigherPriorityTaskWoken ); } /*----------------------------------------------------------------------------*/ /* Реализация задачи RTOS, которая получает уведомление от обработчиков прерываний. */ static void prvHandlingTask( void *pvParameter ) { const TickType_t xMaxBlockTime = pdMS_TO_TICKS( 500 ); BaseType_t xResult; for( ;; ) { /* Ожидаем уведомления от обрабочиков прерываний. */ xResult = xTaskNotifyWait( pdFALSE, /* Не очищать биты при входе. */ ULONG_MAX, /* Очищать все биты при выходе. */ &ulNotifiedValue, /* Куда сохранить уведомление. */ xMaxBlockTime ); if( xResult == pdPASS ) { /* Уведомление получено. Смотрим, какие биты установлены. */ if( ( ulNotifiedValue & TX_BIT ) != 0 ) { /* Обработчик прерывания по передаче данных установил бит. */ prvProcessTx(); } if( ( ulNotifiedValue & RX_BIT ) != 0 ) { /* Обработчик прерывания по приёму данных установил бит. */ prvProcessRx(); } } else { /* Уведомление не было получено за отведённое время. */ prvCheckForErrors(); } } }