Bird
Raised Fist0
FreeRTOSprogramming~7 mins

Queue full and empty handling in FreeRTOS

Choose your learning style10 modes available
Introduction

Queues help tasks send and receive data safely. Handling full and empty queues prevents errors and keeps tasks running smoothly.

When a task sends data but the queue is already full.
When a task tries to receive data but the queue is empty.
When you want to wait for space or data in a queue with a timeout.
When you want to avoid losing data or blocking tasks forever.
When managing communication between tasks or interrupts.
Syntax
FreeRTOS
/* Queue creation */
QueueHandle_t xQueue = xQueueCreate( queue_length, item_size );

/* Sending to queue */
BaseType_t xQueueSend( QueueHandle_t xQueue, const void * pvItemToQueue, TickType_t xTicksToWait );

/* Receiving from queue */
BaseType_t xQueueReceive( QueueHandle_t xQueue, void * pvBuffer, TickType_t xTicksToWait );

xQueueSend returns pdTRUE if data was sent, or errQUEUE_FULL if the queue is full.

xQueueReceive returns pdTRUE if data was received, or pdFALSE if the queue is empty.

Examples
This tries to send data immediately. If the queue is full, it returns without waiting.
FreeRTOS
/* Example: Sending with zero wait time (non-blocking) */
if (xQueueSend(xQueue, &data, 0) != pdTRUE) {
    // Queue full, handle error
}
This waits up to 100 milliseconds for data. If none arrives, it returns indicating the queue is empty.
FreeRTOS
/* Example: Receiving with wait time */
if (xQueueReceive(xQueue, &receivedData, pdMS_TO_TICKS(100)) == pdTRUE) {
    // Data received
} else {
    // Queue empty after waiting 100 ms
}
Shows how to detect and handle a full queue immediately.
FreeRTOS
/* Edge case: Sending when queue is full */
BaseType_t result = xQueueSend(xQueue, &data, 0);
if (result != pdTRUE) {
    // Handle full queue, e.g., discard or retry later
}
Shows how to detect and handle an empty queue immediately.
FreeRTOS
/* Edge case: Receiving when queue is empty */
BaseType_t result = xQueueReceive(xQueue, &data, 0);
if (result != pdTRUE) {
    // Handle empty queue, e.g., wait or skip
}
Sample Program

This program creates a queue with space for 1 integer. It tries to receive from the empty queue first, then sends data, tries to send again when full, and receives twice. It prints messages showing full and empty queue handling.

FreeRTOS
#include "FreeRTOS.h"
#include "queue.h"
#include "task.h"
#include <stdio.h>

QueueHandle_t xQueue;

void vSenderTask(void *pvParameters) {
    int dataToSend = 100;
    printf("Sender: Trying to send %d\n", dataToSend);
    if (xQueueSend(xQueue, &dataToSend, 0) == pdTRUE) {
        printf("Sender: Data sent successfully\n");
    } else {
        printf("Sender: Queue full, cannot send data\n");
    }
    vTaskDelete(NULL);
}

void vReceiverTask(void *pvParameters) {
    int receivedData = 0;
    printf("Receiver: Trying to receive data\n");
    if (xQueueReceive(xQueue, &receivedData, 0) == pdTRUE) {
        printf("Receiver: Received data %d\n", receivedData);
    } else {
        printf("Receiver: Queue empty, no data to receive\n");
    }
    vTaskDelete(NULL);
}

int main(void) {
    xQueue = xQueueCreate(1, sizeof(int));
    if (xQueue == NULL) {
        printf("Failed to create queue\n");
        return 1;
    }

    printf("Queue created with length 1\n");

    // First, receive from empty queue
    vReceiverTask(NULL);

    // Then, send data
    vSenderTask(NULL);

    // Try sending again to full queue
    vSenderTask(NULL);

    // Receive data
    vReceiverTask(NULL);

    // Receive again from empty queue
    vReceiverTask(NULL);

    return 0;
}
OutputSuccess
Important Notes

Time complexity for sending or receiving is O(1) because it just adds or removes one item.

Space complexity depends on queue length and item size.

Common mistake: Not checking return values, which can cause lost data or blocked tasks.

Use blocking waits if you want tasks to wait for space or data; use zero wait for non-blocking checks.

Summary

Always check if the queue is full before sending or empty before receiving.

Use the wait time parameter to control blocking behavior.

Proper handling keeps tasks responsive and prevents data loss.

Practice

(1/5)
1. In FreeRTOS, what happens if you try to send an item to a queue that is already full without waiting?
easy
A. The send operation fails immediately and returns an error.
B. The queue automatically expands to fit the new item.
C. The oldest item in the queue is overwritten.
D. The task sending the item is suspended indefinitely.

Solution

  1. Step 1: Understand queue full behavior

    When a queue is full, FreeRTOS does not allow new items to be added without waiting or handling the error.
  2. Step 2: Check send operation without wait

    If the send function is called with zero wait time and the queue is full, it returns immediately with an error indicating failure.
  3. Final Answer:

    The send operation fails immediately and returns an error. -> Option A
  4. Quick Check:

    Queue full + no wait = send fails [OK]
