Browse Source

Remaining task notification functions

tangzz98 3 years ago
parent
commit
04bdb7a781

+ 2 - 2
FreeRTOS/include/FreeRTOSConfig.h

@@ -48,7 +48,6 @@
 #define configUSE_TICK_HOOK                     1
 #define configCPU_CLOCK_HZ                      ( SystemCoreClock )
 #define configTICK_RATE_HZ                      ( 1000 )
-#define configMAX_PRIORITIES                    ( 5 )
 #define configMINIMAL_STACK_SIZE                ( ( unsigned short ) 130 )
 #define configMAX_TASK_NAME_LEN                 ( 10 )
 #define configUSE_TRACE_FACILITY                1
@@ -84,7 +83,6 @@ FreeRTOS/Source/tasks.c for limitations. */
 /* Set the following definitions to 1 to include the API function, or zero
 to exclude the API function. */
 #define INCLUDE_vTaskCleanUpResources   1
-#define INCLUDE_eTaskGetState           1
 #define INCLUDE_xTimerPendFunctionCall  1
 
 /* Cortex-M specific definitions. */
@@ -141,5 +139,7 @@ standard names. */
 #define INCLUDE_uxTaskGetStackHighWaterMark     1
 #define INCLUDE_uxTaskGetStackHighWaterMark2    1
 #define configUSE_TASK_NOTIFICATIONS            1
+#define INCLUDE_eTaskGetState                   1
+#define configMAX_PRIORITIES                    ( 32 )
 
 #endif /* FREERTOS_CONFIG_H */

+ 582 - 0
FreeRTOS/include/task.h

