Merge branch 'zim-indexed-notifications-from-older-base' into 'master'

freertos: upgrade - indexed notifications

See merge request espressif/esp-idf!14910
This commit is contained in:
Zim Kalinowski
2021-09-06 04:46:23 +00:00
5 changed files with 794 additions and 299 deletions

View File

@@ -890,6 +890,14 @@
#define configUSE_TASK_NOTIFICATIONS 1 #define configUSE_TASK_NOTIFICATIONS 1
#endif #endif
#ifndef configTASK_NOTIFICATION_ARRAY_ENTRIES
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1
#endif
#if configTASK_NOTIFICATION_ARRAY_ENTRIES < 1
#error configTASK_NOTIFICATION_ARRAY_ENTRIES must be at least 1
#endif
#ifndef configUSE_POSIX_ERRNO #ifndef configUSE_POSIX_ERRNO
#define configUSE_POSIX_ERRNO 0 #define configUSE_POSIX_ERRNO 0
#endif #endif
@@ -1217,8 +1225,8 @@ typedef struct xSTATIC_TCB
struct _reent xDummy17; struct _reent xDummy17;
#endif #endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulDummy18; uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
uint8_t ucDummy19; uint8_t ucDummy19[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
#endif #endif
#if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 )
uint8_t uxDummy20; uint8_t uxDummy20;

View File

@@ -300,4 +300,6 @@ extern void vPortCleanUpTCB ( void *pxTCB );
#define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1
#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1
#endif /* FREERTOS_CONFIG_H */ #endif /* FREERTOS_CONFIG_H */

View File

@@ -60,7 +60,15 @@
#define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) #define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL )
#define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL ) #define tskMPU_REGION_DEVICE_MEMORY ( 1UL << 4UL )
/* The direct to task notification feature used to have only a single notification
* per task. Now there is an array of notifications per task that is dimensioned by
* configTASK_NOTIFICATION_ARRAY_ENTRIES. For backward compatibility, any use of the
* original direct to task notification defaults to using the first index in the
* array. */
#define tskDEFAULT_INDEX_TO_NOTIFY ( 0 )
#define tskNO_AFFINITY ( 0x7FFFFFFF ) #define tskNO_AFFINITY ( 0x7FFFFFFF )
/** /**
* task. h * task. h
* *
@@ -2111,11 +2119,23 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin
uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
/** /**
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * task. h
* function to be available. * <PRE>BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction );</PRE>
* <PRE>BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );</PRE>
* *
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
* "notification value", which is a 32-bit unsigned integer (uint32_t). *
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for these
* functions to be available.
*
* Sends a direct to task notification to a task, with an optional value and
* action.
*
* 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 * Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications * objects are queues, semaphores, mutexes and event groups. Task notifications
@@ -2123,28 +2143,46 @@ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
* an intermediary object. * an intermediary object.
* *
* A notification sent to a task can optionally perform an action, such as * A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way * update, overwrite or increment one of the task's notification values. In
* task notifications can be used to send data to a task, or be used as light * that way task notifications can be used to send data to a task, or be used as
* weight and fast binary or counting semaphores. * light weight and fast binary or counting semaphores.
* *
* A notification sent to a task will remain pending until it is cleared by the * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block
* already in the Blocked state to wait for a notification when the notification * to wait for a notification value to have a non-zero value. The task does
* arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
* notification to be pending, or ulTaskNotifyTake() to [optionally] block
* to wait for its notification value to have a non-zero value. The task does
* not consume any CPU time while it is in the Blocked state. * not consume any CPU time while it is in the Blocked state.
* *
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * 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. xTaskNotify() is the original API function, and remains backward
* compatible by always operating on the notification value at index 0 in the
* array. Calling xTaskNotify() is equivalent to calling xTaskNotifyIndexed()
* with the uxIndexToNotify parameter set to 0.
* *
* @param xTaskToNotify The handle of the task being notified. The handle to a * @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 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 * task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle(). * 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. xTaskNotify() does
* not have this parameter and always sends notifications to index 0.
*
* @param ulValue Data that can be sent with the notification. How the data is * @param ulValue Data that can be sent with the notification. How the data is
* used depends on the value of the eAction parameter. * used depends on the value of the eAction parameter.
* *
@@ -2152,54 +2190,96 @@ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION;
* value, if at all. Valid values for eAction are as follows: * value, if at all. Valid values for eAction are as follows:
* *
* eSetBits - * eSetBits -
* The task's notification value is bitwise ORed with ulValue. xTaskNofify() * The target notification value is bitwise ORed with ulValue.
* always returns pdPASS in this case. * xTaskNofifyIndexed() always returns pdPASS in this case.
* *
* eIncrement - * eIncrement -
* The task's notification value is incremented. ulValue is not used and * The target notification value is incremented. ulValue is not used and
* xTaskNotify() always returns pdPASS in this case. * xTaskNotifyIndexed() always returns pdPASS in this case.
* *
* eSetValueWithOverwrite - * eSetValueWithOverwrite -
* The task's notification value is set to the value of ulValue, even if the * The target notification value is set to the value of ulValue, even if the
* task being notified had not yet processed the previous notification (the * task being notified had not yet processed the previous notification at the
* task already had a notification pending). xTaskNotify() always returns * same array index (the task already had a notification pending at that index).
* pdPASS in this case. * xTaskNotifyIndexed() always returns pdPASS in this case.
* *
* eSetValueWithoutOverwrite - * eSetValueWithoutOverwrite -
* If the task being notified did not already have a notification pending then * If the task being notified did not already have a notification pending at the
* the task's notification value is set to ulValue and xTaskNotify() will * same array index then the target notification value is set to ulValue and
* return pdPASS. If the task being notified already had a notification * xTaskNotifyIndexed() will return pdPASS. If the task being notified already
* pending then no action is performed and pdFAIL is returned. * had a notification pending at the same array index then no action is
* performed and pdFAIL is returned.
* *
* eNoAction - * eNoAction -
* The task receives a notification without its notification value being * The task receives a notification at the specified array index without the
* updated. ulValue is not used and xTaskNotify() always returns pdPASS in * notification value at that index being updated. ulValue is not used and
* this case. * xTaskNotifyIndexed() always returns pdPASS in this case.
* *
* @param pulPreviousNotificationValue Can be used to pass out the subject * pulPreviousNotificationValue -
* task's notification value before any bits are modified by the notify * Can be used to pass out the subject task's notification value before any
* function. * bits are modified by the notify function.
* *
* @return Dependent on the value of eAction. See the description of the * @return Dependent on the value of eAction. See the description of the
* eAction parameter. * eAction parameter.
* *
* \defgroup xTaskNotifyIndexed xTaskNotifyIndexed
* \ingroup TaskNotifications * \ingroup TaskNotifications
*/ */
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) UBaseType_t uxIndexToNotify,
#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue ) PRIVILEGED_FUNCTION;
#define xTaskNotify( xTaskToNotify, ulValue, eAction ) \
xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulValue ), ( eAction ), NULL )
#define xTaskNotifyIndexed( xTaskToNotify, uxIndexToNotify, ulValue, eAction ) \
xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( ulValue ), ( eAction ), NULL )
/** /**
* Send task notification from an ISR. * task. h
* <PRE>BaseType_t xTaskNotifyAndQueryIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );</PRE>
* <PRE>BaseType_t xTaskNotifyAndQuery( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotifyValue );</PRE>
* *
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
* function to be available.
* *
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * xTaskNotifyAndQueryIndexed() performs the same operation as
* "notification value", which is a 32-bit unsigned integer (uint32_t). * 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.
* *
* A version of xTaskNotify() that can be used from an interrupt service routine * xTaskNotifyAndQuery() performs the same operation as xTaskNotify() with the
* (ISR). * 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
* <PRE>BaseType_t xTaskNotifyIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );</PRE>
* <PRE>BaseType_t xTaskNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, BaseType_t *pxHigherPriorityTaskWoken );</PRE>
*
* 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 * Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications * objects are queues, semaphores, mutexes and event groups. Task notifications
@@ -2207,22 +2287,40 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
* an intermediary object. * an intermediary object.
* *
* A notification sent to a task can optionally perform an action, such as * A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way * update, overwrite or increment one of the task's notification values. In
* task notifications can be used to send data to a task, or be used as light * that way task notifications can be used to send data to a task, or be used as
* weight and fast binary or counting semaphores. * light weight and fast binary or counting semaphores.
* *
* A notification sent to a task will remain pending until it is cleared by the * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block
* already in the Blocked state to wait for a notification when the notification * to wait for a notification value to have a non-zero value. The task does
* arrives then the task will automatically be removed from the Blocked state
* (unblocked) and the notification cleared.
*
* A task can use xTaskNotifyWait() to [optionally] block to wait for a
* notification to be pending, or ulTaskNotifyTake() to [optionally] block
* to wait for its notification value to have a non-zero value. The task does
* not consume any CPU time while it is in the Blocked state. * not consume any CPU time while it is in the Blocked state.
* *
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * 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 * @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 can be returned from the xTaskCreate() API function used to create the
@@ -2260,9 +2358,6 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
* updated. ulValue is not used and xTaskNotify() always returns pdPASS in * updated. ulValue is not used and xTaskNotify() always returns pdPASS in
* this case. * this case.
* *
* @param pulPreviousNotificationValue Can be used to pass out the subject task's
* notification value before any bits are modified by the notify function.
*
* @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set * @param pxHigherPriorityTaskWoken xTaskNotifyFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
* task to which the notification was sent to leave the Blocked state, and the * task to which the notification was sent to leave the Blocked state, and the
@@ -2275,20 +2370,68 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo
* @return Dependent on the value of eAction. See the description of the * @return Dependent on the value of eAction. See the description of the
* eAction parameter. * eAction parameter.
* *
* \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR
* \ingroup TaskNotifications * \ingroup TaskNotifications
*/ */
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) UBaseType_t uxIndexToNotify,
#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#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 ) )
/** /**
* Wait for task notification * task. h
* <PRE>BaseType_t xTaskNotifyAndQueryIndexedFromISR( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );</PRE>
* <PRE>BaseType_t xTaskNotifyAndQueryFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken );</PRE>
*
* 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
* <pre>
* BaseType_t xTaskNotifyWaitIndexed( UBaseType_t uxIndexToWaitOn, uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
*
* BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait );
* </pre>
*
* Waits for a direct to task notification to be pending at a given index within
* an array of direct to task notifications.
*
* See https://www.FreeRTOS.org/RTOS-task-notifications.html for details.
* *
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this
* function to be available. * function to be available.
* *
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * Each task has a private array of "notification values" (or 'notifications'),
* "notification value", which is a 32-bit unsigned integer (uint32_t). * 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 * Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications * objects are queues, semaphores, mutexes and event groups. Task notifications
@@ -2296,22 +2439,41 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal
* an intermediary object. * an intermediary object.
* *
* A notification sent to a task can optionally perform an action, such as * A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way * update, overwrite or increment one of the task's notification values. In
* task notifications can be used to send data to a task, or be used as light * that way task notifications can be used to send data to a task, or be used as
* weight and fast binary or counting semaphores. * light weight and fast binary or counting semaphores.
* *
* A notification sent to a task will remain pending until it is cleared by the * A notification sent to a task will remain pending until it is cleared by the
* task calling xTaskNotifyWait() or ulTaskNotifyTake(). If the task was * task calling xTaskNotifyWaitIndexed() or ulTaskNotifyTakeIndexed() (or their
* already in the Blocked state to wait for a notification when the notification * un-indexed equivalents). If the task was already in the Blocked state to
* arrives then the task will automatically be removed from the Blocked state * wait for a notification when the notification arrives then the task will
* (unblocked) and the notification cleared. * automatically be removed from the Blocked state (unblocked) and the
* notification cleared.
* *
* A task can use xTaskNotifyWait() to [optionally] block to wait for a * A task can use xTaskNotifyWaitIndexed() to [optionally] block to wait for a
* notification to be pending, or ulTaskNotifyTake() to [optionally] block * notification to be pending, or ulTaskNotifyTakeIndexed() to [optionally] block
* to wait for its notification value to have a non-zero value. The task does * 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. * not consume any CPU time while it is in the Blocked state.
* *
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * **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. xTaskNotifyWait() is the original API function, and remains backward
* compatible by always operating on the notification value at index 0 in the
* array. Calling xTaskNotifyWait() is equivalent to calling
* xTaskNotifyWaitIndexed() 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 received. uxIndexToWaitOn must be less than
* configTASK_NOTIFICATION_ARRAY_ENTRIES. xTaskNotifyWait() does
* not have this parameter and always waits for notifications on index 0.
* *
* @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value * @param ulBitsToClearOnEntry Bits that are set in ulBitsToClearOnEntry value
* will be cleared in the calling task's notification value before the task * will be cleared in the calling task's notification value before the task
@@ -2342,7 +2504,7 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal
* the Blocked state for a notification to be received, should a notification * the Blocked state for a notification to be received, should a notification
* not already be pending when xTaskNotifyWait() was called. The task * not already be pending when xTaskNotifyWait() was called. The task
* will not consume any processing time while it is in the Blocked state. This * 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 * is specified in kernel ticks, the macro pdMS_TO_TICSK( value_in_ms ) can be
* used to convert a time specified in milliseconds to a time specified in * used to convert a time specified in milliseconds to a time specified in
* ticks. * ticks.
* *
@@ -2350,18 +2512,37 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal
* already pending when xTaskNotifyWait was called) then pdPASS is * already pending when xTaskNotifyWait was called) then pdPASS is
* returned. Otherwise pdFAIL is returned. * returned. Otherwise pdFAIL is returned.
* *
* \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed
* \ingroup TaskNotifications * \ingroup TaskNotifications
*/ */
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWaitOn,
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t * pulNotificationValue,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
#define xTaskNotifyWait( ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \
xTaskGenericNotifyWait( tskDEFAULT_INDEX_TO_NOTIFY, ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) )
#define xTaskNotifyWaitIndexed( uxIndexToWaitOn, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait ) \
xTaskGenericNotifyWait( ( uxIndexToWaitOn ), ( ulBitsToClearOnEntry ), ( ulBitsToClearOnExit ), ( pulNotificationValue ), ( xTicksToWait ) )
/** /**
* Simplified macro for sending task notification. * task. h
* <PRE>BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify );</PRE>
* <PRE>BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );</PRE>
* *
* configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro * Sends a direct to task notification to a particular index in the target
* to be available. * task's notification array in a manner similar to giving a counting semaphore.
* *
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * See https://www.FreeRTOS.org/RTOS-task-notifications.html for more details.
* "notification value", which is a 32-bit unsigned integer (uint32_t). *
* 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 * Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications * objects are queues, semaphores, mutexes and event groups. Task notifications
@@ -2369,46 +2550,74 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea
* an intermediary object. * an intermediary object.
* *
* A notification sent to a task can optionally perform an action, such as * A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way * update, overwrite or increment one of the task's notification values. In
* task notifications can be used to send data to a task, or be used as light * that way task notifications can be used to send data to a task, or be used as
* weight and fast binary or counting semaphores. * light weight and fast binary or counting semaphores.
* *
* xTaskNotifyGive() is a helper macro intended for use when task notifications * xTaskNotifyGiveIndexed() is a helper macro intended for use when task
* are used as light weight and faster binary or counting semaphore equivalents. * notifications are used as light weight and faster binary or counting
* Actual FreeRTOS semaphores are given using the xSemaphoreGive() API function, * semaphore equivalents. Actual FreeRTOS semaphores are given using the
* the equivalent action that instead uses a task notification is * xSemaphoreGive() API function, the equivalent action that instead uses a task
* xTaskNotifyGive(). * notification is xTaskNotifyGiveIndexed().
* *
* When task notifications are being used as a binary or counting semaphore * When task notifications are being used as a binary or counting semaphore
* equivalent then the task being notified should wait for the notification * equivalent then the task being notified should wait for the notification
* using the ulTaskNotificationTake() API function rather than the * using the ulTaskNotificationTakeIndexed() API function rather than the
* xTaskNotifyWait() API function. * xTaskNotifyWaitIndexed() API function.
* *
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. * **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 * @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 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 * task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle(). * 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 * @return xTaskNotifyGive() is a macro that calls xTaskNotify() with the
* eAction parameter set to eIncrement - so pdPASS is always returned. * eAction parameter set to eIncrement - so pdPASS is always returned.
* *
* \defgroup xTaskNotifyGiveIndexed xTaskNotifyGiveIndexed
* \ingroup TaskNotifications * \ingroup TaskNotifications
*/ */
#define xTaskNotifyGive( xTaskToNotify ) xTaskGenericNotify( ( xTaskToNotify ), ( 0 ), eIncrement, NULL ) #define xTaskNotifyGive( xTaskToNotify ) \
xTaskGenericNotify( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( 0 ), eIncrement, NULL )
#define xTaskNotifyGiveIndexed( xTaskToNotify, uxIndexToNotify ) \
xTaskGenericNotify( ( xTaskToNotify ), ( uxIndexToNotify ), ( 0 ), eIncrement, NULL )
/** /**
* Simplified macro for sending task notification from ISR. * task. h
* <PRE>void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken );</PRE>
* <PRE>void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );</PRE>
*
* 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 * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro
* to be available. * to be available.
* *
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * Each task has a private array of "notification values" (or 'notifications'),
* "notification value", which is a 32-bit unsigned integer (uint32_t). * each of which is a 32-bit unsigned integer (uint32_t). The constant
* * configTASK_NOTIFICATION_ARRAY_ENTRIES sets the number of indexes in the
* A version of xTaskNotifyGive() that can be called from an interrupt service * array, and (for backward compatibility) defaults to 1 if left undefined.
* routine (ISR). * 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 * Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications * objects are queues, semaphores, mutexes and event groups. Task notifications
@@ -2416,28 +2625,46 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea
* an intermediary object. * an intermediary object.
* *
* A notification sent to a task can optionally perform an action, such as * A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way * update, overwrite or increment one of the task's notification values. In
* task notifications can be used to send data to a task, or be used as light * that way task notifications can be used to send data to a task, or be used as
* weight and fast binary or counting semaphores. * light weight and fast binary or counting semaphores.
* *
* vTaskNotifyGiveFromISR() is intended for use when task notifications are * vTaskNotifyGiveIndexedFromISR() is intended for use when task notifications
* used as light weight and faster binary or counting semaphore equivalents. * are used as light weight and faster binary or counting semaphore equivalents.
* Actual FreeRTOS semaphores are given from an ISR using the * Actual FreeRTOS semaphores are given from an ISR using the
* xSemaphoreGiveFromISR() API function, the equivalent action that instead uses * xSemaphoreGiveFromISR() API function, the equivalent action that instead uses
* a task notification is vTaskNotifyGiveFromISR(). * a task notification is vTaskNotifyGiveIndexedFromISR().
* *
* When task notifications are being used as a binary or counting semaphore * When task notifications are being used as a binary or counting semaphore
* equivalent then the task being notified should wait for the notification * equivalent then the task being notified should wait for the notification
* using the ulTaskNotificationTake() API function rather than the * using the ulTaskNotificationTakeIndexed() API function rather than the
* xTaskNotifyWait() API function. * xTaskNotifyWaitIndexed() API function.
* *
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for more details. * **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 * @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 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 * task, and the handle of the currently running task can be obtained by calling
* xTaskGetCurrentTaskHandle(). * 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 * @param pxHigherPriorityTaskWoken vTaskNotifyGiveFromISR() will set
* *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused the
* task to which the notification was sent to leave the Blocked state, and the * task to which the notification was sent to leave the Blocked state, and the
@@ -2447,18 +2674,38 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea
* requested from an ISR is dependent on the port - see the documentation page * requested from an ISR is dependent on the port - see the documentation page
* for the port in use. * for the port in use.
* *
* \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR
* \ingroup TaskNotifications * \ingroup TaskNotifications
*/ */
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
BaseType_t * pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION;
#define vTaskNotifyGiveFromISR( xTaskToNotify, pxHigherPriorityTaskWoken ) \
vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( pxHigherPriorityTaskWoken ) );
#define vTaskNotifyGiveIndexedFromISR( xTaskToNotify, uxIndexToNotify, pxHigherPriorityTaskWoken ) \
vTaskGenericNotifyGiveFromISR( ( xTaskToNotify ), ( uxIndexToNotify ), ( pxHigherPriorityTaskWoken ) );
/** /**
* Simplified macro for receiving task notification. * task. h
* <pre>
* uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
*
* uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
* </pre>
*
* 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 * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this
* function to be available. * function to be available.
* *
* When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private * Each task has a private array of "notification values" (or 'notifications'),
* "notification value", which is a 32-bit unsigned integer (uint32_t). * 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 * Events can be sent to a task using an intermediary object. Examples of such
* objects are queues, semaphores, mutexes and event groups. Task notifications * objects are queues, semaphores, mutexes and event groups. Task notifications
@@ -2466,35 +2713,54 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri
* an intermediary object. * an intermediary object.
* *
* A notification sent to a task can optionally perform an action, such as * A notification sent to a task can optionally perform an action, such as
* update, overwrite or increment the task's notification value. In that way * update, overwrite or increment one of the task's notification values. In
* task notifications can be used to send data to a task, or be used as light * that way task notifications can be used to send data to a task, or be used as
* weight and fast binary or counting semaphores. * light weight and fast binary or counting semaphores.
* *
* ulTaskNotifyTake() is intended for use when a task notification is used as a * ulTaskNotifyTakeIndexed() is intended for use when a task notification is
* faster and lighter weight binary or counting semaphore alternative. Actual * used as a faster and lighter weight binary or counting semaphore alternative.
* FreeRTOS semaphores are taken using the xSemaphoreTake() API function, the * Actual FreeRTOS semaphores are taken using the xSemaphoreTake() API function,
* equivalent action that instead uses a task notification is * the equivalent action that instead uses a task notification is
* ulTaskNotifyTake(). * ulTaskNotifyTakeIndexed().
* *
* When a task is using its notification value as a binary or counting semaphore * When a task is using its notification value as a binary or counting semaphore
* other tasks should send notifications to it using the xTaskNotifyGive() * other tasks should send notifications to it using the xTaskNotifyGiveIndexed()
* macro, or xTaskNotify() function with the eAction parameter set to * macro, or xTaskNotifyIndex() function with the eAction parameter set to
* eIncrement. * eIncrement.
* *
* ulTaskNotifyTake() can either clear the task's notification value to * ulTaskNotifyTakeIndexed() can either clear the task's notification value at
* zero on exit, in which case the notification value acts like a binary * the array index specified by the uxIndexToWaitOn parameter to zero on exit,
* semaphore, or decrement the task's notification value on exit, in which case * in which case the notification value acts like a binary semaphore, or
* the notification value acts like a counting semaphore. * decrement the notification value on exit, in which case the notification
* value acts like a counting semaphore.
* *
* A task can use ulTaskNotifyTake() to [optionally] block to wait for a * A task can use ulTaskNotifyTakeIndexed() to [optionally] block to wait for
* the task's notification value to be non-zero. The task does not consume any * the task's notification value to be non-zero. The task does not consume any
* CPU time while it is in the Blocked state. * CPU time while it is in the Blocked state.
* *
* Where as xTaskNotifyWait() will return when a notification is pending, * Where as xTaskNotifyWaitIndexed() will return when a notification is pending,
* ulTaskNotifyTake() will return when the task's notification value is * ulTaskNotifyTakeIndexed() will return when the task's notification value is
* not zero. * not zero.
* *
* See http://www.FreeRTOS.org/RTOS-task-notifications.html for details. * **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 * @param xClearCountOnExit if xClearCountOnExit is pdFALSE then the task's
* notification value is decremented when the function exits. In this way the * notification value is decremented when the function exits. In this way the
@@ -2508,29 +2774,153 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri
* should the count not already be greater than zero when * should the count not already be greater than zero when
* ulTaskNotifyTake() was called. The task will not consume any processing * ulTaskNotifyTake() was called. The task will not consume any processing
* time while it is in the Blocked state. This is specified in kernel ticks, * 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 * the macro pdMS_TO_TICSK( value_in_ms ) can be used to convert a time
* specified in milliseconds to a time specified in ticks. * specified in milliseconds to a time specified in ticks.
* *
* @return The task's notification count before it is either cleared to zero or * @return The task's notification count before it is either cleared to zero or
* decremented (see the xClearCountOnExit parameter). * decremented (see the xClearCountOnExit parameter).
* *
* \defgroup ulTaskNotifyTakeIndexed ulTaskNotifyTakeIndexed
* \ingroup TaskNotifications * \ingroup TaskNotifications
*/ */
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) PRIVILEGED_FUNCTION; uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWaitOn,
BaseType_t xClearCountOnExit,
TickType_t xTicksToWait ) PRIVILEGED_FUNCTION;
#define ulTaskNotifyTake( xClearCountOnExit, xTicksToWait ) \
ulTaskGenericNotifyTake( ( tskDEFAULT_INDEX_TO_NOTIFY ), ( xClearCountOnExit ), ( xTicksToWait ) )
#define ulTaskNotifyTakeIndexed( uxIndexToWaitOn, xClearCountOnExit, xTicksToWait ) \
ulTaskGenericNotifyTake( ( uxIndexToWaitOn ), ( xClearCountOnExit ), ( xTicksToWait ) )
/** /**
* task. h
* <pre>
* BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear );
* *
* If the notification state of the task referenced by the handle xTask is * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
* eNotified, then set the task's notification state to eNotWaitingNotification. * </pre>
* The task's notification value is not altered. Set xTask to NULL to clear the *
* notification state of the calling task. * 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 * @return pdTRUE if the task's notification state was set to
* eNotWaitingNotification, otherwise pdFALSE. * eNotWaitingNotification, otherwise pdFALSE.
* *
* \defgroup xTaskNotifyStateClearIndexed xTaskNotifyStateClearIndexed
* \ingroup TaskNotifications * \ingroup TaskNotifications
*/ */
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ); BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
UBaseType_t uxIndexToClear ) PRIVILEGED_FUNCTION;
#define xTaskNotifyStateClear( xTask ) \
xTaskGenericNotifyStateClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ) )
#define xTaskNotifyStateClearIndexed( xTask, uxIndexToClear ) \
xTaskGenericNotifyStateClear( ( xTask ), ( uxIndexToClear ) )
/**
* task. h
* <pre>
* uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear );
*
* uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear );
* </pre>
*
* 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 ) PRIVILEGED_FUNCTION;
#define ulTaskNotifyValueClear( xTask, ulBitsToClear ) \
ulTaskGenericNotifyValueClear( ( xTask ), ( tskDEFAULT_INDEX_TO_NOTIFY ), ( ulBitsToClear ) )
#define ulTaskNotifyValueClearIndexed( xTask, uxIndexToClear, ulBitsToClear ) \
ulTaskGenericNotifyValueClear( ( xTask ), ( uxIndexToClear ), ( ulBitsToClear ) )
/*----------------------------------------------------------- /*-----------------------------------------------------------
* SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES * SCHEDULER INTERNALS AVAILABLE FOR PORTING PURPOSES

View File

@@ -40,7 +40,9 @@ entries:
tasks: xTaskResumeAll (default) tasks: xTaskResumeAll (default)
tasks: uxTaskResetEventItemValue (default) tasks: uxTaskResetEventItemValue (default)
tasks: ulTaskNotifyTake (default) tasks: ulTaskNotifyTake (default)
tasks: ulTaskGenericNotifyTake (default)
tasks: xTaskNotifyWait (default) tasks: xTaskNotifyWait (default)
tasks: xTaskGenericNotifyWait (default)
tasks: xTaskGenericNotify (default) tasks: xTaskGenericNotify (default)
tasks: eTaskGetState (default) tasks: eTaskGetState (default)
tasks: pxTaskGetStackStart (default) tasks: pxTaskGetStackStart (default)

View File

@@ -333,8 +333,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to
#endif #endif
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
volatile uint32_t ulNotifiedValue; volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
volatile uint8_t ucNotifyState; volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ];
#endif #endif
/* See the comments in FreeRTOS.h with the definition of /* See the comments in FreeRTOS.h with the definition of
@@ -1090,8 +1090,8 @@ static void prvInitialiseNewTask( TaskFunction_t pxTaskCode,
#if ( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
{ {
pxNewTCB->ulNotifiedValue = 0; memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) );
pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) );
} }
#endif #endif
@@ -1630,19 +1630,24 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB,
* indefinitely? */ * indefinitely? */
if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ) if( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL )
{ {
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
{ {
BaseType_t x;
/* The task does not appear on the event list item of /* The task does not appear on the event list item of
* and of the RTOS objects, but could still be in the * and of the RTOS objects, but could still be in the
* blocked state if it is waiting on its notification * blocked state if it is waiting on its notification
* rather than waiting on an object. */ * rather than waiting on an object. If not, is
if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ) * suspended. */
eReturn = eSuspended;
for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
{ {
eReturn = eBlocked; if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
} {
else eReturn = eBlocked;
{ break;
eReturn = eSuspended; }
} }
} }
#else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
@@ -1972,16 +1977,21 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB,
vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) );
curTCB = pxCurrentTCB[ xPortGetCoreID() ]; curTCB = pxCurrentTCB[ xPortGetCoreID() ];
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
{ {
if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ) BaseType_t x;
for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ )
{ {
/* The task was blocked to wait for a notification, but is if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION )
* now suspended, so no notification was received. */ {
pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; /* The task was blocked to wait for a notification, but is
* now suspended, so no notification was received. */
pxTCB->ucNotifyState[ x ] = taskNOT_WAITING_NOTIFICATION;
}
} }
} }
#endif #endif /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@@ -5241,19 +5251,33 @@ TickType_t uxTaskResetEventItemValue( void )
#endif /* configUSE_MUTEXES */ #endif /* configUSE_MUTEXES */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait ) #ifdef ESP_PLATFORM // IDF-3851
// included here for backward binary compatibility
#undef ulTaskNotifyTake
uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit,
TickType_t xTicksToWait )
{ {
uint32_t ulReturn; return ulTaskGenericNotifyTake(tskDEFAULT_INDEX_TO_NOTIFY, xClearCountOnExit, xTicksToWait);
}
#endif // ESP-PLATFORM
uint32_t ulTaskGenericNotifyTake( UBaseType_t uxIndexToWait,
BaseType_t xClearCountOnExit,
TickType_t xTicksToWait )
{
uint32_t ulReturn;
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
/* Only block if the notification count is not already non-zero. */ /* Only block if the notification count is not already non-zero. */
if( pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue == 0UL ) if( pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] == 0UL )
{ {
/* Mark this task as waiting for a notification. */ /* Mark this task as waiting for a notification. */
pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
if( xTicksToWait > ( TickType_t ) 0 ) if( xTicksToWait > ( TickType_t ) 0 )
{ {
@@ -5261,9 +5285,9 @@ TickType_t uxTaskResetEventItemValue( void )
traceTASK_NOTIFY_TAKE_BLOCK(); traceTASK_NOTIFY_TAKE_BLOCK();
/* All ports are written to allow a yield in a critical /* All ports are written to allow a yield in a critical
section (some will yield immediately, others wait until the * section (some will yield immediately, others wait until the
critical section exits) - but it is not something that * critical section exits) - but it is not something that
application code should ever do. */ * application code should ever do. */
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else else
@@ -5281,17 +5305,17 @@ TickType_t uxTaskResetEventItemValue( void )
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
traceTASK_NOTIFY_TAKE(); traceTASK_NOTIFY_TAKE();
ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ];
if( ulReturn != 0UL ) if( ulReturn != 0UL )
{ {
if( xClearCountOnExit != pdFALSE ) if( xClearCountOnExit != pdFALSE )
{ {
pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = 0UL; pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = 0UL;
} }
else else
{ {
pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = ulReturn - ( uint32_t ) 1; pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1;
} }
} }
else else
@@ -5299,7 +5323,7 @@ TickType_t uxTaskResetEventItemValue( void )
mtCOVERAGE_TEST_MARKER(); mtCOVERAGE_TEST_MARKER();
} }
pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@@ -5309,24 +5333,41 @@ TickType_t uxTaskResetEventItemValue( void )
#endif /* configUSE_TASK_NOTIFICATIONS */ #endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClearOnExit, uint32_t *pulNotificationValue, TickType_t xTicksToWait ) #ifdef ESP_PLATFORM // IDF-3851
// included for backward compatibility
#undef xTaskNotifyWait
BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t * pulNotificationValue,
TickType_t xTicksToWait )
{ {
BaseType_t xReturn; return xTaskGenericNotifyWait(tskDEFAULT_INDEX_TO_NOTIFY, ulBitsToClearOnEntry, ulBitsToClearOnExit, pulNotificationValue, xTicksToWait);
}
#endif // ESP-PLATFORM
BaseType_t xTaskGenericNotifyWait( UBaseType_t uxIndexToWait,
uint32_t ulBitsToClearOnEntry,
uint32_t ulBitsToClearOnExit,
uint32_t * pulNotificationValue,
TickType_t xTicksToWait )
{
BaseType_t xReturn;
configASSERT( uxIndexToWait < configTASK_NOTIFICATION_ARRAY_ENTRIES );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
/* Only block if a notification is not already pending. */ /* Only block if a notification is not already pending. */
if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
{ {
/* Clear bits in the task's notification value as bits may get /* Clear bits in the task's notification value as bits may get
set by the notifying task or interrupt. This can be used to * set by the notifying task or interrupt. This can be used to
clear the value to zero. */ * clear the value to zero. */
pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnEntry; pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry;
/* Mark this task as waiting for a notification. */ /* Mark this task as waiting for a notification. */
pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION;
if( xTicksToWait > ( TickType_t ) 0 ) if( xTicksToWait > ( TickType_t ) 0 )
{ {
@@ -5334,9 +5375,9 @@ TickType_t uxTaskResetEventItemValue( void )
traceTASK_NOTIFY_WAIT_BLOCK(); traceTASK_NOTIFY_WAIT_BLOCK();
/* All ports are written to allow a yield in a critical /* All ports are written to allow a yield in a critical
section (some will yield immediately, others wait until the * section (some will yield immediately, others wait until the
critical section exits) - but it is not something that * critical section exits) - but it is not something that
application code should ever do. */ * application code should ever do. */
portYIELD_WITHIN_API(); portYIELD_WITHIN_API();
} }
else else
@@ -5358,15 +5399,15 @@ TickType_t uxTaskResetEventItemValue( void )
if( pulNotificationValue != NULL ) if( pulNotificationValue != NULL )
{ {
/* Output the current notification value, which may or may not /* Output the current notification value, which may or may not
have changed. */ * have changed. */
*pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; *pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ];
} }
/* If ucNotifyValue is set then either the task never entered the /* If ucNotifyValue is set then either the task never entered the
blocked state (because a notification was already pending) or the * blocked state (because a notification was already pending) or the
task unblocked because of a notification. Otherwise the task * task unblocked because of a notification. Otherwise the task
unblocked because of a timeout. */ * unblocked because of a timeout. */
if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED )
{ {
/* A notification was not received. */ /* A notification was not received. */
xReturn = pdFALSE; xReturn = pdFALSE;
@@ -5374,12 +5415,12 @@ TickType_t uxTaskResetEventItemValue( void )
else else
{ {
/* A notification was already pending or a notification was /* A notification was already pending or a notification was
received while the task was waiting. */ * received while the task was waiting. */
pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnExit; pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit;
xReturn = pdTRUE; xReturn = pdTRUE;
} }
pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION;
} }
taskEXIT_CRITICAL(); taskEXIT_CRITICAL();
@@ -5389,14 +5430,19 @@ TickType_t uxTaskResetEventItemValue( void )
#endif /* configUSE_TASK_NOTIFICATIONS */ #endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
BaseType_t xReturn = pdPASS; BaseType_t xReturn = pdPASS;
uint8_t ucOriginalNotifyState; uint8_t ucOriginalNotifyState;
configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
configASSERT( xTaskToNotify ); configASSERT( xTaskToNotify );
pxTCB = xTaskToNotify; pxTCB = xTaskToNotify;
@@ -5404,49 +5450,53 @@ TickType_t uxTaskResetEventItemValue( void )
{ {
if( pulPreviousNotificationValue != NULL ) if( pulPreviousNotificationValue != NULL )
{ {
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue; *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
} }
ucOriginalNotifyState = pxTCB->ucNotifyState; ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
switch( eAction ) switch( eAction )
{ {
case eSetBits : case eSetBits:
pxTCB->ulNotifiedValue |= ulValue; pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
break; break;
case eIncrement : case eIncrement:
( pxTCB->ulNotifiedValue )++; ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
break; break;
case eSetValueWithOverwrite : case eSetValueWithOverwrite:
pxTCB->ulNotifiedValue = ulValue; pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
break; break;
case eSetValueWithoutOverwrite : case eSetValueWithoutOverwrite:
if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{ {
pxTCB->ulNotifiedValue = ulValue; pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
} }
else else
{ {
/* The value could not be written to the task. */ /* The value could not be written to the task. */
xReturn = pdFAIL; xReturn = pdFAIL;
} }
break; break;
case eNoAction: case eNoAction:
/* The task is being notified without its notify value being /* The task is being notified without its notify value being
updated. */ * updated. */
break; break;
default: default:
/* Should not get here if all enums are handled. /* Should not get here if all enums are handled.
Artificially force an assert by testing a value the * Artificially force an assert by testing a value the
compiler can't assume is const. */ * compiler can't assume is const. */
configASSERT( pxTCB->ulNotifiedValue == ~0UL ); configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL );
break; break;
} }
@@ -5454,7 +5504,7 @@ TickType_t uxTaskResetEventItemValue( void )
traceTASK_NOTIFY(); traceTASK_NOTIFY();
/* If the task is in the blocked state specifically to wait for a /* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */ * notification then unblock it now. */
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{ {
( void ) uxListRemove( &( pxTCB->xStateListItem ) ); ( void ) uxListRemove( &( pxTCB->xStateListItem ) );
@@ -5463,20 +5513,20 @@ TickType_t uxTaskResetEventItemValue( void )
/* The task should not have been on an event list. */ /* The task should not have been on an event list. */
configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL );
#if( configUSE_TICKLESS_IDLE != 0 ) #if ( configUSE_TICKLESS_IDLE != 0 )
{ {
/* If a task is blocked waiting for a notification then /* If a task is blocked waiting for a notification then
xNextTaskUnblockTime might be set to the blocked task's time * xNextTaskUnblockTime might be set to the blocked task's time
out time. If the task is unblocked for a reason other than * out time. If the task is unblocked for a reason other than
a timeout xNextTaskUnblockTime is normally left unchanged, * a timeout xNextTaskUnblockTime is normally left unchanged,
because it will automatically get reset to a new value when * because it will automatically get reset to a new value when
the tick count equals xNextTaskUnblockTime. However if * the tick count equals xNextTaskUnblockTime. However if
tickless idling is used it might be more important to enter * tickless idling is used it might be more important to enter
sleep mode at the earliest possible time - so reset * sleep mode at the earliest possible time - so reset
xNextTaskUnblockTime here to ensure it is updated at the * xNextTaskUnblockTime here to ensure it is updated at the
earliest possible time. */ * earliest possible time. */
prvResetNextTaskUnblockTime(); prvResetNextTaskUnblockTime();
} }
#endif #endif
if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
@@ -5507,32 +5557,38 @@ TickType_t uxTaskResetEventItemValue( void )
#endif /* configUSE_TASK_NOTIFICATIONS */ #endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
uint32_t ulValue,
eNotifyAction eAction,
uint32_t * pulPreviousNotificationValue,
BaseType_t * pxHigherPriorityTaskWoken )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
uint8_t ucOriginalNotifyState; uint8_t ucOriginalNotifyState;
BaseType_t xReturn = pdPASS; BaseType_t xReturn = pdPASS;
configASSERT( xTaskToNotify ); configASSERT( xTaskToNotify );
configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
/* RTOS ports that support interrupt nesting have the concept of a /* RTOS ports that support interrupt nesting have the concept of a
maximum system call (or maximum API call) interrupt priority. * maximum system call (or maximum API call) interrupt priority.
Interrupts that are above the maximum system call priority are keep * Interrupts that are above the maximum system call priority are keep
permanently enabled, even when the RTOS kernel is in a critical section, * permanently enabled, even when the RTOS kernel is in a critical section,
but cannot make any calls to FreeRTOS API functions. If configASSERT() * but cannot make any calls to FreeRTOS API functions. If configASSERT()
is defined in FreeRTOSConfig.h then * is defined in FreeRTOSConfig.h then
portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has * failure if a FreeRTOS API function is called from an interrupt that has
been assigned a priority above the configured maximum system call * been assigned a priority above the configured maximum system call
priority. Only FreeRTOS functions that end in FromISR can be called * priority. Only FreeRTOS functions that end in FromISR can be called
from interrupts that have been assigned a priority at or (logically) * from interrupts that have been assigned a priority at or (logically)
below the maximum system call interrupt priority. FreeRTOS maintains a * below the maximum system call interrupt priority. FreeRTOS maintains a
separate interrupt safe API to ensure interrupt entry is as fast and as * separate interrupt safe API to ensure interrupt entry is as fast and as
simple as possible. More information (albeit Cortex-M specific) is * simple as possible. More information (albeit Cortex-M specific) is
provided on the following link: * provided on the following link:
http://www.freertos.org/RTOS-Cortex-M3-M4.html */ * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
pxTCB = xTaskToNotify; pxTCB = xTaskToNotify;
@@ -5541,55 +5597,59 @@ TickType_t uxTaskResetEventItemValue( void )
{ {
if( pulPreviousNotificationValue != NULL ) if( pulPreviousNotificationValue != NULL )
{ {
*pulPreviousNotificationValue = pxTCB->ulNotifiedValue; *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ];
} }
ucOriginalNotifyState = pxTCB->ucNotifyState; ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
switch( eAction ) switch( eAction )
{ {
case eSetBits : case eSetBits:
pxTCB->ulNotifiedValue |= ulValue; pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue;
break; break;
case eIncrement : case eIncrement:
( pxTCB->ulNotifiedValue )++; ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
break; break;
case eSetValueWithOverwrite : case eSetValueWithOverwrite:
pxTCB->ulNotifiedValue = ulValue; pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
break; break;
case eSetValueWithoutOverwrite : case eSetValueWithoutOverwrite:
if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED )
{ {
pxTCB->ulNotifiedValue = ulValue; pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue;
} }
else else
{ {
/* The value could not be written to the task. */ /* The value could not be written to the task. */
xReturn = pdFAIL; xReturn = pdFAIL;
} }
break; break;
case eNoAction : case eNoAction:
/* The task is being notified without its notify value being /* The task is being notified without its notify value being
updated. */ * updated. */
break; break;
default: default:
/* Should not get here if all enums are handled. /* Should not get here if all enums are handled.
Artificially force an assert by testing a value the * Artificially force an assert by testing a value the
compiler can't assume is const. */ * compiler can't assume is const. */
configASSERT( pxTCB->ulNotifiedValue == ~0UL ); configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL );
break; break;
} }
traceTASK_NOTIFY_FROM_ISR(); traceTASK_NOTIFY_FROM_ISR();
/* If the task is in the blocked state specifically to wait for a /* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */ * notification then unblock it now. */
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{ {
/* The task should not have been on an event list. */ /* The task should not have been on an event list. */
@@ -5603,14 +5663,14 @@ TickType_t uxTaskResetEventItemValue( void )
else else
{ {
/* The delayed and ready lists cannot be accessed, so hold /* The delayed and ready lists cannot be accessed, so hold
this task pending until the scheduler is resumed. */ * this task pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) );
} }
if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{ {
/* The notified task has a priority above the currently /* The notified task has a priority above the currently
executing task so a yield is required. */ * executing task so a yield is required. */
if( pxHigherPriorityTaskWoken != NULL ) if( pxHigherPriorityTaskWoken != NULL )
{ {
*pxHigherPriorityTaskWoken = pdTRUE; *pxHigherPriorityTaskWoken = pdTRUE;
@@ -5637,47 +5697,50 @@ TickType_t uxTaskResetEventItemValue( void )
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if( configUSE_TASK_NOTIFICATIONS == 1 )
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPriorityTaskWoken ) void vTaskGenericNotifyGiveFromISR( TaskHandle_t xTaskToNotify,
UBaseType_t uxIndexToNotify,
BaseType_t * pxHigherPriorityTaskWoken )
{ {
TCB_t * pxTCB; TCB_t * pxTCB;
uint8_t ucOriginalNotifyState; uint8_t ucOriginalNotifyState;
configASSERT( xTaskToNotify ); configASSERT( xTaskToNotify );
configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES );
/* RTOS ports that support interrupt nesting have the concept of a /* RTOS ports that support interrupt nesting have the concept of a
maximum system call (or maximum API call) interrupt priority. * maximum system call (or maximum API call) interrupt priority.
Interrupts that are above the maximum system call priority are keep * Interrupts that are above the maximum system call priority are keep
permanently enabled, even when the RTOS kernel is in a critical section, * permanently enabled, even when the RTOS kernel is in a critical section,
but cannot make any calls to FreeRTOS API functions. If configASSERT() * but cannot make any calls to FreeRTOS API functions. If configASSERT()
is defined in FreeRTOSConfig.h then * is defined in FreeRTOSConfig.h then
portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion
failure if a FreeRTOS API function is called from an interrupt that has * failure if a FreeRTOS API function is called from an interrupt that has
been assigned a priority above the configured maximum system call * been assigned a priority above the configured maximum system call
priority. Only FreeRTOS functions that end in FromISR can be called * priority. Only FreeRTOS functions that end in FromISR can be called
from interrupts that have been assigned a priority at or (logically) * from interrupts that have been assigned a priority at or (logically)
below the maximum system call interrupt priority. FreeRTOS maintains a * below the maximum system call interrupt priority. FreeRTOS maintains a
separate interrupt safe API to ensure interrupt entry is as fast and as * separate interrupt safe API to ensure interrupt entry is as fast and as
simple as possible. More information (albeit Cortex-M specific) is * simple as possible. More information (albeit Cortex-M specific) is
provided on the following link: * provided on the following link:
http://www.freertos.org/RTOS-Cortex-M3-M4.html */ * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */
portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); portASSERT_IF_INTERRUPT_PRIORITY_INVALID();
pxTCB = xTaskToNotify; pxTCB = xTaskToNotify;
taskENTER_CRITICAL_ISR(); taskENTER_CRITICAL_ISR();
{ {
ucOriginalNotifyState = pxTCB->ucNotifyState; ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ];
pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED;
/* 'Giving' is equivalent to incrementing a count in a counting /* 'Giving' is equivalent to incrementing a count in a counting
semaphore. */ * semaphore. */
( pxTCB->ulNotifiedValue )++; ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++;
traceTASK_NOTIFY_GIVE_FROM_ISR(); traceTASK_NOTIFY_GIVE_FROM_ISR();
/* If the task is in the blocked state specifically to wait for a /* If the task is in the blocked state specifically to wait for a
notification then unblock it now. */ * notification then unblock it now. */
if( ucOriginalNotifyState == taskWAITING_NOTIFICATION ) if( ucOriginalNotifyState == taskWAITING_NOTIFICATION )
{ {
/* The task should not have been on an event list. */ /* The task should not have been on an event list. */
@@ -5691,7 +5754,7 @@ TickType_t uxTaskResetEventItemValue( void )
else else
{ {
/* The delayed and ready lists cannot be accessed, so hold /* The delayed and ready lists cannot be accessed, so hold
this task pending until the scheduler is resumed. */ * this task pending until the scheduler is resumed. */
vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) ); vListInsertEnd( &( xPendingReadyList[xPortGetCoreID()] ), &( pxTCB->xEventListItem ) );
} }
@@ -5699,7 +5762,7 @@ TickType_t uxTaskResetEventItemValue( void )
if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority )
{ {
/* The notified task has a priority above the currently /* The notified task has a priority above the currently
executing task so a yield is required. */ * executing task so a yield is required. */
if( pxHigherPriorityTaskWoken != NULL ) if( pxHigherPriorityTaskWoken != NULL )
{ {
*pxHigherPriorityTaskWoken = pdTRUE; *pxHigherPriorityTaskWoken = pdTRUE;
@@ -5720,25 +5783,27 @@ TickType_t uxTaskResetEventItemValue( void )
} }
#endif /* configUSE_TASK_NOTIFICATIONS */ #endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( configUSE_TASK_NOTIFICATIONS == 1 ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask ) BaseType_t xTaskGenericNotifyStateClear( TaskHandle_t xTask,
UBaseType_t uxIndexToClear )
{ {
TCB_t *pxTCB; TCB_t * pxTCB;
BaseType_t xReturn; BaseType_t xReturn;
configASSERT( uxIndexToClear < configTASK_NOTIFICATION_ARRAY_ENTRIES );
/* If null is passed in here then it is the calling task that is having /* If null is passed in here then it is the calling task that is having
its notification state cleared. */ * its notification state cleared. */
pxTCB = prvGetTCBFromHandle( xTask ); pxTCB = prvGetTCBFromHandle( xTask );
taskENTER_CRITICAL(); taskENTER_CRITICAL();
{ {
if( pxTCB->ucNotifyState == taskNOTIFICATION_RECEIVED ) if( pxTCB->ucNotifyState[ uxIndexToClear ] == taskNOTIFICATION_RECEIVED )
{ {
pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; pxTCB->ucNotifyState[ uxIndexToClear ] = taskNOT_WAITING_NOTIFICATION;
xReturn = pdPASS; xReturn = pdPASS;
} }
else else
@@ -5754,7 +5819,35 @@ TickType_t uxTaskResetEventItemValue( void )
#endif /* configUSE_TASK_NOTIFICATIONS */ #endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/ /*-----------------------------------------------------------*/
#if( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) ) #if ( configUSE_TASK_NOTIFICATIONS == 1 )
uint32_t ulTaskGenericNotifyValueClear( TaskHandle_t xTask,
UBaseType_t uxIndexToClear,
uint32_t ulBitsToClear )
{
TCB_t * pxTCB;
uint32_t ulReturn;
/* If null is passed in here then it is the calling task that is having
* its notification state cleared. */
pxTCB = prvGetTCBFromHandle( xTask );
taskENTER_CRITICAL();
{
/* Return the notification as it was before the bits were cleared,
* then clear the bit mask. */
ulReturn = pxTCB->ulNotifiedValue[ uxIndexToClear ];
pxTCB->ulNotifiedValue[ uxIndexToClear ] &= ~ulBitsToClear;
}
taskEXIT_CRITICAL();
return ulReturn;
}
#endif /* configUSE_TASK_NOTIFICATIONS */
/*-----------------------------------------------------------*/
#if ( ( configGENERATE_RUN_TIME_STATS == 1 ) && ( INCLUDE_xTaskGetIdleTaskHandle == 1 ) )
uint32_t ulTaskGetIdleRunTimeCounter( void ) uint32_t ulTaskGetIdleRunTimeCounter( void )
{ {