xQueueSend parameter passing

Hi,
when using xQueueSend (or similar functions) and need to send data to the queue, you can send for example a INT or a struct. The API says it passes by value which ensures that a variable does NOT need to persist after the xQueueSend() call. Correct?

Couple of questions:

1)In the API it shows that you need to cast it to (void*). Would the following also work safely or not?
If not, why do you need to cast it to (void*) if you already providing the address?

struct
{
    uint32_t u32_MessageID;
    uint32_t u32_Payload;
} xMotorMessage;

FunctionSendStruct(void)
{
          xDispatcherMessage msg;
          msg. u32_MessageID = CMD_SET_TORQUE;
          msg. u32_Payload = VALUE_START_TORQUE;
          xQueueSend(xMotorQueue,
                                 &msg,
                                 portMAX_DELAY);
}
  1. what is the correct & safe way to pass a literal (instead of defining a variable and passing its address)? Is the following correct? Or would it fetch the value at address 0x45?
#define CMD_TURN_ON    45

FunctionSendIntegerCmd(void)
{
         xQueueSend(xMeterQueue,
                     (void*) CMD_TURN_ON,
                     portMAX_DELAY);
}

Thank you :slight_smile:

Using queues to transfer items by value or by reference/pointer is explained in the FreeRTOS docs. See the example code there FreeRTOS - Open Source Software for Embedded Systems - FreeRTOS xQueueSend() API function descriptions
In short FreeRTOS queues always copy over the item data given by its address of the size defined on creation. You can easily verify that by looking up the code.
So you can’t blindly cast a literal value to an void* pointer to send it via a queue. This is a license to crash :wink:
Using void* arguments is common practice in C-programs when dealing with addresses of any resp. unknown typed variables/objects.

Thank you Hartmut,
I did read the API before and again now but what is not clear is still why does the API example that passes a structure passes the address but casts it to a (void*) too? I don’t understand the reason for the casting.

And re. the second point, passing a literal is then not possible. You must declare a variable first then pass its address. correct? The reason for asking that second point in the first place is that in two separate posts people were doing that and I thought it was wrong but worth asking. So I can only declare a variable and pass its address, not possible to pass a literal directly correct?

Apologies for the sometime trivial/stupid questions. And thank you as always! :slight_smile:

  1. I see your point. I didn’t try but I think acc. to the C/C++ standard the explicit cast of a (typed) struct pointer to void* isn’t necessary in this case. Maybe it’s in the example for documentation/clarification.
  2. You’ve to provide the memory (the address of that piece of memory) where the item to enqueue resides because the FreeRTOS queue (send) code copies the item (with the size specified on queue creation) from that memory into the queue. The same applies vice versa to queue receive.
    FreeRTOS queues have no idea about the type of the queue items. They’re generic and handle all types of items just by dealing with them as binary blocks of data copied in and out a queue.
    I’m curious: In which posts people posted the code passing literal values to queues ?

I believe the reason for the casts is the coding convention they are using says to not rely on implied conversions but to make them explicitly.

The key thing to remember is that the functions are really defined as ultimately using an array of bytes that are copied into and out of the queue, and we pass to the function that ADDRESS of that array. C doesn’t allow the passing of the address of a constant numeric literal.

Thank you both!

Hartmut,
this is one of the forums I came across that sparked my original question (LINK UPDATED - NO IDEA HOW IT PASTED THE LINK OF THIS THREAD INSTEAD):

Thank you

@hs2
As I was re-reading your replies I just noticed that the link I posted in the reply above was the link of this very thread. No idea how I did that.

Anyway, I updated the link. This is one of the two places where I originally saw passing literal to a function taking a (void*). That was what sparked my original question (see the first of the answers starting with “Both C and C++ standards explicitly allow for such conversion.”.

Thank you as always! :slight_smile:

That is talking about a very different thing. There are a number of places where FreeRTOS takes a void* parameter which is just passed to a user provided function as a user provided bit of information, and that is all FreeRTOS does with that. For THAT case, that pointer value can also be an integer value that has been cast to a pointer. That is very different then the queue send case, as QueueSend does access the pointer, as it sends the data that the pointer points to, not the pointer itself.

Thank you Richard,
yes that makes sense!

Thank you