@@ -1301,6 +1301,188 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
 #define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \
     xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL )
 
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );
+ * BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * xTaskNotifyAndQueryIndexed() performs the same operation as
+ * xTaskNotifyIndexed() with the addition that it also returns the subject
+ * task's prior notification value (the notification value at the time the
+ * function is called rather than when the function returns) in the additional
+ * pulPreviousNotifyValue parameter.
+ *
+ * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the
+ * addition that it also returns the subject task's prior notification value
+ * (the notification value as it was at the time the function is called, rather
+ * than when the function returns) in the additional pulPreviousNotifyValue
+ * parameter.
+ *
+ * \defgroup xTaskNotifyAndQueryIndexed xTaskNotifyAndQueryIndexed
+ * \ingroup TaskNotifications
+ */
+#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) \
+    xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) )
+#define xTaskNotifyAndQueryIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotifyValue ) \
+    xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * A version of xTaskNotifyIndexed() that can be used from an interrupt service
+ * routine (ISR).
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t).  The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values.  In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a
+ * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block
+ * to wait for a notification value to have a non-zero value.  The task does
+ * not consume any CPU time while it is in the Blocked state.
+ *
+ * A notification sent to a task will remain pending until it is cleared by the
+ * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their
+ * un-indexed equivalents).  If the task was already in the Blocked state to
+ * wait for a notification when the notification arrives then the task will
+ * automatically be removed from the Blocked state (unblocked) and the
+ * notification cleared.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array.  xTaskNotifyFromISR() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling xTaskNotifyFromISR() is equivalent to calling
+ * xTaskNotifyIndexedFromISR() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param uxIndexToNotify The index within the target task's array of
+ * notification values to which the notification is to be sent.  uxIndexToNotify
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.  xTaskNotifyFromISR()
+ * does not have this parameter and always sends notifications to index 0.
+ *
+ * @param xTaskToNotify The handle of the task being notified.  The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param ulValue Data that can be sent with the notification.  How the data is
+ * used depends on the value of the eAction parameter.
+ *
+ * @param eAction Specifies how the notification updates the task's notification
+ * value, if at all.  Valid values for eAction are as follows:
+ *
+ * eSetBits -
+ * The task's notification value is bitwise ORed with ulValue.  xTaskNotify()
+ * always returns pdPASS in this case.
+ *
+ * eIncrement -
+ * The task's notification value is incremented.  ulValue is not used and
+ * xTaskNotify() always returns pdPASS in this case.
+ *
+ * eSetValueWithOverwrite -
+ * The task's notification value is set to the value of ulValue, even if the
+ * task being notified had not yet processed the previous notification (the
+ * task already had a notification pending).  xTaskNotify() always returns
+ * pdPASS in this case.
+ *
+ * eSetValueWithoutOverwrite -
+ * If the task being notified did not already have a notification pending then
+ * the task's notification value is set to ulValue and xTaskNotify() will
+ * return pdPASS.  If the task being notified already had a notification
+ * pending then no action is performed and pdFAIL is returned.
+ *
+ * eNoAction -
+ * The task receives a notification without its notification value being
+ * updated.  ulValue is not used and xTaskNotify() always returns pdPASS in
+ * this case.
+ *
+ * @param pxHigherPriorityTaskWoken  xTaskNotifyFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task.  If
+ * xTaskNotifyFromISR() sets this value to pdTRUE then a context switch should
+ * be requested before the interrupt is exited.  How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * @return Dependent on the value of eAction.  See the description of the
+ * eAction parameter.
+ *
+ * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR
+ * \ingroup TaskNotifications
+ */
+BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
+                                      UBaseType_t uxIndexToNotify,
+                                      uint32_t ulValue,
+                                      eNotifyAction eAction,
+                                      uint32_t * pulPreviousNotificationValue,
+                                      BaseType_t * pxHigherPriorityTaskWoken );
+#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \
+    xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )
+#define xTaskNotifyIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) \
+    xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );
+ * BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * xTaskNotifyAndQueryIndexedFromISR() performs the same operation as
+ * xTaskNotifyIndexedFromISR() with the addition that it also returns the
+ * subject task's prior notification value (the notification value at the time
+ * the function is called rather than at the time the function returns) in the
+ * additional pulPreviousNotifyValue parameter.
+ *
+ * xTaskNotifyAndQueryFromISR() performs the same operation as
+ * xTaskNotifyFromISR() with the addition that it also returns the subject
+ * task's prior notification value (the notification value at the time the
+ * function is called rather than at the time the function returns) in the
+ * additional pulPreviousNotifyValue parameter.
+ *
+ * \defgroup xTaskNotifyAndQueryIndexedFromISR xTaskNotifyAndQueryIndexedFromISR
+ * \ingroup TaskNotifications
+ */
+#define xTaskNotifyAndQueryIndexedFromISR( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \
+    xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )
+#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) \
+    xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) )
+
 /**
  * task. h
  * @code{c}
@@ -1415,6 +1597,406 @@ BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
 #define xTaskNotifyWaitIndexed( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \
     xTaskGenericNotifyWait( ( uxIndexToWaitOn ), ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) )
 
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify );
+ * BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
+ * @endcode
+ *
+ * Sends a direct to task notification to a particular index in the target
+ * task's notification array in a manner similar to giving a counting semaphore.
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * macros to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t).  The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values.  In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * xTaskNotifyGiveIndexed() is a helper macro intended for use when task
+ * notifications are used as light weight and faster binary or counting
+ * semaphore equivalents.  Actual FreeRTOS semaphores are given using the
+ * xSemaphoreGive() API function, the equivalent action that instead uses a task
+ * notification is xTaskNotifyGiveIndexed().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotificationTakeIndexed() API function rather than the
+ * xTaskNotifyWaitIndexed() API function.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array.  xTaskNotifyGive() is the original API function, and remains backward
+ * compatible by always operating on the notification value at index 0 in the
+ * array. Calling xTaskNotifyGive() is equivalent to calling
+ * xTaskNotifyGiveIndexed() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param xTaskToNotify The handle of the task being notified.  The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param uxIndexToNotify The index within the target task's array of
+ * notification values to which the notification is to be sent.  uxIndexToNotify
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.  xTaskNotifyGive()
+ * does not have this parameter and always sends notifications to index 0.
+ *
+ * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the
+ * eAction parameter set to eIncrement - so pdPASS is always returned.
+ *
+ * \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed
+ * \ingroup TaskNotifications
+ */
+#define xTaskNotifyGive( xTaskToNotify ) \
+    xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( 0 ), eIncrement, NULL )
+#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \
+    xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( 0 ), eIncrement, NULL )
+
+/**
+ * task. h
+ * @code{c}
+ * void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken );
+ * void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ * @endcode
+ *
+ * A version of xTaskNotifyGiveIndexed() that can be called from an interrupt
+ * service routine (ISR).
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
+ * to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t).  The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values.  In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications
+ * are used as light weight and faster binary or counting semaphore equivalents.
+ * Actual FreeRTOS semaphores are given from an ISR using the
+ * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
+ * a task notification is vTaskNotifyGiveIndexedFromISR().
+ *
+ * When task notifications are being used as a binary or counting semaphore
+ * equivalent then the task being notified should wait for the notification
+ * using the ulTaskNotificationTakeIndexed() API function rather than the
+ * xTaskNotifyWaitIndexed() API function.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array.  xTaskNotifyFromISR() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling xTaskNotifyGiveFromISR() is equivalent to calling
+ * xTaskNotifyGiveIndexedFromISR() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param xTaskToNotify The handle of the task being notified.  The handle to a
+ * task can be returned from the xTaskCreate() API function used to create the
+ * task, and the handle of the currently running task can be obtained by calling
+ * xTaskGetCurrentTaskHandle().
+ *
+ * @param uxIndexToNotify The index within the target task's array of
+ * notification values to which the notification is to be sent.  uxIndexToNotify
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ * xTaskNotifyGiveFromISR() does not have this parameter and always sends
+ * notifications to index 0.
+ *
+ * @param pxHigherPriorityTaskWoken  vTaskNotifyGiveFromISR() will set
+ * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
+ * task to which the notification was sent to leave the Blocked state, and the
+ * unblocked task has a priority higher than the currently running task.  If
+ * vTaskNotifyGiveFromISR() sets this value to pdTRUE then a context switch
+ * should be requested before the interrupt is exited.  How a context switch is
+ * requested from an ISR is dependent on the port - see the documentation page
+ * for the port in use.
+ *
+ * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR
+ * \ingroup TaskNotifications
+ */
+void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
+                                    UBaseType_t uxIndexToNotify,
+                                    BaseType_t * pxHigherPriorityTaskWoken );
+#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \
+    vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) );
+#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) \
+    vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) );
+
+/**
+ * task. h
+ * @code{c}
+ * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ *
+ * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * @endcode
+ *
+ * Waits for a direct to task notification on a particular index in the calling
+ * task's notification array in a manner similar to taking a counting semaphore.
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this
+ * function to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t).  The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * Events can be sent to a task using an intermediary object.  Examples of such
+ * objects are queues, semaphores, mutexes and event groups.  Task notifications
+ * are a method of sending an event directly to a task without the need for such
+ * an intermediary object.
+ *
+ * A notification sent to a task can optionally perform an action, such as
+ * update, overwrite or increment one of the task's notification values.  In
+ * that way task notifications can be used to send data to a task, or be used as
+ * light weight and fast binary or counting semaphores.
+ *
+ * ulTaskNotifyTakeIndexed() is intended for use when a task notification is
+ * used as a faster and lighter weight binary or counting semaphore alternative.
+ * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function,
+ * the equivalent action that instead uses a task notification is
+ * ulTaskNotifyTakeIndexed().
+ *
+ * When a task is using its notification value as a binary or counting semaphore
+ * other tasks should send notifications to it using the xTaskNotifyGiveIndexed()
+ * macro, or xTaskNotifyIndex() function with the eAction parameter set to
+ * eIncrement.
+ *
+ * ulTaskNotifyTakeIndexed() can either clear the task's notification value at
+ * the array index specified by the uxIndexToWaitOn parameter to zero on exit,
+ * in which case the notification value acts like a binary semaphore, or
+ * decrement the notification value on exit, in which case the notification
+ * value acts like a counting semaphore.
+ *
+ * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for
+ * a notification.  The task does not consume any CPU time while it is in the
+ * Blocked state.
+ *
+ * Where as xTaskNotifyWaitIndexed() will return when a notification is pending,
+ * ulTaskNotifyTakeIndexed() will return when the task's notification value is
+ * not zero.
+ *
+ * **NOTE** Each notification within the array operates independently - a task
+ * can only block on one notification within the array at a time and will not be
+ * unblocked by a notification sent to any other array index.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array.  ulTaskNotifyTake() is the original API function, and remains backward
+ * compatible by always operating on the notification value at index 0 in the
+ * array. Calling ulTaskNotifyTake() is equivalent to calling
+ * ulTaskNotifyTakeIndexed() with the uxIndexToWaitOn parameter set to 0.
+ *
+ * @param uxIndexToWaitOn The index within the calling task's array of
+ * notification values on which the calling task will wait for a notification to
+ * be non-zero.  uxIndexToWaitOn must be less than
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES.  xTaskNotifyTake() does
+ * not have this parameter and always waits for notifications on index 0.
+ *
+ * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's
+ * notification value is decremented when the function exits.  In this way the
+ * notification value acts like a counting semaphore.  If xClearCountOnExit is
+ * not pdFALSE then the task's notification value is cleared to zero when the
+ * function exits.  In this way the notification value acts like a binary
+ * semaphore.
+ *
+ * @param xTicksToWait The maximum amount of time that the task should wait in
+ * the Blocked state for the task's notification value to be greater than zero,
+ * should the count not already be greater than zero when
+ * ulTaskNotifyTake() was called.  The task will not consume any processing
+ * time while it is in the Blocked state.  This is specified in kernel ticks,
+ * the macro pdMS_TO_TICKS( value_in_ms ) can be used to convert a time
+ * specified in milliseconds to a time specified in ticks.
+ *
+ * @return The task's notification count before it is either cleared to zero or
+ * decremented (see the xClearCountOnExit parameter).
+ *
+ * \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed
+ * \ingroup TaskNotifications
+ */
+uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
+                                  BaseType_t xClearCountOnExit,
+                                  TickType_t xTicksToWait );
+#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \
+    ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), ( xClearCountOnExit ), ( xTicksToWait ) )
+#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) \
+    ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), ( xClearCountOnExit ), ( xTicksToWait ) )
+
+/**
+ * task. h
+ * @code{c}
+ * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear );
+ *
+ * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t).  The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * If a notification is sent to an index within the array of notifications then
+ * the notification at that index is said to be 'pending' until it is read or
+ * explicitly cleared by the receiving task.  xTaskNotifyStateClearIndexed()
+ * is the function that clears a pending notification without reading the
+ * notification value.  The notification value at the same array index is not
+ * altered.  Set xTask to NULL to clear the notification state of the calling
+ * task.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array.  xTaskNotifyStateClear() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling xTaskNotifyStateClear() is equivalent to calling
+ * xTaskNotifyStateClearIndexed() with the uxIndexToNotify parameter set to 0.
+ *
+ * @param xTask The handle of the RTOS task that will have a notification state
+ * cleared.  Set xTask to NULL to clear a notification state in the calling
+ * task.  To obtain a task's handle create the task using xTaskCreate() and
+ * make use of the pxCreatedTask parameter, or create the task using
+ * xTaskCreateStatic() and store the returned value, or use the task's name in
+ * a call to xTaskGetHandle().
+ *
+ * @param uxIndexToClear The index within the target task's array of
+ * notification values to act upon.  For example, setting uxIndexToClear to 1
+ * will clear the state of the notification at index 1 within the array.
+ * uxIndexToClear must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ * ulTaskNotifyStateClear() does not have this parameter and always acts on the
+ * notification at index 0.
+ *
+ * @return pdTRUE if the task's notification state was set to
+ * eNotWaitingNotification, otherwise pdFALSE.
+ *
+ * \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed
+ * \ingroup TaskNotifications
+ */
+BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
+                                         UBaseType_t uxIndexToClear );
+#define xTaskNotifyStateClear( xTask ) \
+    xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) )
+#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \
+    xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) )
+
+/**
+ * task. h
+ * @code{c}
+ * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear );
+ *
+ * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear );
+ * @endcode
+ *
+ * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
+ *
+ * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
+ * functions to be available.
+ *
+ * Each task has a private array of "notification values" (or 'notifications'),
+ * each of which is a 32-bit unsigned integer (uint32_t).  The constant
+ * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
+ * array, and (for backward compatibility) defaults to 1 if left undefined.
+ * Prior to FreeRTOS V10.4.0 there was only one notification value per task.
+ *
+ * ulTaskNotifyValueClearIndexed() clears the bits specified by the
+ * ulBitsToClear bit mask in the notification value at array index uxIndexToClear
+ * of the task referenced by xTask.
+ *
+ * Backward compatibility information:
+ * Prior to FreeRTOS V10.4.0 each task had a single "notification value", and
+ * all task notification API functions operated on that value. Replacing the
+ * single notification value with an array of notification values necessitated a
+ * new set of API functions that could address specific notifications within the
+ * array.  ulTaskNotifyValueClear() is the original API function, and remains
+ * backward compatible by always operating on the notification value at index 0
+ * within the array. Calling ulTaskNotifyValueClear() is equivalent to calling
+ * ulTaskNotifyValueClearIndexed() with the uxIndexToClear parameter set to 0.
+ *
+ * @param xTask The handle of the RTOS task that will have bits in one of its
+ * notification values cleared. Set xTask to NULL to clear bits in a
+ * notification value of the calling task.  To obtain a task's handle create the
+ * task using xTaskCreate() and make use of the pxCreatedTask parameter, or
+ * create the task using xTaskCreateStatic() and store the returned value, or
+ * use the task's name in a call to xTaskGetHandle().
+ *
+ * @param uxIndexToClear The index within the target task's array of
+ * notification values in which to clear the bits.  uxIndexToClear
+ * must be less than configTASK_NOTIFICATION_ARRAY_ENTRIES.
+ * ulTaskNotifyValueClear() does not have this parameter and always clears bits
+ * in the notification value at index 0.
+ *
+ * @param ulBitsToClear Bit mask of the bits to clear in the notification value of
+ * xTask. Set a bit to 1 to clear the corresponding bits in the task's notification
+ * value. Set ulBitsToClear to 0xffffffff (UINT_MAX on 32-bit architectures) to clear
+ * the notification value to 0.  Set ulBitsToClear to 0 to query the task's
+ * notification value without clearing any bits.
+ *
+ *
+ * @return The value of the target task's notification value before the bits
+ * specified by ulBitsToClear were cleared.
+ * \defgroup ulTaskNotifyValueClear ulTaskNotifyValueClear
+ * \ingroup TaskNotifications
+ */
+uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
+                                        UBaseType_t uxIndexToClear,
+                                        uint32_t ulBitsToClear );
+#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \
+    ulTaskGenericNotifyValueClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulBitsToClear ) )
+#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \
+    ulTaskGenericNotifyValueClear( ( xTask ), ( uxIndexToClear ), ( ulBitsToClear ) )
+
 /*
  * Return the handle of the calling task.
  */

