cancel
Showing results for 
Search instead for 
Did you mean: 

Queue usage fault

Ofer
Associate III

Hi

I use free-rtos with stm32wb55.

I use some queues, they all behave as expected except for one of them (led driver queue).

It seemed that some of the messages being sent (to the led driver queue) are ignored or missed.

I added a debug code and found out that the number of messages being sent to the queue is equal to the messages being received but the content being sent is sometime different. I explored it and found out that messages being sent shortly one after another are being "recieved" the same as the last: for example: if 3 messages being sent (with no delay between them) it is received as 3 same messages which are equal to the last message (from the 3 messages).

A delay between mesaages sending sometimes help.

What can be the problem ? 

Thanks

8 REPLIES 8
Danish1
Lead II

Disclaimer: I don't use free-rtos.

I guess that the queue you are using simply stores a pointer to the message, not the message itself.

So when you re-use that memory to post another message, your first message is overwritten by the new message.

If this is indeed the cause, then you should never use "automatic" variables to store such messages. By that I mean a (non-static) variable that is declared inside a function. The reason being that such variables "go out of scope" when you exit the function and the memory risks being overwritten by other variable in the next function that is called.

How "should" such a message-queue be used? See the free-rtos documentation. One way would be to dynamically allocate (malloc) the memory for each message. And free the memory once you have processed the message. But I dislike using dynamic memory in embedded systems.

Andrew Neil
Evangelist III

@Ofer wrote:

What can be the problem ? 


You haven't shown your code - so we can only guess at what might be going on in it!

@Danish1 's  guess is plausible.

Please  post your code - using this button:

AndrewNeil_0-1712133408682.png

 

 

Thanks Danish

I will check it today.

Hi Andrew

There is my probematic code:

 

void LED_DRIVER::led_driver_start_sequence( LED_DRIVER_COMMAND led_driver_command , LED_COLOR led_color , uint8_t parameter )

{

static LED_DRIVER_ACTIVATION led_driver_record = { led_driver_command , led_color , parameter };

BaseType_t HigherPriorityTaskWoken = pdTRUE;

led_driver_record.led_driver_command = led_driver_command;

led_driver_record.led_color = led_color;

led_driver_record.parameter = parameter;

LED_DRIVER_ACTIVATION *led_driver_activation = &led_driver_record;

aaa = 0;

osDelay(INTERVAL_TIME_BETWEEN_ISOFIX_LEDS);

xQueueSendFromISR( static_cast<QueueHandle_t>(led_driver_queueHandle) , &led_driver_activation , &HigherPriorityTaskWoken );

}



void LED_DRIVER::led_driver_leds_sequence_activation()

{

static LED_DRIVER_ACTIVATION *led_driver_activation;

if( xQueueReceive( static_cast<QueueHandle_t>(led_driver_queueHandle) , &led_driver_activation , portMAX_DELAY ) )

{

..

}

Please  post your code - using this button:

AndrewNeil_0-1712150699115.png

 

Like @Danish1 , I don't use FreeRTOS but it does look like his guess about the queue using a pointer could be correct.

So, even though your led_driver_record is static, you have only a single record;  therefore the pointer will get whatever is the latest thing to have been written into that single record - not the thing that was there at the time of the xQueueSendFromISR call.

EDIT

You haven't shown your definition of LED_DRIVER_ACTIVATION 


@Andrew Neil wrote:

Like @Danish1 , I don't use FreeRTOS but it does look like his guess about the queue using a pointer could be correct.

 


Nope - The FreeRTOS documentation says:

"Items are queued by copy not reference" 

However, I think your problem is here:

 

 

LED_DRIVER_ACTIVATION *led_driver_activation = &led_driver_record;

 

 

So you've created a pointer to your led_driver_record

But then you pass the address of that pointer to the queue-send function:

 

 

xQueueSendFromISR( static_cast<QueueHandle_t>(led_driver_queueHandle) , &led_driver_activation , &HigherPriorityTaskWoken );

 

 

So you are defeating the FreeRTOS "queue-by-copy" and turning it into a queue-by-reference - and that's going to fail for the reason I said earlier.

 

 

Dear Andrew

I tried using a local variable and I got trash data.

When I tried dynamic allocation, it seems to solve the problem:

void LED_DRIVER::led_driver_start_sequence( LED_DRIVER_COMMAND led_driver_command , LED_COLOR led_color , uint8_t parameter )

{

LED_DRIVER_ACTIVATION *led_driver_record = new LED_DRIVER_ACTIVATION { led_driver_command , led_color , parameter };

xQueueSendFromISR( static_cast<QueueHandle_t>(led_driver_queueHandle) , &led_driver_record , pdFALSE );

}

Is there a way to do it without a dynamic allocation ?

 

Thanks

 

Did you miss how to properly post source code:

Please  post your code - using this button:

AndrewNeil_0-1712328783624.png

 


@Ofer wrote:

Is there a way to do it without a dynamic aloocation ?


Yes - don't make the mistake which I described in my previous post:

 

So you are defeating the FreeRTOS "queue-by-copy" and turning it into a queue-by-reference - and that's going to fail for the reason I said earlier.