Send a struct through Queue

Hi there I am new to this forum and I am already bring some problems that I have been facing while exploring FreeRTOS on my STM32F4: I want to pass a simple structure from one task to anoder. Actually am I followyig by the book (I think….) what is told on FreeRTOS API suport: This is shortest example fo what I am doing:
    #define WHEEL_PERIMETER    100

    struct ENCODER_Motion 
    {
        float    Current_Speed;
        float    Current_Direction;
    } ENCODER_MOTION_Read;

    QueueHandle_t     xQueueENCODER_Readings;

    int main (void)
    {
        ... Initiate system configuration ...

        xQueueENCODER_Readings  = xQueueCreate( 10  , sizeof( struct ENCODER_Motion* ) );

        if ( xQueueENCODER_Readings == 0)
            ... flags with a flashing led;

        ... creates Task_A and Task_B and lauches scheduler....

        while (1);
    }

    void Task:A ( void *pvParameters ) 
    {
        struct      ENCODER_Motion   *ENCODER_MOTION_NOW;

        float RPM ;
        float DIRECTION ;

        while (1)
        {
            ... Reads Encoder to RPM and DIRECTION ...

            ENCODER_MOTION_Read.Current_Speed = RPM * WHEEL_PERIMETER;
            ENCODER_MOTION_Read.Current_Direction = DIRECTION;

            if ( xQueueENCODER_Readings != 0 ) 
            {
                ENCODER_MOTION_NOW = &ENCODER_MOTION_Read;  
                xQueueSend ( xQueueENCODER_Readings , (void *) &ENCODER_MOTION_NOW , 
                                         (TickType) 10 );
            }

        }

    void Task:B ( void *pvParameters ) 
    {
        struct      ENCODER_Motion   *ENCODER_Received;
        float SPEED_RECEIVED;
        float DIRCTION_RECEIVED;

        while (1)
        {
            if ( xQueueENCODER_Readings )
                {
                    if ( uxQueueMessagesWaiting ( xQueueENCODER_Readings ) )    
                    {
                        if (xQueueReceive ( xQueueENCODER_Readings , &(ENCODER_Received) , 
                                                        QUEUE_TIME_TO_WAIT_10 ) );
                        {
                            SPEED_RECEIVED = ENCODER_Received->Current_Speed;
                            DIRCTION_RECEIVED = ENCODER_Received->Current_Direction;
                        }

                }
            }
        }
My problems that; passing the struck though the queue or not (not calling the xQueueSend on TaskA) I still receive on TASKB the information saved at this point of may code
            ENCODER_MOTION_Read.Current_Speed = RPM * WHEEL_PERIMETER;
            ENCODER_MOTION_Read.Current_Direction = DIRECTION;
It seems I am saving the data on a Global variable (structure) and not sending a pointer to a strcuture – one of the 10 that was created when I called xQueueCreat. I tryed not using pointer on the TASK_B but it receives trash. Any help will be highly appreciated Thanks

Send a struct through Queue

In your code you are only creating one structure, then sending pointers to that one structure through the queue. All the pointers will be pointing to the same structure, and reading anything out from the structure will result in whatever value was last written to the structure by any task (all tasks are accessing the same one). Is this correct? If the structure is small you might be better of sending the structure itself, so each time you send the structure to the queue you send a copy of a strcture, rather than a pointer to a single structure. So the queue would be created as: // The * has been removed xQueueENCODERReadings = xQueueCreate( 10 , sizeof( struct ENCODERMotion) ); Then Task a can do this to send a copy of its local variable, rather than a pointer to it, to the queue
void Task:A ( void *pvParameters ) 
{
    struct      ENCODER_Motion   ENCODER_MOTION_NOW;
    
    for( ;; )
    {
        ENCODER_MOTION_NOW.Current_Speed = // whatever
        ENCODER_MOTION_NOW.Current_Direction = // whatever
    
        // Send a copy of the queue to the other task.
        xQueueSend ( xQueueENCODER_Readings , 
                    (void *) &ENCODER_MOTION_NOW , 
                    (TickType) 10 );
        
        // Reset of code follows
And Task B can receive a copy into its own local variable, as follows:
void Task:B ( void *pvParameters ) 
{
struct      ENCODER_Motion   ENCODER_Received;

    while (1)
    {
        if (xQueueReceive ( xQueueENCODER_Readings , 
                           &(ENCODER_Received) , 
                           QUEUE_TIME_TO_WAIT_10 ) );
                           
        // Reset of code follows
I think if you wanted to queue pointers, maybe for efficiency reasons, then you would have to have a set of structures available that could be pointed to, so no two tasks point to the same structure at the same time – or perhaps dynamically allocate a structure then send a pointer to the dynamically allocated structure, and have the receiving task free the dynamically allocated structure again after it has received it. Regards.

Send a struct through Queue

Thank you so much for your reply. Your solution worked perfectly! Thank you again. Indeed I was intending to use pointers due to efficiency issues. Actually the example above was the smallest and maybe the simpliest situation. This is the first time I saw this kind of buggy behaviour – accessing globaly to the same structure through those pointers which were indeed pointing precisely to the same strucutre. In my aplication I need to pass arge structures from TASKA, TASKB and TASKC to TASKD and this last one will gather all information and process it. I was trying to use a single Queue, common to all tasks A, B and C, which will be used to send the data to task D. The strucutre has a sort of task ID to identify from where that information came. So please confirm if I undertood it right: it is recomended to create several structures associated to each task A, B and C. Then send each pointer through the same queue to task D. Thank you once again for your important support Regards

Send a struct through Queue

If you want to send pointers to structures then you can create a pool of structures, and tag each structure as available or in use

define MAX_STRUCTS 5

// The pool of structs ENCODERMOTIONRead mystructs[ MAXSTRUCTS ]; // Available flags bool isinuse[ MAX_STRUCTS ] = { false }; ENCODERMOTIONRead *get_struct(void){ int i;
// Find the next free struct
for(i=0; i<MAX_STRUCTS; i++){
    if(is_in_use[i]==false){
       // Mark struct in use and return it
       is_in_use[i]=true;
       return &my_structs[i];
    }
}

// All in use
return NULL;
} void freestruct(ENCODERMOTIONRead *torelease){ int i;
// Find the struct being freed
for(i=0; i<MAX_STRUCTS; i++){
    if(to_release==&my_structs[i]){
       // Mark struct not in use
       is_in_use[i]=false;
       return;
    }
}
} To send a pointer to a structure, call get_struct to get a struct from the pool, fill the struct with data, then send a pointer to the struct to the queue. At the other end of the queue, read out the data from the struct, then call free_struct() to return the stuct to the pool. This implementation is very crude but ok if MAX_STRUCTS is small.

Send a struct through Queue

If each task is sending the same sort of data, there is no need for multiple queues, and in fact multiple queues can make you life harder. My general rules as each source of asyncronous data should have a single task dedicated to it. Whether to send a structure or a pointer is largely dependent on how much data is in the structure. Two floats isn’t bad. Sending structures is simpler in that you normally don’t need to deal with life management of the data structures. Passing pointers may be quicker if there is much data in the structure, OR if the structure deals with pointers to itself or other data buffers. (And when dealing wth pointers to buffers, I find the simplest way to keep track of the free buffers is to put the pointers into another queue, that you take from to get a buffer and put to in order to free a buffer)