+ 221 - 12
FreeRTOS/task.c

@@ -71,6 +71,19 @@ typedef tskTCB TCB_t;
 
 /*-----------------------------------------------------------*/
 
+/*
+ * Called after a Task_t structure has been allocated either statically or
+ * dynamically to fill in the structure's members.
+ */
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+                                  const char * const pcName,
+                                  const uint32_t ulStackDepth,
+                                  void * const pvParameters,
+                                  UBaseType_t uxPriority,
+                                  TaskHandle_t * const pxCreatedTask,
+                                  TCB_t * pxNewTCB,
+                                  StackType_t * const puxStackBuffer );
+
 #if ( configSUPPORT_STATIC_ALLOCATION == 1 )
 
     TaskHandle_t xTaskCreateStatic( TaskFunction_t pxTaskCode,
@@ -81,6 +94,7 @@ typedef tskTCB TCB_t;
                                     StackType_t * const puxStackBuffer,
                                     StaticTask_t * const pxTaskBuffer )
     {
+        TCB_t * pxNewTCB;
         TaskHandle_t xReturn = NULL;
 
         configASSERT( puxStackBuffer != NULL );
@@ -99,10 +113,9 @@ typedef tskTCB TCB_t;
 
         if( ( pxTaskBuffer != NULL ) && ( puxStackBuffer != NULL ) )
         {
-            rt_thread_init( ( struct rt_thread * ) pxTaskBuffer, pcName, pxTaskCode, pvParameters,
-                            ( void * ) puxStackBuffer, ulStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 );
-            rt_thread_startup( ( rt_thread_t ) pxTaskBuffer );
-            xReturn = ( TaskHandle_t ) pxTaskBuffer;
+            pxNewTCB = ( TCB_t * ) pxTaskBuffer;
+            prvInitialiseNewTask( pxTaskCode, pcName, ulStackDepth, pvParameters, uxPriority, &xReturn, pxNewTCB, puxStackBuffer );
+            rt_thread_startup( ( rt_thread_t ) pxNewTCB );
         }
 
         return xReturn;
@@ -129,13 +142,8 @@ typedef tskTCB TCB_t;
             stack_start = RT_KERNEL_MALLOC( usStackDepth * sizeof( StackType_t ) );
             if ( stack_start != RT_NULL )
             {
-                rt_thread_init( ( struct rt_thread * ) pxNewTCB, pcName, pxTaskCode, pvParameters,
-                                stack_start, usStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 );
+                prvInitialiseNewTask( pxTaskCode, pcName, ( uint32_t ) usStackDepth, pvParameters, uxPriority, pxCreatedTask, pxNewTCB, ( StackType_t * ) stack_start );
                 xReturn = pdPASS;
-                if ( pxCreatedTask != NULL )
-                {
-                    *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
-                }
                 /* Mark as dynamic */
                 ( ( struct rt_thread * ) pxNewTCB )->type &= ~RT_Object_Class_Static;
                 rt_thread_startup( ( rt_thread_t ) pxNewTCB );
@@ -152,6 +160,42 @@ typedef tskTCB TCB_t;
 #endif /* configSUPPORT_DYNAMIC_ALLOCATION */
 /*-----------------------------------------------------------*/
 
+static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
+                                  const char * const pcName,
+                                  const uint32_t ulStackDepth,
+                                  void * const pvParameters,
+                                  UBaseType_t uxPriority,
+                                  TaskHandle_t * const pxCreatedTask,
+                                  TCB_t * pxNewTCB,
+                                  StackType_t * const puxStackBuffer )
+{
+    /* This is used as an array index so must ensure it's not too large. */
+    configASSERT( uxPriority < configMAX_PRIORITIES );
+
+    if( uxPriority >= ( UBaseType_t ) configMAX_PRIORITIES )
+    {
+        uxPriority = ( UBaseType_t ) configMAX_PRIORITIES - ( UBaseType_t ) 1U;
+    }
+
+    rt_thread_init( ( struct rt_thread * ) pxNewTCB, pcName, pxTaskCode, pvParameters,
+                    puxStackBuffer, ulStackDepth * sizeof( StackType_t ), FREERTOS_PRIORITY_TO_RTTHREAD( uxPriority ), 1 );
+
+#if ( configUSE_APPLICATION_TASK_TAG == 1 )
+    pxNewTCB->pxTaskTag = NULL;
+#endif
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+    rt_memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) );
+    rt_memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) );
+#endif
+
+    if ( pxCreatedTask != NULL )
+    {
+        *pxCreatedTask = ( TaskHandle_t ) pxNewTCB;
+    }
+}
+/*-----------------------------------------------------------*/
+
 #if ( INCLUDE_vTaskDelete == 1 )
 
     void vTaskDelete( TaskHandle_t xTaskToDelete )
