diff --git a/components/freertos/include/freertos/FreeRTOS.h b/components/freertos/include/freertos/FreeRTOS.h index c05c125380..d354bbedb3 100644 --- a/components/freertos/include/freertos/FreeRTOS.h +++ b/components/freertos/include/freertos/FreeRTOS.h @@ -890,6 +890,14 @@ #define configUSE_TASK_NOTIFICATIONS 1 #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 #define configUSE_POSIX_ERRNO 0 #endif @@ -1217,8 +1225,8 @@ typedef struct xSTATIC_TCB struct _reent xDummy17; #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - uint32_t ulDummy18; - uint8_t ucDummy19; + uint32_t ulDummy18[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + uint8_t ucDummy19[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; #endif #if ( tskSTATIC_AND_DYNAMIC_ALLOCATION_POSSIBLE != 0 ) uint8_t uxDummy20; diff --git a/components/freertos/include/freertos/FreeRTOSConfig.h b/components/freertos/include/freertos/FreeRTOSConfig.h index c1dcd1cd48..ecc7c30aac 100644 --- a/components/freertos/include/freertos/FreeRTOSConfig.h +++ b/components/freertos/include/freertos/FreeRTOSConfig.h @@ -300,4 +300,6 @@ extern void vPortCleanUpTCB ( void *pxTCB ); #define configINCLUDE_FREERTOS_TASK_C_ADDITIONS_H 1 +#define configTASK_NOTIFICATION_ARRAY_ENTRIES 1 + #endif /* FREERTOS_CONFIG_H */ diff --git a/components/freertos/include/freertos/task.h b/components/freertos/include/freertos/task.h index 53dfe53135..5c7ce9ada0 100644 --- a/components/freertos/include/freertos/task.h +++ b/components/freertos/include/freertos/task.h @@ -60,7 +60,15 @@ #define tskMPU_REGION_NORMAL_MEMORY ( 1UL << 3UL ) #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 ) + /** * task. h * @@ -2111,11 +2119,23 @@ void vTaskGetRunTimeStats( char * pcWriteBuffer ) PRIVILEGED_FUNCTION; /*lin uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; /** - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. + * task. h + *
BaseType_t xTaskNotifyIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify, uint32_t ulValue, eNotifyAction eAction );
+ *
BaseType_t xTaskNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction );
* - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * 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. + * + * 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 * objects are queues, semaphores, mutexes and event groups. Task notifications @@ -2123,28 +2143,46 @@ uint32_t ulTaskGetIdleRunTimeCounter( void ) PRIVILEGED_FUNCTION; * an intermediary object. * * 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 - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * 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 notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). 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. - * - * 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 + * 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. * - * 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 * 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. 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 * 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: * * eSetBits - - * The task's notification value is bitwise ORed with ulValue. xTaskNofify() - * always returns pdPASS in this case. + * The target notification value is bitwise ORed with ulValue. + * xTaskNofifyIndexed() 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. + * The target notification value is incremented. ulValue is not used and + * xTaskNotifyIndexed() 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. + * The target notification value is set to the value of ulValue, even if the + * task being notified had not yet processed the previous notification at the + * same array index (the task already had a notification pending at that index). + * xTaskNotifyIndexed() 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. + * If the task being notified did not already have a notification pending at the + * same array index then the target notification value is set to ulValue and + * xTaskNotifyIndexed() will return pdPASS. If the task being notified already + * had a notification pending at the same array index 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. + * The task receives a notification at the specified array index without the + * notification value at that index being updated. ulValue is not used and + * xTaskNotifyIndexed() always returns pdPASS in 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. + * pulPreviousNotificationValue - + * Can be used to pass out the subject task's notification value before any + * bits are modified by the notify function. * * @return Dependent on the value of eAction. See the description of the * eAction parameter. * + * \defgroup xTaskNotifyIndexed xTaskNotifyIndexed * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue ) PRIVILEGED_FUNCTION; -#define xTaskNotify( xTaskToNotify, ulValue, eAction ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL ) -#define xTaskNotifyAndQuery( xTaskToNotify, ulValue, eAction, pulPreviousNotifyValue ) xTaskGenericNotify( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotifyValue ) ) +BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + 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 + *
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 );
* - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this - * function to be available. + * See https://www.FreeRTOS.org/RTOS-task-notifications.html for details. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * 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. * - * A version of xTaskNotify() that can be used from an interrupt service routine - * (ISR). + * 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 + *
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 );
+ * + * 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 @@ -2207,22 +2287,40 @@ BaseType_t xTaskGenericNotify( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNo * an intermediary object. * * 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 - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * 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 notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). 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. - * - * 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 + * 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. * - * 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 * 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 * 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 * *pxHigherPriorityTaskWoken to pdTRUE if sending the notification caused 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 * eAction parameter. * + * \defgroup xTaskNotifyIndexedFromISR xTaskNotifyIndexedFromISR * \ingroup TaskNotifications */ -BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulValue, eNotifyAction eAction, uint32_t *pulPreviousNotificationValue, BaseType_t *pxHigherPriorityTaskWoken ) PRIVILEGED_FUNCTION; -#define xTaskNotifyFromISR( xTaskToNotify, ulValue, eAction, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), NULL, ( pxHigherPriorityTaskWoken ) ) -#define xTaskNotifyAndQueryFromISR( xTaskToNotify, ulValue, eAction, pulPreviousNotificationValue, pxHigherPriorityTaskWoken ) xTaskGenericNotifyFromISR( ( xTaskToNotify ), ( ulValue ), ( eAction ), ( pulPreviousNotificationValue ), ( pxHigherPriorityTaskWoken ) ) +BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, + UBaseType_t uxIndexToNotify, + 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 + *
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 );
+ * + * 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 + *
+ * 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 );
+ * 
+ * + * 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 * function to be available. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * 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 @@ -2296,22 +2439,41 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal * an intermediary object. * * 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 - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * 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 notification sent to a task will remain pending until it is cleared by the - * task calling xTaskNotifyWait() or ulTaskNotifyTake(). 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. + * 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. * - * 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 + * 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. * - * 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 * 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 * not already be pending when xTaskNotifyWait() 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 + * 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 * ticks. * @@ -2350,18 +2512,37 @@ BaseType_t xTaskGenericNotifyFromISR( TaskHandle_t xTaskToNotify, uint32_t ulVal * already pending when xTaskNotifyWait was called) then pdPASS is * returned. Otherwise pdFAIL is returned. * + * \defgroup xTaskNotifyWaitIndexed xTaskNotifyWaitIndexed * \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 + *
BaseType_t xTaskNotifyGiveIndexed( TaskHandle_t xTaskToNotify, UBaseType_t uxIndexToNotify );
+ *
BaseType_t xTaskNotifyGive( TaskHandle_t xTaskToNotify );
* - * configUSE_TASK_NOTIFICATIONS must be undefined or defined as 1 for this macro - * to be available. + * 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. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * 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 @@ -2369,46 +2550,74 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * an intermediary object. * * 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 - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * 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. * - * xTaskNotifyGive() 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 - * xTaskNotifyGive(). + * 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 ulTaskNotificationTake() API function rather than the - * xTaskNotifyWait() API function. + * using the ulTaskNotificationTakeIndexed() API function rather than the + * 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 * 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 ), ( 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 + *
void vTaskNotifyGiveIndexedFromISR( TaskHandle_t xTaskHandle, UBaseType_t uxIndexToNotify, BaseType_t *pxHigherPriorityTaskWoken );
+ *
void vTaskNotifyGiveFromISR( TaskHandle_t xTaskHandle, BaseType_t *pxHigherPriorityTaskWoken );
+ * + * 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. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). - * - * A version of xTaskNotifyGive() that can be called 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 @@ -2416,28 +2625,46 @@ BaseType_t xTaskNotifyWait( uint32_t ulBitsToClearOnEntry, uint32_t ulBitsToClea * an intermediary object. * * 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 - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * 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. * - * vTaskNotifyGiveFromISR() is intended for use when task notifications are - * used as light weight and faster binary or counting semaphore equivalents. + * 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 vTaskNotifyGiveFromISR(). + * 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 ulTaskNotificationTake() API function rather than the - * xTaskNotifyWait() API function. + * using the ulTaskNotificationTakeIndexed() API function rather than the + * 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 * 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 @@ -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 * for the port in use. * + * \defgroup vTaskNotifyGiveIndexedFromISR vTaskNotifyGiveIndexedFromISR * \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 + *
+ * uint32_t ulTaskNotifyTakeIndexed( UBaseType_t uxIndexToWaitOn, BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ *
+ * uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit, TickType_t xTicksToWait );
+ * 
+ * + * 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. * - * When configUSE_TASK_NOTIFICATIONS is set to one each task has its own private - * "notification value", which is a 32-bit unsigned integer (uint32_t). + * 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 @@ -2466,35 +2713,54 @@ void vTaskNotifyGiveFromISR( TaskHandle_t xTaskToNotify, BaseType_t *pxHigherPri * an intermediary object. * * 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 - * task notifications can be used to send data to a task, or be used as light - * weight and fast binary or counting semaphores. + * 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. * - * ulTaskNotifyTake() 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 - * ulTaskNotifyTake(). + * 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 xTaskNotifyGive() - * macro, or xTaskNotify() function with the eAction parameter set to + * other tasks should send notifications to it using the xTaskNotifyGiveIndexed() + * macro, or xTaskNotifyIndex() function with the eAction parameter set to * eIncrement. * - * ulTaskNotifyTake() can either clear the task's notification value to - * zero on exit, in which case the notification value acts like a binary - * semaphore, or decrement the task's notification value on exit, in which case - * the notification value acts like a counting semaphore. + * 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 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 * CPU time while it is in the Blocked state. * - * Where as xTaskNotifyWait() will return when a notification is pending, - * ulTaskNotifyTake() will return when the task's notification value is + * Where as xTaskNotifyWaitIndexed() will return when a notification is pending, + * ulTaskNotifyTakeIndexed() will return when the task's notification value is * 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 * 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 * 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 + * the macro pdMS_TO_TICSK( 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 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 + *
+ * BaseType_t xTaskNotifyStateClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToCLear );
  *
- * If the notification state of the task referenced by the handle xTask is
- * eNotified, then set the task's notification state to eNotWaitingNotification.
- * The task's notification value is not altered.  Set xTask to NULL to clear the
- * notification state of the calling task.
+ * BaseType_t xTaskNotifyStateClear( TaskHandle_t xTask );
+ * 
+ * + * 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 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 + *
+ * uint32_t ulTaskNotifyValueClearIndexed( TaskHandle_t xTask, UBaseType_t uxIndexToClear, uint32_t ulBitsToClear );
+ *
+ * uint32_t ulTaskNotifyValueClear( TaskHandle_t xTask, uint32_t ulBitsToClear );
+ * 
+ * + * 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 diff --git a/components/freertos/linker.lf b/components/freertos/linker.lf index bb8d397ae3..a9aeec7d6b 100644 --- a/components/freertos/linker.lf +++ b/components/freertos/linker.lf @@ -40,7 +40,9 @@ entries: tasks: xTaskResumeAll (default) tasks: uxTaskResetEventItemValue (default) tasks: ulTaskNotifyTake (default) + tasks: ulTaskGenericNotifyTake (default) tasks: xTaskNotifyWait (default) + tasks: xTaskGenericNotifyWait (default) tasks: xTaskGenericNotify (default) tasks: eTaskGetState (default) tasks: pxTaskGetStackStart (default) diff --git a/components/freertos/tasks.c b/components/freertos/tasks.c index 872a586421..e91616233e 100644 --- a/components/freertos/tasks.c +++ b/components/freertos/tasks.c @@ -333,8 +333,8 @@ typedef struct tskTaskControlBlock /* The old naming convention is used to #endif #if ( configUSE_TASK_NOTIFICATIONS == 1 ) - volatile uint32_t ulNotifiedValue; - volatile uint8_t ucNotifyState; + volatile uint32_t ulNotifiedValue[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; + volatile uint8_t ucNotifyState[ configTASK_NOTIFICATION_ARRAY_ENTRIES ]; #endif /* 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 ) { - pxNewTCB->ulNotifiedValue = 0; - pxNewTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + memset( ( void * ) &( pxNewTCB->ulNotifiedValue[ 0 ] ), 0x00, sizeof( pxNewTCB->ulNotifiedValue ) ); + memset( ( void * ) &( pxNewTCB->ucNotifyState[ 0 ] ), 0x00, sizeof( pxNewTCB->ucNotifyState ) ); } #endif @@ -1630,19 +1630,24 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, * indefinitely? */ 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 * and of the RTOS objects, but could still be in the * blocked state if it is waiting on its notification - * rather than waiting on an object. */ - if( pxTCB->ucNotifyState == taskWAITING_NOTIFICATION ) + * rather than waiting on an object. If not, is + * suspended. */ + eReturn = eSuspended; + + for( x = 0; x < configTASK_NOTIFICATION_ARRAY_ENTRIES; x++ ) { - eReturn = eBlocked; - } - else - { - eReturn = eSuspended; + if( pxTCB->ucNotifyState[ x ] == taskWAITING_NOTIFICATION ) + { + eReturn = eBlocked; + break; + } } } #else /* if ( configUSE_TASK_NOTIFICATIONS == 1 ) */ @@ -1972,16 +1977,21 @@ static void prvAddNewTaskToReadyList( TCB_t * pxNewTCB, vListInsertEnd( &xSuspendedTaskList, &( pxTCB->xStateListItem ) ); 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 - * now suspended, so no notification was received. */ - pxTCB->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + if( pxTCB->ucNotifyState[ x ] == taskWAITING_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(); @@ -5241,19 +5251,33 @@ TickType_t uxTaskResetEventItemValue( void ) #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(); { /* 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. */ - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { @@ -5261,9 +5285,9 @@ TickType_t uxTaskResetEventItemValue( void ) traceTASK_NOTIFY_TAKE_BLOCK(); /* All ports are written to allow a yield in a critical - section (some will yield immediately, others wait until the - critical section exits) - but it is not something that - application code should ever do. */ + * section (some will yield immediately, others wait until the + * critical section exits) - but it is not something that + * application code should ever do. */ portYIELD_WITHIN_API(); } else @@ -5281,17 +5305,17 @@ TickType_t uxTaskResetEventItemValue( void ) taskENTER_CRITICAL(); { traceTASK_NOTIFY_TAKE(); - ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; + ulReturn = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ]; if( ulReturn != 0UL ) { if( xClearCountOnExit != pdFALSE ) { - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = 0UL; + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = 0UL; } else { - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue = ulReturn - ( uint32_t ) 1; + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] = ulReturn - ( uint32_t ) 1; } } else @@ -5299,7 +5323,7 @@ TickType_t uxTaskResetEventItemValue( void ) mtCOVERAGE_TEST_MARKER(); } - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); @@ -5309,24 +5333,41 @@ TickType_t uxTaskResetEventItemValue( void ) #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(); { /* 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 - set by the notifying task or interrupt. This can be used to - clear the value to zero. */ - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnEntry; + * set by the notifying task or interrupt. This can be used to + * clear the value to zero. */ + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnEntry; /* Mark this task as waiting for a notification. */ - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskWAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskWAITING_NOTIFICATION; if( xTicksToWait > ( TickType_t ) 0 ) { @@ -5334,9 +5375,9 @@ TickType_t uxTaskResetEventItemValue( void ) traceTASK_NOTIFY_WAIT_BLOCK(); /* All ports are written to allow a yield in a critical - section (some will yield immediately, others wait until the - critical section exits) - but it is not something that - application code should ever do. */ + * section (some will yield immediately, others wait until the + * critical section exits) - but it is not something that + * application code should ever do. */ portYIELD_WITHIN_API(); } else @@ -5358,15 +5399,15 @@ TickType_t uxTaskResetEventItemValue( void ) if( pulNotificationValue != NULL ) { /* Output the current notification value, which may or may not - have changed. */ - *pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue; + * have changed. */ + *pulNotificationValue = pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ]; } /* If ucNotifyValue is set then either the task never entered the - blocked state (because a notification was already pending) or the - task unblocked because of a notification. Otherwise the task - unblocked because of a timeout. */ - if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState != taskNOTIFICATION_RECEIVED ) + * blocked state (because a notification was already pending) or the + * task unblocked because of a notification. Otherwise the task + * unblocked because of a timeout. */ + if( pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] != taskNOTIFICATION_RECEIVED ) { /* A notification was not received. */ xReturn = pdFALSE; @@ -5374,12 +5415,12 @@ TickType_t uxTaskResetEventItemValue( void ) else { /* A notification was already pending or a notification was - received while the task was waiting. */ - pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue &= ~ulBitsToClearOnExit; + * received while the task was waiting. */ + pxCurrentTCB[xPortGetCoreID()]->ulNotifiedValue[ uxIndexToWait ] &= ~ulBitsToClearOnExit; xReturn = pdTRUE; } - pxCurrentTCB[xPortGetCoreID()]->ucNotifyState = taskNOT_WAITING_NOTIFICATION; + pxCurrentTCB[xPortGetCoreID()]->ucNotifyState[ uxIndexToWait ] = taskNOT_WAITING_NOTIFICATION; } taskEXIT_CRITICAL(); @@ -5389,14 +5430,19 @@ TickType_t uxTaskResetEventItemValue( void ) #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; - BaseType_t xReturn = pdPASS; - uint8_t ucOriginalNotifyState; + TCB_t * pxTCB; + BaseType_t xReturn = pdPASS; + uint8_t ucOriginalNotifyState; + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); configASSERT( xTaskToNotify ); pxTCB = xTaskToNotify; @@ -5404,49 +5450,53 @@ TickType_t uxTaskResetEventItemValue( void ) { 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 ) { - case eSetBits : - pxTCB->ulNotifiedValue |= ulValue; + case eSetBits: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue; break; - case eIncrement : - ( pxTCB->ulNotifiedValue )++; + case eIncrement: + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; break; - case eSetValueWithOverwrite : - pxTCB->ulNotifiedValue = ulValue; + case eSetValueWithOverwrite: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; break; - case eSetValueWithoutOverwrite : + case eSetValueWithoutOverwrite: + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { - pxTCB->ulNotifiedValue = ulValue; + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; } else { /* The value could not be written to the task. */ xReturn = pdFAIL; } + break; case eNoAction: + /* The task is being notified without its notify value being - updated. */ + * updated. */ break; default: + /* Should not get here if all enums are handled. - Artificially force an assert by testing a value the - compiler can't assume is const. */ - configASSERT( pxTCB->ulNotifiedValue == ~0UL ); + * Artificially force an assert by testing a value the + * compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL ); break; } @@ -5454,7 +5504,7 @@ TickType_t uxTaskResetEventItemValue( void ) traceTASK_NOTIFY(); /* 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 ) { ( void ) uxListRemove( &( pxTCB->xStateListItem ) ); @@ -5463,20 +5513,20 @@ TickType_t uxTaskResetEventItemValue( void ) /* The task should not have been on an event list. */ configASSERT( listLIST_ITEM_CONTAINER( &( pxTCB->xEventListItem ) ) == NULL ); - #if( configUSE_TICKLESS_IDLE != 0 ) - { - /* If a task is blocked waiting for a notification then - xNextTaskUnblockTime might be set to the blocked task's time - out time. If the task is unblocked for a reason other than - a timeout xNextTaskUnblockTime is normally left unchanged, - because it will automatically get reset to a new value when - the tick count equals xNextTaskUnblockTime. However if - tickless idling is used it might be more important to enter - sleep mode at the earliest possible time - so reset - xNextTaskUnblockTime here to ensure it is updated at the - earliest possible time. */ - prvResetNextTaskUnblockTime(); - } + #if ( configUSE_TICKLESS_IDLE != 0 ) + { + /* If a task is blocked waiting for a notification then + * xNextTaskUnblockTime might be set to the blocked task's time + * out time. If the task is unblocked for a reason other than + * a timeout xNextTaskUnblockTime is normally left unchanged, + * because it will automatically get reset to a new value when + * the tick count equals xNextTaskUnblockTime. However if + * tickless idling is used it might be more important to enter + * sleep mode at the earliest possible time - so reset + * xNextTaskUnblockTime here to ensure it is updated at the + * earliest possible time. */ + prvResetNextTaskUnblockTime(); + } #endif if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) @@ -5507,32 +5557,38 @@ TickType_t uxTaskResetEventItemValue( void ) #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; - uint8_t ucOriginalNotifyState; - BaseType_t xReturn = pdPASS; + TCB_t * pxTCB; + uint8_t ucOriginalNotifyState; + BaseType_t xReturn = pdPASS; configASSERT( xTaskToNotify ); + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); pxTCB = xTaskToNotify; @@ -5541,55 +5597,59 @@ TickType_t uxTaskResetEventItemValue( void ) { if( pulPreviousNotificationValue != NULL ) { - *pulPreviousNotificationValue = pxTCB->ulNotifiedValue; + *pulPreviousNotificationValue = pxTCB->ulNotifiedValue[ uxIndexToNotify ]; } - ucOriginalNotifyState = pxTCB->ucNotifyState; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; switch( eAction ) { - case eSetBits : - pxTCB->ulNotifiedValue |= ulValue; + case eSetBits: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] |= ulValue; break; - case eIncrement : - ( pxTCB->ulNotifiedValue )++; + case eIncrement: + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; break; - case eSetValueWithOverwrite : - pxTCB->ulNotifiedValue = ulValue; + case eSetValueWithOverwrite: + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; break; - case eSetValueWithoutOverwrite : + case eSetValueWithoutOverwrite: + if( ucOriginalNotifyState != taskNOTIFICATION_RECEIVED ) { - pxTCB->ulNotifiedValue = ulValue; + pxTCB->ulNotifiedValue[ uxIndexToNotify ] = ulValue; } else { /* The value could not be written to the task. */ xReturn = pdFAIL; } + break; - case eNoAction : + case eNoAction: + /* The task is being notified without its notify value being - updated. */ + * updated. */ break; default: + /* Should not get here if all enums are handled. - Artificially force an assert by testing a value the - compiler can't assume is const. */ - configASSERT( pxTCB->ulNotifiedValue == ~0UL ); + * Artificially force an assert by testing a value the + * compiler can't assume is const. */ + configASSERT( pxTCB->ulNotifiedValue[ uxIndexToNotify ] == ~0UL ); break; } traceTASK_NOTIFY_FROM_ISR(); /* 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 ) { /* The task should not have been on an event list. */ @@ -5603,14 +5663,14 @@ TickType_t uxTaskResetEventItemValue( void ) else { /* 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 ) ); } if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* 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 ) { *pxHigherPriorityTaskWoken = pdTRUE; @@ -5637,47 +5697,50 @@ TickType_t uxTaskResetEventItemValue( void ) #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; uint8_t ucOriginalNotifyState; configASSERT( xTaskToNotify ); + configASSERT( uxIndexToNotify < configTASK_NOTIFICATION_ARRAY_ENTRIES ); /* RTOS ports that support interrupt nesting have the concept of a - maximum system call (or maximum API call) interrupt priority. - Interrupts that are above the maximum system call priority are keep - permanently enabled, even when the RTOS kernel is in a critical section, - but cannot make any calls to FreeRTOS API functions. If configASSERT() - is defined in FreeRTOSConfig.h then - portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion - failure if a FreeRTOS API function is called from an interrupt that has - been assigned a priority above the configured maximum system call - priority. Only FreeRTOS functions that end in FromISR can be called - from interrupts that have been assigned a priority at or (logically) - below the maximum system call interrupt priority. FreeRTOS maintains a - separate interrupt safe API to ensure interrupt entry is as fast and as - simple as possible. More information (albeit Cortex-M specific) is - provided on the following link: - http://www.freertos.org/RTOS-Cortex-M3-M4.html */ + * maximum system call (or maximum API call) interrupt priority. + * Interrupts that are above the maximum system call priority are keep + * permanently enabled, even when the RTOS kernel is in a critical section, + * but cannot make any calls to FreeRTOS API functions. If configASSERT() + * is defined in FreeRTOSConfig.h then + * portASSERT_IF_INTERRUPT_PRIORITY_INVALID() will result in an assertion + * failure if a FreeRTOS API function is called from an interrupt that has + * been assigned a priority above the configured maximum system call + * priority. Only FreeRTOS functions that end in FromISR can be called + * from interrupts that have been assigned a priority at or (logically) + * below the maximum system call interrupt priority. FreeRTOS maintains a + * separate interrupt safe API to ensure interrupt entry is as fast and as + * simple as possible. More information (albeit Cortex-M specific) is + * provided on the following link: + * https://www.FreeRTOS.org/RTOS-Cortex-M3-M4.html */ portASSERT_IF_INTERRUPT_PRIORITY_INVALID(); pxTCB = xTaskToNotify; taskENTER_CRITICAL_ISR(); { - ucOriginalNotifyState = pxTCB->ucNotifyState; - pxTCB->ucNotifyState = taskNOTIFICATION_RECEIVED; + ucOriginalNotifyState = pxTCB->ucNotifyState[ uxIndexToNotify ]; + pxTCB->ucNotifyState[ uxIndexToNotify ] = taskNOTIFICATION_RECEIVED; /* 'Giving' is equivalent to incrementing a count in a counting - semaphore. */ - ( pxTCB->ulNotifiedValue )++; + * semaphore. */ + ( pxTCB->ulNotifiedValue[ uxIndexToNotify ] )++; traceTASK_NOTIFY_GIVE_FROM_ISR(); /* 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 ) { /* The task should not have been on an event list. */ @@ -5691,7 +5754,7 @@ TickType_t uxTaskResetEventItemValue( void ) else { /* 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 ) ); } @@ -5699,7 +5762,7 @@ TickType_t uxTaskResetEventItemValue( void ) if( tskCAN_RUN_HERE(pxTCB->xCoreID) && pxTCB->uxPriority > pxCurrentTCB[ xPortGetCoreID() ]->uxPriority ) { /* 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 ) { *pxHigherPriorityTaskWoken = pdTRUE; @@ -5720,25 +5783,27 @@ TickType_t uxTaskResetEventItemValue( void ) } #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; - BaseType_t xReturn; + TCB_t * pxTCB; + BaseType_t xReturn; + + 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. */ + * its notification state cleared. */ pxTCB = prvGetTCBFromHandle( xTask ); 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; } else @@ -5754,7 +5819,35 @@ TickType_t uxTaskResetEventItemValue( void ) #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 ) {