2024-04-02 07:25 PM
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
2024-04-03 01:23 AM
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.
2024-04-03 01:37 AM
2024-04-03 06:08 AM
Thanks Danish
I will check it today.
2024-04-03 06:13 AM - last edited on 2024-04-05 08:01 AM by SofLit
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 ) )
{
..
}
2024-04-03 06:31 AM - edited 2024-04-03 07:26 AM
Please post your code - using this button:
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
2024-04-03 07:17 AM - edited 2024-04-03 07:28 AM
@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.
2024-04-05 07:42 AM - last edited on 2024-04-05 08:02 AM by SofLit
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
2024-04-05 07:55 AM
Did you miss how to properly post source code:
Please post your code - using this button:
@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.