@@ -396,7 +440,7 @@ typedef tskTCB TCB_t;
             {
                 need_schedule = RT_TRUE;
             }
-            rt_hw_interrupt_enable(level);
+            rt_hw_interrupt_enable( level );
         }
         if (need_schedule == RT_TRUE)
         {
@@ -618,6 +662,68 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )
 #endif /* ( ( INCLUDE_xTaskGetCurrentTaskHandle == 1 ) || ( configUSE_MUTEXES == 1 ) ) */
 /*-----------------------------------------------------------*/
 
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+    uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
+                                      BaseType_t xClearCountOnExit,
+                                      TickType_t xTicksToWait )
+    {
+        uint32_t ulReturn;
+        TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self();
+        rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB;
+        rt_base_t level;
+
+        configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+
+        level = rt_hw_interrupt_disable();
+        /* Only block if the notification count is not already non-zero. */
+        if( pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] == 0UL )
+        {
+            /* Mark this task as waiting for a notification. */
+            pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
+
+            if( xTicksToWait > ( TickType_t ) 0 )
+            {
+                rt_thread_suspend( thread );
+                if ( ( rt_int32_t ) xTicksToWait > 0 )
+                {
+                    rt_timer_control(&(thread->thread_timer),
+                                     RT_TIMER_CTRL_SET_TIME,
+                                     &xTicksToWait);
+                    rt_timer_start(&(thread->thread_timer));
+                }
+                rt_hw_interrupt_enable(level);
+                rt_schedule();
+                /* Clear thread error. */
+                thread->error = RT_EOK;
+            }
+        }
+        rt_hw_interrupt_enable( level );
+
+        level = rt_hw_interrupt_disable();
+        ulReturn = pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ];
+
+        if( ulReturn != 0UL )
+        {
+            if( xClearCountOnExit != pdFALSE )
+            {
+                pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = 0UL;
+            }
+            else
+            {
+                pxCurrentTCB->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
+            }
+        }
+
+        pxCurrentTCB->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
+        rt_hw_interrupt_enable( level );
+
+        return ulReturn;
+    }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
 #if ( configUSE_TASK_NOTIFICATIONS == 1 )
 
     BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
