When working with tasks that need to manage multiple signals or events, you can use an index array within direct task notifications. This allows a task to wait for multiple signals across multiple channels, each identified by a specific index. In this example, we’ll use an array of three elements, where each event represents a different signal from multiple tasks sending the signals.

By using an index array, the receiving task can wait for notifications on any channel, enabling efficient and orderly handling of multiple events. Each index in the array can be configured for different purposes, such as controlling LEDs, reading sensors, or managing buttons, providing flexibility to the system design.

You can choose the maximum array index in a task notification. Just modify the value of the next define, in the FreeRTOSConfig file.

#define configTASK_NOTIFICATION_ARRAY_ENTRIES   3

Code Example:

#include "bsp.h"

#define LED_1           (uint8_t*)(1)           /* Parameter to be send with the Task to send LEDs notification */
#define LED_2           (uint8_t*)(2)           /* Parameter to be send with the Task to send LEDs notification */

#define INDEX_LED_1     0                       /* Index of LED 1 notification */
#define INDEX_LED_2     1                       /* Index of LED 2 notification */
#define INDEX_BUTTON    2                       /* Index of button notification */

#define NO_DATA         0                       /* Macro to indicate that notification is not received */

static void vTaskLED( void *parameters );       /* Function task to manage sent of LEDs notifications */
static void vTaskReceiver( void *parameters );  /* Function task to process all the notifications */

TaskHandle_t TaskH = NULL;

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

    HAL_NVIC_SetPriority(EXTI4_15_IRQn,0,2);                                /* Configure an interruption */
    HAL_NVIC_EnableIRQ(EXTI4_15_IRQn);                                      /* Enable the interruption */

    xTaskCreate( vTaskLED, "Task_LED1", 128u, LED_1, 1u, NULL );            /* Register Task to send the notification of LED 1 */
    xTaskCreate( vTaskLED, "Task_LED2", 128u, LED_2, 1u, NULL );            /* Register task to send the notification of LED 2 */
    xTaskCreate( vTaskReceiver, "Task_Receptor", 128u, NULL, 2u, &TaskH );  /* Register task to receive all the notifications */

    vTaskStartScheduler( );                                                 /* Init the Kernel */

    return 0u;
}

static void vTaskLED( void *parameters )
{
    uint8_t *Led = (uint8_t *)(parameters);     /* Receive and concatenate the parameter */

    for( ;; )
    {
        if( LED_1 == Led )                      /* enter whith Task of LED 1 */
        {
           xTaskNotifyGiveIndexed( TaskH, INDEX_LED_1 );    /* Send the notification of LED 1 */
        }
        else                                    /* enter with task of LED 2 */
        {
           xTaskNotifyGiveIndexed( TaskH, INDEX_LED_2 );    /* Send the notification of LED 2 */
        }

        vTaskDelay( 1000u );
    }
}

static void vTaskReceiver( void *parameters )
{
    UNUSED( parameters );
    uint32_t NotiValue[3];      /* Array to store differents notifications */

    for( ;; )
    {
        /* Wait for notifications on each index with a timeout of 10 ticks */
        NotiValue[INDEX_LED_1]  = ulTaskNotifyTakeIndexed( INDEX_LED_1, pdFALSE,10 );
        NotiValue[INDEX_LED_2]  = ulTaskNotifyTakeIndexed( INDEX_LED_2, pdFALSE, 10 );
        NotiValue[INDEX_BUTTON] = ulTaskNotifyTakeIndexed( INDEX_BUTTON, pdFALSE, 10 );

        /* Check and handle notification for LED 1 */
        if( NotiValue[INDEX_LED_1] != NO_DATA )
        {
            HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_0 );
            SEGGER_SYSVIEW_PrintfHost("Led 1");
        }

        /* Check and handle notification for LED 2 */
        if( NotiValue[INDEX_LED_2] != NO_DATA )
        {
            HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_1 );
            SEGGER_SYSVIEW_PrintfHost("Led 2");
        }

        /* Check and handle notification for Button */
        if( NotiValue[INDEX_BUTTON] != NO_DATA )
        {
            HAL_GPIO_TogglePin( GPIOC, GPIO_PIN_7 );
            SEGGER_SYSVIEW_PrintfHost("Button");
        }

        vTaskDelay( 100u );
    }
}

void HAL_GPIO_EXTI_Rising_Callback( uint16_t GPIO_Pin )                     /* Callback of interrupt */
{
    SEGGER_SYSVIEW_RecordEnterISR();                                        /* Record enter of IRS on SytemView timeline */
    BaseType_t xTaskWoken = pdFALSE;

    vTaskNotifyGiveIndexedFromISR( TaskH, INDEX_BUTTON, &xTaskWoken );      /* Send a notification to the Task Receiver */
    
    SEGGER_SYSVIEW_RecordExitISR();                                         /* Record exit of IRS on SytemView timeline */
    portEND_SWITCHING_ISR( xTaskWoken );                                    /* Change context */
}

Three tasks are registered: two of them send data using different index task notifications, and an ISR is used to send the third notification. The other registered task is the Receiver task, which waits for 10ms for each message if no notification is available. This wait time can be set to zero if you don’t want to wait for a specific signal to arrive.

Observe that the task and the ISR are used to send a notification and change the status for a specific LED for each one, the Receiver task processes the received signals and controls the LEDs based on the signals received.

SystemView Output:

The terminal shows that the receiver task executes different actions based on the index array of the notifications. For example, the first two messages correspond to the LED index, but if the button is not pressed, the task only executes the LED notifications at that moment. Once the button is pressed, the task then receives and processes the notification for the button.

Document

TimeLine:

Document

When application init the task execute and immediately the Task_Receptor execute, processing the notification, but let focus in the red box, the LEDs task sends the notification in the corresponding index array.

When 100ms elapsed the Task_Receptor execute and find the 2 notification from LEDs tasks, Then processes each notification.

In this picture, the button generate an ISR to send a notification in the last index array, after, notice that the Task_Receiver is executed processing first a notification received from Task_LED2, subsequently the notification of the button is processed, observe the printed message.