In this example, Queue messages are used as communication method between tasks. The first task (Task_Selector) used to transfer multiple data of each pin connected to LEDs every 2 seconds, and the second task (Task_Control) uses this info to change the LED state reading each message of Task_Selector every 200ms. When Task_Selector executes again the LED status will change.

code example:

#include "bsp.h"
#include <math.h>

#define NUMBER_OF_LEDS  8   /* Indicate the number of LEDs */
#define NONE_MESSAGES   0   /* Indicate that No messages available */
#define RESET_VALUE     0   /* Default value to Restore a Variable */ 

static void Task_LED_Selector( void *parameters );      /* Task to select LED to be control */
static void Task_LED_Control( void *parameters );       /* Task to control LED status */

QueueHandle_t QueueLEDstatus;

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

    QueueLEDstatus = xQueueCreate( 8, sizeof(uint16_t) );           /* Create the Queue to store a data of 16 bits */

    xTaskCreate( Task_LED_Selector, "Task_Selector", 128u, NULL, 1u, NULL );   /* Register a Task */
    xTaskCreate( Task_LED_Control, "Task_Control", 128u, NULL, 1u, NULL );    /* Register a Task */

    vTaskStartScheduler( );                                         /* initilize the kernel */

    return 0u;
}

static void Task_LED_Selector( void *parameters )
{
    UNUSED( parameters );
    uint16_t Led_Pin[NUMBER_OF_LEDS] = { GPIO_PIN_0, GPIO_PIN_1, GPIO_PIN_2, GPIO_PIN_3, GPIO_PIN_4, GPIO_PIN_5, GPIO_PIN_6, GPIO_PIN_7 };                                   
    static uint16_t i = 0;    /* Iter Value to send different messages */

    for( ;; )
    {
        while( uxQueueSpacesAvailable( QueueLEDstatus ) > NONE_MESSAGES ) /* Check how many spaces the Queue has */
        {
            xQueueSend( QueueLEDstatus, &Led_Pin[i], 0 );     /* Send the data to Queue */
            i++;                                              /* Increment to select another data from Array */
        }
        i = RESET_VALUE;                                      /* If Queue has no space, Reset the Value */

        vTaskDelay(2000 / portTICK_PERIOD_MS);               /* Periodicity of Task */
    }
}

static void Task_LED_Control( void *parameters )
{
    UNUSED( parameters );
    uint16_t dataRead;                                      /* Variable to store data of Queue */

    for( ;; )
    {
        /* Enter to a loop to Read elements until Queue Buffer is zero */
        while ( uxQueueMessagesWaiting( QueueLEDstatus ) > NONE_MESSAGES )
        {
            xQueueReceive( QueueLEDstatus, &dataRead, 0 );      /* Read the data of the Queue */
            HAL_GPIO_TogglePin( GPIOC, dataRead );              /* Change the LED Status */ 
            
            uint32_t res = log2(dataRead);                      /* Just convert message binary to Dec to be printed */
            SEGGER_SYSVIEW_PrintfHost( "LED %d", res );         /* Print on Terminal the message received */
            
            vTaskDelay(200 / portTICK_PERIOD_MS);               /* Wait 200ms to read other msg */
        }

        vTaskDelay(200 / portTICK_PERIOD_MS);               /* Periodicity of Task */
    }
}
💡
Note: Function uxQueueMessagesWaiting() Returns the number of messages to read, in the example used in a while loop to read and process all the messages until the queue has no more messages to read.

SystemView output:

The terminal will show that task Task_LED_Control prints the numbers of the LEDs received by the queue buffer, when the counter is restarted the LED state changes.

Document

TimeLine:

Document

Task Task_LED_Selector executes first and sends all the messages on Queue buffer, next the task Task_LED_Control executes and reads just a message from the buffer and waits 200ms for the next execution.

After 200ms again Task_LED_Control executes and processes the next message.

Finally, after 2 seconds, the first task Task_LED_Selector executes again sending all parameters, when finished, the task Task_LED_Control executes and now the LED state will change.