@@ -628,7 +734,7 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )
     {
         BaseType_t xReturn;
         TCB_t * pxCurrentTCB = ( TCB_t * ) rt_thread_self();
-        rt_thread_t thread = rt_thread_self();
+        rt_thread_t thread = ( rt_thread_t ) pxCurrentTCB;
         rt_base_t level;
 
         configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
@@ -799,6 +905,109 @@ char * pcTaskGetName( TaskHandle_t xTaskToQuery )
 #endif /* configUSE_TASK_NOTIFICATIONS */
 /*-----------------------------------------------------------*/
 
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+    BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
+                                          UBaseType_t uxIndexToNotify,
+                                          uint32_t ulValue,
+                                          eNotifyAction eAction,
+                                          uint32_t * pulPreviousNotificationValue,
+                                          BaseType_t * pxHigherPriorityTaskWoken )
+    {
+        BaseType_t xReturn;
+
+        xReturn = xTaskGenericNotify( xTaskToNotify, uxIndexToNotify, ulValue, eAction, pulPreviousNotificationValue );
+        if ( pxHigherPriorityTaskWoken != NULL )
+        {
+            *pxHigherPriorityTaskWoken = pdFALSE;
+        }
+
+        return xReturn;
+    }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+    void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
+                                        UBaseType_t uxIndexToNotify,
+                                        BaseType_t * pxHigherPriorityTaskWoken )
+    {
+        xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify );
+        if ( pxHigherPriorityTaskWoken != NULL )
+        {
+            *pxHigherPriorityTaskWoken = pdFALSE;
+        }
+    }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+    BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
+                                             UBaseType_t uxIndexToClear )
+    {
+        TCB_t * pxTCB;
+        BaseType_t xReturn;
+        rt_base_t level;
+
+        configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
+
+        /* If null is passed in here then it is the calling task that is having
+         * its notification state cleared. */
+        pxTCB = prvGetTCBFromHandle( xTask );
+
+        level = rt_hw_interrupt_disable();
+
+        if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
+        {
+            pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
+            xReturn = pdPASS;
+        }
+        else
+        {
+            xReturn = pdFAIL;
+        }
+
+        rt_hw_interrupt_enable( level );
+
+        return xReturn;
+    }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
+#if ( configUSE_TASK_NOTIFICATIONS == 1 )
+
+    uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
+                                            UBaseType_t uxIndexToClear,
+                                            uint32_t ulBitsToClear )
+    {
+        TCB_t * pxTCB;
+        uint32_t ulReturn;
+        rt_base_t level;
+
+        /* If null is passed in here then it is the calling task that is having
+         * its notification state cleared. */
+        pxTCB = prvGetTCBFromHandle( xTask );
+
+        level = rt_hw_interrupt_disable();
+
+        /* Return the notification as it was before the bits were cleared,
+         * then clear the bit mask. */
+        ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
+        pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
+
+        rt_hw_interrupt_enable( level );
+
+        return ulReturn;
+    }
+
+#endif /* configUSE_TASK_NOTIFICATIONS */
+/*-----------------------------------------------------------*/
+
 #if ( INCLUDE_uxTaskGetStackHighWaterMark2 == 1 )
 
 /* uxTaskGetStackHighWaterMark() and uxTaskGetStackHighWaterMark2() are the

+ 63 - 0
test/task_notification_binary_semaphore.c

@@ -0,0 +1,63 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ */
+
+/*
+ *
+ * Demo: task notification
+ * This program demonstrates using task notification as a light weight binary semaphore
+ *
+ */
+
+#include <rtthread.h>
+#include <FreeRTOS.h>
+#include <task.h>
+
+#define TASK_PRIORITY         25
+
+static TaskHandle_t xHandle = NULL;
+static rt_timer_t timer1;
+
+static void vTask1Code(void * pvParameters)
+{
+    while (1)
+    {
+        uint32_t ulNotificationValue;
+        ulNotificationValue = ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
+        if (ulNotificationValue == 1)
+        {
+            rt_kprintf("Task received notification\n");
+        }
+    }
+}
+
+static void timeout(void *parameter)
+{
+    rt_kprintf("Timer interrupt generated\n");
+    vTaskNotifyGiveFromISR(xHandle, NULL);
+}
+
+int task_notification_binary_semaphore()
+{
+    xTaskCreate(vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &xHandle);
+    if (xHandle == NULL)
+    {
+        rt_kprintf("Create task failed\n");
+        return -1;
+    }
+    /* Create a hard timer with period of 1 second */
+    timer1 = rt_timer_create("timer1", timeout, RT_NULL, rt_tick_from_millisecond(1000), RT_TIMER_FLAG_PERIODIC | RT_TIMER_FLAG_HARD_TIMER);
+    if (timer1 != RT_NULL)
+    {
+        rt_timer_start(timer1);
+    }
+    return 0;
+}
+
+MSH_CMD_EXPORT(task_notification_binary_semaphore, task notification sample);

