[RTOS Task Notification API]
uint32_t ulTaskNotifyTake( BaseType_t xClearCountOnExit,
TickType_t xTicksToWait );
Each RTOS task has a 32-bit notification value which is initialised to zero when the RTOS task is created. An RTOS task notification is an event sent directly to a task that can unblock the receiving task, and optionally update the receiving task’s notification value.
ulTaskNotifyTake() is intended for use when a task notification is used as a faster and lighter weight binary or counting semaphore alternative. FreeRTOS semaphores are taken using the xSemaphoreTake() API function, ulTaskNotifyTake() is the equivalent that instead uses a task notification.
When a task is using its notification value as a binary or counting semaphore other tasks and interrupts should send notifications to it using either the xTaskNotifyGive() macro, or the xTaskNotify() function with the function’s eAction parameter set to eIncrement (the two are equivalent).
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 more like a counting semaphore.
An RTOS task can use ulTaskNotifyTake() to [optionally] block to wait for a 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 not zero, decrementing the task’s notification value before it returns.
xClearCountOnExit If an RTOS task notification is received and xClearCountOnExit is set to pdFALSE then the RTOS task’s notification value is decremented before ulTaskNotifyTake() exits. This is equivalent to the value of a counting semaphore being decremented by a successful call to xSemaphoreTake().
If an RTOS task notification is received and xClearCountOnExit is set to pdTRUE then the RTOS task’s notification value is reset to 0 before ulTaskNotifyTake() exits. This is equivalent to the value of a binary semaphore being left at zero (or empty, or ‘not available’) after a successful call to xSemaphoreTake().
xTicksToWait The maximum time to wait in the Blocked state for a notification to be received if a notification is not already pending when ulTaskNotifyTake() is called.
The RTOS task does not consume any CPU time when it is in the Blocked state.
The time is specified in RTOS tick periods. The pdMS_TO_TICKS() macro can be used to convert a time specified in milliseconds into a time specified in ticks.
- The value of the task’s notification value before it is decremented or cleared (see the description of xClearCountOnExit).
[More examples are referenced from the main RTOS task notifications page]
/* An interrupt handler. The interrupt handler does not perform any processing,
instead it unblocks a high priority task in which the event that generated the
interrupt is processed. If the priority of the task is high enough then the
interrupt will return directly to the task (so it will interrupt one task but
return to a different task), so the processing will occur contiguously in time -
just as if all the processing had been done in the interrupt handler itself. */
void vANInterruptHandler( void )
/* Clear the interrupt. */
/* xHigherPriorityTaskWoken must be initialised to pdFALSE. If calling
vTaskNotifyGiveFromISR() unblocks the handling task, and the priority of
the handling task is higher than the priority of the currently running task,
then xHigherPriorityTaskWoken will automatically get set to pdTRUE. */
xHigherPriorityTaskWoken = pdFALSE;
/* Unblock the handling task so the task can perform any processing necessitated
by the interrupt. xHandlingTask is the task's handle, which was obtained
when the task was created. */
vTaskNotifyGiveFromISR( xHandlingTask, &xHigherPriorityTaskWoken );
/* Force a context switch if xHigherPriorityTaskWoken is now set to pdTRUE.
The macro used to do this is dependent on the port and may be called
portYIELD_FROM_ISR( xHigherPriorityTaskWoken );
/* A task that blocks waiting to be notified that the peripheral needs servicing,
processing all the events pending in the peripheral each time it is notified to
do so. */
void vHandlingTask( void *pvParameters )
for( ;; )
/* Block indefinitely (without a timeout, so no need to check the function's
return value) to wait for a notification. Here the RTOS task notification
is being used as a binary semaphore, so the notification value is cleared
to zero on exit. NOTE! Real applications should not block indefinitely,
but instead time out occasionally in order to handle error conditions
that may prevent the interrupt from sending any more notifications. */
ulTaskNotifyTake( pdTRUE, /* Clear the notification value before
portMAX_DELAY ); /* Block indefinitely. */
/* The RTOS task notification is used as a binary (as opposed to a
counting) semaphore, so only go back to wait for further notifications
when all events pending in the peripheral have been processed. */
xEvent = xQueryPeripheral();
if( xEvent != NO_MORE_EVENTS )
vProcessPeripheralEvent( xEvent );
} while( xEvent != NO_MORE_EVENTS );