Hint: Send with zero wait fails if queue is full [OK]
Common Mistakes:
  • Assuming queue grows automatically
  • Thinking oldest data is overwritten
  • Believing task suspends indefinitely
2. Which of the following is the correct way to receive an item from a FreeRTOS queue with a block time of 10 ticks?
easy
A. xQueueReceive(queue, &item, 10);
B. xQueueReceive(queue, item, 10);
C. xQueueReceive(queue, &item, 0);
D. xQueueReceive(queue, &item, -1);

Solution

  1. Step 1: Understand xQueueReceive parameters

    The function takes the queue handle, a pointer to the variable to store the item, and the block time in ticks.
  2. Step 2: Identify correct syntax

    Passing &item as the second argument is correct to provide the address. Block time 10 means wait up to 10 ticks.
  3. Final Answer:

    xQueueReceive(queue, &item, 10); -> Option A
  4. Quick Check:

    Pointer + block time 10 = correct receive call [OK]
Hint: Use &item and positive ticks for blocking receive [OK]
Common Mistakes:
  • Passing item instead of &item
  • Using zero or negative block time incorrectly
  • Confusing send and receive parameters
3. Consider the following code snippet:
QueueHandle_t queue = xQueueCreate(2, sizeof(int));
int val = 10;
xQueueSend(queue, &val, 0);
val = 20;
xQueueSend(queue, &val, 0);
val = 30;
BaseType_t result = xQueueSend(queue, &val, 0);
What is the value of result after the last send call?
medium
A. pdPASS (send succeeded)
B. errQUEUE_FULL (send failed due to full queue)
C. pdFAIL (generic failure)
D. Block indefinitely until space is available

Solution

  1. Step 1: Analyze queue creation and sends

    The queue can hold 2 integers. Two sends with zero wait fill it completely.
  2. Step 2: Evaluate last send with zero wait

    The third send tries to add an item when the queue is full and does not wait, so it fails returning errQUEUE_FULL.
  3. Final Answer:

    errQUEUE_FULL (send failed due to full queue) -> Option B
  4. Quick Check:

    Queue full + zero wait = send fails with errQUEUE_FULL [OK]
Hint: Queue size 2 + 3 sends with zero wait = last send fails [OK]
Common Mistakes:
  • Assuming last send blocks
  • Thinking last send overwrites data
  • Confusing pdPASS and pdFAIL
4. Given this code snippet, why does xQueueReceive never return pdPASS?
QueueHandle_t queue = xQueueCreate(1, sizeof(int));
int data;

// Task A
xQueueReceive(queue, &data, 0);

// Task B
int val = 5;
xQueueSend(queue, &val, 0);
medium
A. xQueueSend is called with zero wait time, so it fails.
B. Queue size is too small to hold any data.
C. xQueueReceive is called with incorrect pointer.
D. Task A tries to receive before Task B sends, queue is empty, no wait time.

Solution

  1. Step 1: Understand queue state at receive

    Task A calls receive immediately with zero wait, but queue is empty because Task B hasn't sent yet.
  2. Step 2: Effect of zero wait on empty queue

    With zero wait, receive returns immediately with failure since no data is available yet.
  3. Final Answer:

    Task A tries to receive before Task B sends, queue is empty, no wait time. -> Option D
  4. Quick Check:

    Receive zero wait + empty queue = no pdPASS [OK]
Hint: Receive zero wait on empty queue always fails [OK]
Common Mistakes:
  • Thinking queue size 1 means no data can be stored
  • Assuming send fails with zero wait
  • Confusing pointer usage in receive
5. You want to design a FreeRTOS task that sends sensor data to a queue but must never block if the queue is full. Which approach correctly handles the queue full condition?
hard
A. Increase the queue size dynamically when full.
B. Use xQueueSend with portMAX_DELAY to wait indefinitely until space is available.
C. Use xQueueSend with zero block time and check the return value to discard data if full.
D. Use xQueueOverwrite to replace the oldest data in the queue automatically.

Solution

  1. Step 1: Understand non-blocking send requirement

    The task must never block, so waiting indefinitely or for a long time is not allowed.
  2. Step 2: Choose correct send method and handling

    Using xQueueSend with zero block time returns immediately. Checking the return value lets the task discard data if the queue is full.
  3. Step 3: Evaluate other options

    Use xQueueSend with portMAX_DELAY to wait indefinitely until space is available. blocks indefinitely, violating requirement. Use xQueueOverwrite to replace the oldest data in the queue automatically. overwrites data but may lose important info. Increase the queue size dynamically when full. is not supported by FreeRTOS.
  4. Final Answer:

    Use xQueueSend with zero block time and check the return value to discard data if full. -> Option C
  5. Quick Check:

    Non-blocking send + check return = safe discard [OK]
Hint: Send zero wait + check return to avoid blocking [OK]
Common Mistakes:
  • Using blocking send when non-blocking needed
  • Assuming queue size can grow dynamically
  • Ignoring return value of send
Recommended

Ready to prove it?

Pass the test and this pattern moves unknown strong while earning +1 Grip toward your certificate.

10 questions~5 mineasy hard