+ 94 - 0
test/task_notification_event_group.c

@@ -0,0 +1,94 @@
+/*
+ * Copyright (c) 2006-2022, RT-Thread Development Team
+ *
+ * SPDX-License-Identifier: Apache-2.0
+ *
+ * Change Logs:
+ * Date           Author       Notes
+ * 2018-08-24     yangjie      the first version
+ */
+
+/*
+ *
+ * Demo: task notification
+ * This program demonstrates using task notification as a light weight event group
+ *
+ */
+
+#include <rtthread.h>
+#include <FreeRTOS.h>
+#include <task.h>
+
+#define TASK_PRIORITY         25
+#define BIT_0                 ( 1 << 0 )
+#define BIT_1                 ( 1 << 1 )
+
+static TaskHandle_t TaskHandle1 = NULL;
+static TaskHandle_t TaskHandle2 = NULL;
+static TaskHandle_t TaskHandle3 = NULL;
+
+static void vTask1Code(void * pvParameters)
+{
+    BaseType_t xResult;
+    uint32_t ulNotificationValue;
+    while (1)
+    {
+        xResult = xTaskNotifyWait( pdFALSE, BIT_0 | BIT_1, &ulNotificationValue, portMAX_DELAY);
+        if (xResult == pdTRUE)
+        {
+            if (ulNotificationValue & BIT_0)
+            {
+                rt_kprintf("Task 1 received notification from task 2\n");
+            }
+            if (ulNotificationValue & BIT_1)
+            {
+                rt_kprintf("Task 1 received notification from task 3\n");
+            }
+        }
+    }
+}
+
+void vTask2Code(void * pvParameters)
+{
+    while (1)
+    {
+        vTaskDelay(pdMS_TO_TICKS(1000));
+        rt_kprintf("Task 2 send notification\n");
+        xTaskNotify(TaskHandle1, BIT_0, eSetBits);
+    }
+}
+
+void vTask3Code(void * pvParameters)
+{
+    while (1)
+    {
+        vTaskDelay(pdMS_TO_TICKS(2000));
+        rt_kprintf("Task 3 send notification\n");
+        xTaskNotify(TaskHandle1, BIT_1, eSetBits);
+    }
+}
+
+int task_notification_event_group()
+{
+    xTaskCreate(vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle1);
+    if (TaskHandle1 == NULL)
+    {
+        rt_kprintf("Create task failed\n");
+        return -1;
+    }
+    xTaskCreate(vTask2Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle2);
+    if (TaskHandle2 == NULL)
+    {
+        rt_kprintf("Create task failed\n");
+        return -1;
+    }
+    xTaskCreate(vTask3Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY, &TaskHandle3);
+    if (TaskHandle3 == NULL)
+    {
+        rt_kprintf("Create task failed\n");
+        return -1;
+    }
+    return 0;
+}
+
+MSH_CMD_EXPORT(task_notification_event_group, task notification sample);

