In this example LED rotation is changed, using Queue options when button is pressed.

Code Example:

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

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

#define RIGHT   0           //Rotate LEDs to right
#define LEFT    1           //Rotate LEDs to left

static void Task_LED_Selector( void *parameters );      /* Task to select LED to be control */
static void Task_Read_Buttons( void *parameters );      /* Task to read Buttons to change LED rotation */
static void Task_LED_Control( void *parameters );       /* Task to control LED status */

QueueHandle_t QueueLEDstatus;                           /* Handler of Queue */
static uint16_t Rotation = RIGHT;                       /* Option to change QueueSend function */

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_Read_Buttons, "Task_Rotation", 128u, NULL, 3u, NULL );   /* Register a Task */
    xTaskCreate( Task_LED_Selector, "Task_Selector", 128u, NULL, 2u, 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 uint8_t i = 0;    /* Iter Value to send different messages */

    for( ;; )
    {
        while( uxQueueSpacesAvailable( QueueLEDstatus ) > NONE_MESSAGES ) /* Check space in Queue to write */
        {
            if( Rotation == LEFT )                                      /* Check Flag Value */
            {
                xQueueSendToBack( QueueLEDstatus, &Led_Pin[i], 0 );     /* Write elements back of Queue buffer */
            }
            else if( Rotation == RIGHT )                                /* Check Flag Value */
            {
                xQueueSendToFront( QueueLEDstatus, &Led_Pin[i], 0 );    /* Write elements in front of Queue buffer */
            }

            i++;                                                        /* Increment to select another data from Array */
        }
        i = RESET_VALUE;                                                /* If Queue has no space, Reset the Value */

        vTaskDelay(2000 / portTICK_PERIOD_MS);                          /* wait 2s to send another complete Queue */
    }
}

static void Task_Read_Buttons( void *parameters )
{
    UNUSED( parameters );

    for( ;; )
    {
        if ( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_7) == GPIO_PIN_RESET )       /* Read Status of button 7 */
        {
            Rotation = LEFT;                                               /* Change Flag value */
            SEGGER_SYSVIEW_PrintfHost( "Button Pressed to Left" );
        }
        else if( HAL_GPIO_ReadPin(GPIOB, GPIO_PIN_15) == GPIO_PIN_RESET )  /* Read Status of button 15 */
        {
            Rotation = RIGHT;                                              /* Change Flag value */
            SEGGER_SYSVIEW_PrintfHost( "Button Pressed to Right" );
        }

        vTaskDelay( 50 / portTICK_PERIOD_MS );                             /* Check buttons each 50ms */
    }
}

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

    for( ;; )
    {
        while ( uxQueueMessagesWaiting( QueueLEDstatus ) > NONE_MESSAGES )  /* Check that there are message to read */
        {
            xQueueReceive( QueueLEDstatus, &dataRead, 0 );      /* Read the data of the Queue */
            HAL_GPIO_TogglePin( GPIOC, dataRead );              /* Change the LED Status */

            vTaskDelay(200 / portTICK_PERIOD_MS);               /* Wait 200ms to read other msg */
            
            uint32_t res = log2(dataRead);                      
            SEGGER_SYSVIEW_PrintfHost( "LED %d", res );
        }

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

Three tasks are created, Task_Read_Buttons() that Read 2 buttons, each of them executes a different Queue option in Task_LED_Selector(), for example, if flag Rotation is equal to RIGHT the function to execute is xQueueSendToFront() that writes each data in the front of the Queue as a normal function, but if flag Rotation change to LEFT, the function to execute is xQueueSendToBack() that send each data to the back of Queue buffer.

Task Task_LED_Control() isn't affected by the selection of rotation, just processes the data received from QueueLEDstatus.


There are not difference between function xQueueSendToBack() and xQueueSend() , This functions just use a macro to call the same function.

#define xQueueSendToBack( xQueue, pvItemToQueue, xTicksToWait ) \
    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )
    
#define xQueueSend( xQueue, pvItemToQueue, xTicksToWait ) \
    xQueueGenericSend( ( xQueue ), ( pvItemToQueue ), ( xTicksToWait ), queueSEND_TO_BACK )

SystemView Output:

Terminal output shows that initial rotation of LEDs is to the Right. By default application sends to front elements to the Queue, As a result Terminal shows a count drecrement each time that message is read.

Document

TimeLine:

Document

Task "Task_Read_Buttons" is executed but ignored because the button is not pressed yet.
Next, the timeline shows the Task "Task_LED_Control" reading an element from the Queue when elements were sent to the front of the Queue Buffer.

When the button to change to Left is pressed a message is send to terminal, and task "Task_LED_Control" wait to read all the elements on Queue to change the LED rotation.
Now elements is send to front of the Queue.

Timeline Shows when the last message of the Right rotation finish and when the Left rotation start.
Between this 2 events there arent task execution for 600ms, this indicate that "Task_LED_Control" Read all the Queue messages and wait to "Task_LED_Selector" to send a complete buffer again.

End of Right Rotation

Start Left Rotation