In the previous example Example of data lost in Queue Buffer, Queue buffer was configured to store a maximum of 4 data with a size of uint16_t or 2 bytes. Two task was configured to send and receive the data, The task in charge of send data to buffer, writes a data every 200ms but this task send a data from array position, this array position have 8 elements to send in Queue, this is a problem because buffer just store 4 elements. Therefore some data is lost.

To Fix the data lost, we can use the function uxQueueSpacesAvailable( Queue ); This function will return the number of spaces free in the Queue buffer. Using it we can send data only when the buffer is not full and write the rest of the elements when the buffer has spaces free.

Code example to fix lost data:

#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   /* Defualt value to restore variable */

static void WriteInQueue( void *parameters );      /* Task to select LED to be control */
static void ReadInQueue( void *parameters );       /* Task to control LED status */

QueueHandle_t Queue_LED;

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

    Queue_LED = xQueueCreate( 4, sizeof(uint16_t) );           /* Create the Queue with a buffer size of 4 elements of 16 bits */

    xTaskCreate( WriteInQueue, "Task_Write_Queue", 128u, NULL, 1u, NULL );   /* Register a Task */
    xTaskCreate( ReadInQueue, "Task_Read_Queue", 128u, NULL, 1u, NULL );    /* Register a Task */

    vTaskStartScheduler( );                                         /* initilize the kernel */

    return 0u;
}

static void WriteInQueue( void *parameters )
{
    UNUSED( parameters );
    
    /* Array of data to Send, 8 data must be send to Queue */
    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;                                  /* Variable to iterate between array elements */

    for( ;; )
    {
        /* Check the spaces available on Queue buffer to know if can be write on it. Also, checks if iteration is correct */
        if( (uxQueueSpacesAvailable( Queue_LED ) > NONE_MESSAGES) && ( i < NUMBER_OF_LEDS ) )
        {
            xQueueSend( Queue_LED, &Led_Pin[i], 0 );        /* Send the current element of the Array to the Queue */
            i++;                                            /* Increment iteration count */
        }
        else if( i >= NUMBER_OF_LEDS )                      /* Check if iteration of the 8 elements is done */
        {
            i = RESET_VALUE;                                /* Reset the Iteration Value to restart to init position of array */
        }

        vTaskDelay(200 / portTICK_PERIOD_MS);               /* Send a element each 200ms, send all the array will cost 1600ms */
    }
}

static void ReadInQueue( 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( Queue_LED ) > NONE_MESSAGES )
        {
            xQueueReceive( Queue_LED, &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(1600 / portTICK_PERIOD_MS);             /* Read Queue buffer each 1600ms, when all the elements must be in Queue */
    }
}

SystemView Output:

Now on Terminal, we can observe that task WriteInQueue() now sent the complete array Led_Pin[NUMBER_OF_LEDS], even though the buffer size is 4 elements.

Document

TimeLine:

The timeline shows how the task WriteInQueue() sends data and after the task ReadInQueue() receives data and processes it. After finishing ReadInQueue() execution, WriteInQueue() sends the rest of the elements.

Document

Image shows the execution of the task WriteInQueue() which sends data to the Queue Buffer.
If we back to the code we can observe that now the task going to send data to buffer until have free spaces.

Task ReadInQueue() is executed 1600ms after the first execution of the task WriteInQueue().
Task Read and process all the elements on the Queue buffer, as you can see on the image the first element read was zero.
When the task ReadInQueue() finishes execution, again task WriteInQueue() starts to send the rest of elements.

When task ReadInQueue() is executed again, now the elements to read are different from the last execution. we can notice that now the first message to read and process is element 4.