+ 1 - 1
test/test_event_group_dynamic.c

@@ -70,7 +70,7 @@ int event_group_dynamic(void)
         rt_kprintf("create event group failed.\n");
         return -1;
     }
-    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle1 );
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle1 );
     if (TaskHandle1 == NULL)
     {
         rt_kprintf("Create task 1 failed\n");

+ 1 - 1
test/test_event_group_static.c

@@ -70,7 +70,7 @@ int event_group_static(void)
         rt_kprintf("create event group failed.\n");
         return -1;
     }
-    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle1 );
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle1 );
     if (TaskHandle1 == NULL)
     {
         rt_kprintf("Create task 1 failed\n");

+ 1 - 1
test/test_queue_dynamic.c

@@ -79,7 +79,7 @@ int queue_dynamic(void)
         rt_kprintf("create dynamic queue failed.\n");
         return -1;
     }
-    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle1 );
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle1 );
     if (TaskHandle1 == NULL)
     {
         rt_kprintf("Create task 1 failed\n");

+ 1 - 1
test/test_queue_static.c

@@ -81,7 +81,7 @@ int queue_static(void)
         rt_kprintf("create static queue failed.\n");
         return -1;
     }
-    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle1 );
+    xTaskCreate( vTask1Code, "Task1", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle1 );
     if (TaskHandle1 == NULL)
     {
         rt_kprintf("Create task 1 failed\n");

+ 1 - 1
test/test_semaphore_binary_dynamic.c

@@ -92,7 +92,7 @@ int semaphore_binary_dynamic()
         rt_kprintf("Create task 1 failed\n");
         return -1;
     }
