Error on API reference xQueueReceive?

Hello,
I read on the xQueueReceive page (https://www.freertos.org/a00118.html) that the received buffer must be allocated before calling the receive function (the item is received by copy so a buffer of adequate size must be provided).
In the example provided at the bottom of the page this is not done (pxRxedMessage is not allocated).
It was an error? Some code is missing?
Thanks

I believe the example is correct, but agree it could be clearer. This is actually a really (really!) old code example that could do with reformatting anyway so I will update it.

In the example the queue is used to pass pointers. In vATask the variable pxMessage is set to the address of the xMessage structure, and then the value of pxMessage (which is the address of the xMessage structure) is sent to the queue. vADifferentTask() declares a pointer variable called pxRxedMessage, then passes the address of pxRxedMessage as the buffer into which data from the queue is read. The data read from the queue is the address of the xMessage structure, so after reading from the queue, pxRxedMessage points to xMessage too.

So in this case the buffer into which the message is read is the memory used to store the pxRxedMessage variable - so the address of a variable rather than the address of a separately allocated buffer.

I’ve looked at the code again, and you’re right. The queue is used to pass pointers, not the struct content. But this is not a useful example because is not using the queue; if the xMessage is overwritten (for a new message to put in the queue), the queue is not consistent anymore. I suggest a modify of the example for a better understanding.
Thanks

Not sure I understand that part, but I have already updated the example code for that page, although the update is not live yet. This is what I replaced the example with:

/* Define a variable of type struct AMMessage.  The examples below demonstrate
how to pass the whole variable through the queue, and as the structure is
moderately large, also how to pass a reference to the variable through a queue. */
struct AMessage
{
   char ucMessageID;
   char ucData[ 20 ];
} xMessage;

/* Queue used to send and receive complete struct AMessage structures. */
QueueHandle_t xStructQueue = NULL;

/* Queue used to send and receive pointers to struct AMessage structures. */
QueueHandle_t xPointerQueue = NULL;


void vCreateQueues( void )
{
   xMessage.ucMessageID = 0xab;
   memset( &( xMessage.ucData ), 0x12, 20 );

   /* Create the queue used to send complete struct AMessage structures.  This can
   also be created after the schedule starts, but care must be task to ensure
   nothing uses the queue until after it has been created. */
   xStructQueue = xQueueCreate(
                         /* The number of items the queue can hold. */
                         10,
                         /* Size of each item is big enough to hold the
                         whole structure. */
                         sizeof( xMessage ) );

   /* Create the queue used to send pointers to struct AMessage structures. */
   xPointerQueue = xQueueCreate(
                         /* The number of items the queue can hold. */
                         10,
                         /* Size of each item is big enough to hold only a
                         pointer. */
                         sizeof( &xMessage ) );

   if( ( xStructQueue == NULL ) || ( xPointerQueue == NULL ) )
   {
      /* One or more queues were not created successfully as there was not enough
      heap memory available.  Handle the error here.  Queues can also be created
      statically. */
   }
}

/* Task that writes to the queues. */
void vATask( void *pvParameters )
{
struct AMessage *pxPointerToxMessage;

   /* Send the entire structure to the queue created to hold 10 structures. */
   xQueueSend( /* The handle of the queue. */
               xStructQueue,
               /* The address of the xMessage variable.  sizeof( struct AMessage )
               bytes are copied from here into the queue. */
               ( void * ) &xMessage,
               /* Block time of 0 says don't block if the queue is already full.
               Check the value returned by xQueueSend() to know if the message
               was sent to the queue successfully. */
               ( TickType_t ) 0 );

   /* Store the address of the xMessage variable in a pointer variable. */
   pxPointerToxMessage = &xMessage;

   /* Send the address of xMessage to the queue created to hold 10    pointers. */
   xQueueSend( /* The handle of the queue. */
               xPointerQueue,
               /* The address of the variable that holds the address of xMessage.
               sizeof( &xMessage ) bytes are copied from here into the queue. As the
               variable holds the address of xMessage it is the address of xMessage
               that is copied into the queue. */
               ( void * ) &pxPointerToxMessage,
               ( TickType_t ) 0 );

   /* ... Rest of task code goes here. */
}

/* Task that reads from the queues. */
void vADifferentTask( void *pvParameters )
{
struct AMessage xRxedStructure, *pxRxedPointer;

   if( xStructQueue != NULL )
   {
      /* Receive a message from the created queue to hold complex struct AMessage
      structure.  Block for 10 ticks if a message is not immediately available.
      The value is read into a struct AMessage variable, so after calling
      xQueueReceive() xRxedStructure will hold a copy of xMessage. */
      if( xQueueReceive( xStructQueue,
                         &( xRxedStructure ),
                         ( TickType_t ) 10 ) == pdPASS )
      {
         /* xRxedStructure now contains a copy of xMessage. */
      }
   }

   if( xPointerQueue != NULL )
   {
      /* Receive a message from the created queue to hold pointers.  Block for 10
      ticks if a message is not immediately available.  The value is read into a
      pointer variable, and as the value received is the address of the xMessage
      variable, after this call pxRxedPointer will point to xMessage. */
      if( xQueueReceive( xPointerQueue,
                         &( pxRxedPointer ),
                         ( TickType_t ) 10 ) == pdPASS )
      {
         /* *pxRxedPointer now points to xMessage. */
      }
   }

   /* ... Rest of task code goes here. */
}

What I mean is that the normal usage of a queue is to put the data into it from a task, and read it from another. For putting structure into a queue, the structure must be allocated first. So i declare only a struct variable on the sender task, and I reuse it (overwrite) every time before sending it into the queue (that copy the content).
Sending a pointer of a struct is not such useful (in normal cases), because it would mean that I wrote a some kind of queue (circular buffer for example, using an array of a struct) in my code, that is exact implementation of the FreeRTOS queue.
Right now I can’t imagine a use case where the queue is used in a different way, but for sure it can be useful with pointers exchange too.

Right, I understand. The code was trying to show that for larger data you have the option of queuing a pointer to the data instead of the data itself - but then there are other issues you need to take care of (like who owns the data being pointed to). There is more information on this page https://www.freertos.org/Embedded-RTOS-Queues.html

I will add that I had one application where I had an array of message structures that I passed via pointers through queue, with one queue being used to hold a list of ‘free’ buffers managed by a sub-system. That subsystem, if asked for a buffer when none were available would log that fact, and see if the system had enough spare memory to dynamically allocate an additional buffer (and the buffer had a flag in it to indicate that it was an additional buffer, so it would be freed when the system returned it to the free list).

We had enough buffers of each type statically allocated to handle the specified request rate, with some margin, but rather than just failing at higher rates, it would try to use surplus resources to handle the requests, but still left records so we could make sure we never used the extra under the required conditions.