The producer-consumer pattern helps two parts of a program work together smoothly. One part makes data (producer), and the other uses it (consumer). This keeps things organized and avoids problems when both work at the same time.
Producer-consumer pattern in FreeRTOS
/* Create a queue */ QueueHandle_t xQueue = xQueueCreate(queue_length, item_size); /* Producer task */ void vProducerTask(void *pvParameters) { DataType data; for(;;) { // Prepare data xQueueSend(xQueue, &data, portMAX_DELAY); } } /* Consumer task */ void vConsumerTask(void *pvParameters) { DataType receivedData; for(;;) { if(xQueueReceive(xQueue, &receivedData, portMAX_DELAY) == pdPASS) { // Process receivedData } } }
Use xQueueCreate() to make a queue that holds data between producer and consumer.
xQueueSend() adds data to the queue; xQueueReceive() takes data out safely.
QueueHandle_t xQueue = xQueueCreate(5, sizeof(int)); void vProducerTask(void *pvParameters) { int value = 0; for(;;) { xQueueSend(xQueue, &value, portMAX_DELAY); value++; vTaskDelay(pdMS_TO_TICKS(100)); } }
void vConsumerTask(void *pvParameters) {
int receivedValue;
for(;;) {
if(xQueueReceive(xQueue, &receivedValue, portMAX_DELAY) == pdPASS) {
// Use receivedValue here
}
}
}This program creates a queue for 3 integers. The producer task sends numbers every 500 milliseconds. The consumer task receives and prints them. The queue safely passes data between tasks.
#include "FreeRTOS.h" #include "task.h" #include "queue.h" #include <stdio.h> QueueHandle_t xQueue; void vProducerTask(void *pvParameters) { int value = 1; for(;;) { xQueueSend(xQueue, &value, portMAX_DELAY); printf("Produced: %d\n", value); value++; vTaskDelay(pdMS_TO_TICKS(500)); } } void vConsumerTask(void *pvParameters) { int receivedValue; for(;;) { if(xQueueReceive(xQueue, &receivedValue, portMAX_DELAY) == pdPASS) { printf("Consumed: %d\n", receivedValue); } } } int main(void) { xQueue = xQueueCreate(3, sizeof(int)); if(xQueue == NULL) { printf("Queue creation failed!\n"); return 1; } xTaskCreate(vProducerTask, "Producer", 1000, NULL, 1, NULL); xTaskCreate(vConsumerTask, "Consumer", 1000, NULL, 1, NULL); vTaskStartScheduler(); for(;;); return 0; }
Make sure the queue size fits your data flow to avoid blocking tasks too long.
Use portMAX_DELAY to wait indefinitely for queue operations.
Always check if queue creation succeeds before using it.
The producer-consumer pattern helps tasks share data safely using queues.
Producers send data to the queue; consumers receive and process it.
FreeRTOS queues handle synchronization so tasks don't interfere with each other.