-    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle2 );
+    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     if (TaskHandle2 == NULL)
     {
         rt_kprintf("Create task 2 failed\n");

+ 1 - 1
test/test_semaphore_binary_static.c

@@ -94,7 +94,7 @@ int semaphore_binary_static()
         rt_kprintf("Create task 1 failed\n");
         return -1;
     }
-    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle2 );
+    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     if (TaskHandle2 == NULL)
     {
         rt_kprintf("Create task 2 failed\n");

+ 1 - 1
test/test_semaphore_counting_dynamic.c

@@ -103,7 +103,7 @@ int semaphore_counting_dynamic()
         rt_kprintf("Create task 1 failed\n");
         return -1;
     }
-    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle2 );
+    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     if (TaskHandle2 == NULL)
     {
         rt_kprintf("Create task 2 failed\n");

+ 1 - 1
test/test_semaphore_counting_static.c

@@ -106,7 +106,7 @@ int semaphore_counting_static()
         rt_kprintf("Create task 1 failed\n");
         return -1;
     }
-    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY - 1, &TaskHandle2 );
+    xTaskCreate( vTask2Code, "Task2", configMINIMAL_STACK_SIZE, NULL, TASK_PRIORITY + 1, &TaskHandle2 );
     if (TaskHandle2 == NULL)
     {
         rt_kprintf("Create task 2 failed\n");

+ 2 - 2
test/test_task.c

@@ -18,7 +18,7 @@ static StaticTask_t xTaskBuffer;
 StackType_t xStack[configMINIMAL_STACK_SIZE * 2];
 static BaseType_t num = 0;
 
-void vTask1Code(void * pvParameters)
+static void vTask1Code(void * pvParameters)
 {
     while (1)
     {
@@ -35,7 +35,7 @@ void vTask1Code(void * pvParameters)
     }
 }
 
-void vTask2Code(void * pvParameters)
+static void vTask2Code(void * pvParameters)
 {
     while (1)
     {