I am new to FreeRTOS and learning queues at the moment. I have a Task_3 who send 5 integers to the queue and Task 4 who reads the queue and prints the values read. Problem is that i write 0..4 to the queue but the Task 4 reads on all 5 positions of the queue the value 5. Why not 0..4 ?
The send task 3
void task_3(void *args)
{
uint32_t count = 0;
uint32_t *Value;
Value = &count;
ESP_EARLY_LOGI(TAG, "Task 3 entered..");
if (myQueue_2 == NULL)
{
printf("myQueue_2 could not be created !\n");
}
ESP_EARLY_LOGI("TASK 3", "Data waiting in myQueue_2_1 : %d, Space available : %d", uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2));
for (count = 0; count < 5;count++)
{
ESP_EARLY_LOGI("TASK 3", "Value = %d\n", *Value);
xQueueSend(myQueue_2, (void*)&Value, (TickType_t)0);
}
ESP_EARLY_LOGI("TASK 3", "Data waiting in myQueue_2_1 : %d, Space available : %d",
uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2));
while (1)
{
vTaskDelay(pdMS_TO_TICKS(500));
}
}
Output of Task 3
I (0) TASK 3: Data waiting in myQueue_2_1 : 0, Space available : 5
I (10) TASK 3: Value = 0
I (10) TASK 3: Value = 1
I (20) TASK 3: Value = 2
I (20) TASK 3: Value = 3
I (20) TASK 3: Value = 4
The read task 4
void task_4(void *args)
{
uint32_t *RxValue = NULL;
while (1)
{
vTaskDelay(pdMS_TO_TICKS(500));
if (uxQueueMessagesWaiting(myQueue_2) > 0)
{
xQueueReceive(myQueue_2, &RxValue, (TickType_t)5);
ESP_EARLY_LOGI("TASK 4", "Received from myQueue_2 = %d\n", *RxValue);
ESP_EARLY_LOGI("TASK 4", "Data waiting in myQueue_2 : %d, Space available : %d",
uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2));
}
}
}
Output of task 4
I (30) TASK 3: Data waiting in myQueue_2_1 : 5, Space available : 0
I (1300) TASK 4: Received from myQueue_2 = 5
I (1300) TASK 4: Data waiting in myQueue_2 : 4, Space available : 1
I (1800) TASK 4: Received from myQueue_2 = 5
I (1800) TASK 4: Data waiting in myQueue_2 : 3, Space available : 2
I (2300) TASK 4: Received from myQueue_2 = 5
I (2300) TASK 4: Data waiting in myQueue_2 : 2, Space available : 3
I (2800) TASK 4: Received from myQueue_2 = 5
I (2800) TASK 4: Data waiting in myQueue_2 : 1, Space available : 4
I (3300) TASK 4: Received from myQueue_2 = 5
I (3300) TASK 4: Data waiting in myQueue_2 : 0, Space available : 5
xQueueSend()
sends a pointer to a value, not the value itself. It doesn't make a copy of what's being pointed to. If the value that's pointed to changes before the queue is read, the reader will see the new value.
Your code enqueues the same five pointers to the variable count
, not five copies of the value of count
. By the time task_4
runs, count
is equal to 5. So task_4
reads 5 each time.
The correct way to do this is to pass a different pointer each time. You might malloc()
the value each time and free it:
for (count = 0; count < 5;count++)
{
uint32_t *value = (uint32_t *)malloc(sizeof(uint32_t));
if (value) {
*value = count;
ESP_EARLY_LOGI("TASK 3", "Value = %d\n", *value);
xQueueSend(myQueue_2, (void*)&Value, (TickType_t)0);
} else {
ESP_EARLY_LOGI("TASK 3", "malloc failed");
}
}
and
while (1)
{
vTaskDelay(pdMS_TO_TICKS(500));
if (uxQueueMessagesWaiting(myQueue_2) > 0)
{
xQueueReceive(myQueue_2, &RxValue, (TickType_t)5);
ESP_EARLY_LOGI("TASK 4", "Received from myQueue_2 = %d\n", *RxValue);
ESP_EARLY_LOGI("TASK 4", "Data waiting in myQueue_2 : %d, Space available : %d",
uxQueueMessagesWaiting(myQueue_2), uxQueueSpacesAvailable(myQueue_2));
free(RxValue);
}
}
The first code fragment allocates storage and enqueues it each time, so each item queued will be different. It's extremely important that the second code fragment free the storage, otherwise the program will leak memory and eventually run out of it.
Since a pointer is large enough to store uint32_t
, you could also just cast the counter to be void *
and cast it back to uint32_t
in the receiving task. If you want to pass anything larger than a pointer you'll need to malloc()
it and initialize it or do your own memory management of the objects you want to pass.