Task Notification is a mechanism that enables tasks to communicate by sending data to each other. However, there are specific restrictions to be aware of. Each notification can only carry a single 32-bit data value at a time. This means that you cannot send multiple values simultaneously or use other data types than 32-bit integers.

To illustrate how Task Notification works, we will use the basic example provided on the main page. We will modify the example to demonstrate how task notifications can be used with data values.

Code Example:

#include "bsp.h"

static void vTask1( void *parameters );     /* Creation of task function */
static void vTask2( void *parameters );     /* Creation of task function */

TaskHandle_t TaskH1 = NULL;                 /* Create the handle to task1 */
TaskHandle_t TaskH2 = NULL;                 /* Create the handle to task2 */

int main( void )
{
    HAL_Init( );
    /*enable RTT and system view*/
    SEGGER_SYSVIEW_Conf( );
    SEGGER_SYSVIEW_Start( );

    xTaskCreate( vTask1, "Task", 128u, NULL, 1u, &TaskH1 ); /* Register on Kernel the Task and pass the handler of the task1 */
    xTaskCreate( vTask2, "Task", 128u, NULL, 1u, &TaskH2 ); /* Register on Kernel the Task and pass the handler of the task2 */

    vTaskStartScheduler( );     /* Init the Kernel */

    return 0u;
}

static void vTask1( void *parameters )
{
    UNUSED( parameters );
    uint32_t MsgToSend = 0;                                             /* Variable that contain the message to send */

    for( ;; )
    {
        xTaskNotify(TaskH2, MsgToSend, eSetValueWithOverwrite);         /* Send the notification with the message */
        MsgToSend++;                                                    /* Increment the Value to send another data the next execution */

        vTaskDelay( 1000u );                                            /* Wait a second */
    }
}

static void vTask2( void *parameters )
{
    UNUSED( parameters );                                               
    uint32_t ulNotifiedValue;                                           /* Variable where the Task notification value will be received */

    for( ;; )
    {
        xTaskNotifyWait(0, 0, &ulNotifiedValue, portMAX_DELAY);         /* Receive the task notification message */    
        SEGGER_SYSVIEW_PrintfHost( "Message Received: %d", ulNotifiedValue );   /* Print the message received */

        vTaskDelay( 100u );                                             /* Wait a notification each 100ms */
    }
}

Observe that the code is similar to the basic example explained on the main page, the differences become on the API functions. Check Task1 The function xTaskNotify() is declared with different parameters, the parameter MsgToSend is a variable that contains the data to be sent, and the parameter eSetValueWithOverwrite configures the action to manage the notification value when the notification is sent, the current action set is to overwrite data with the new message to send. Function xTaskNotifyWait() in task2, is used to receive the notifications, this function allows us to use a bit mask to clear some bits received from the sender task, this occasion we disable the mask of bits with the value of 0.

SystemView Output:

The terminal shows the message printed every second, The sender task is configured to send different data each execution, and the receiver task is configured to read the notification every 100ms without cleaning any bit of the data received.

Document

TimeLine:

Document

Notice that in the first execution task sender execute and send the data through the task notification value, after the receiver task is executed and prints the data received.

After 100ms the period of the receiver task, task is executed but notification is not ready yet. Therefore the task enters in the blocked state to wait until a notification arrives.

After 1 second when another notification is sent by Sender task, the receiver task is unlocked and execute to print the new message received.