Bird
Raised Fist0
FreeRTOSprogramming~7 mins

Queue blocking behavior (timeout) in FreeRTOS

Choose your learning style10 modes available
Introduction

Queues in FreeRTOS help tasks send and receive data safely. Blocking with timeout means a task waits for a limited time if the queue is full or empty, so it doesn't wait forever.

When a task needs to send data but the queue is full, and it should wait only a short time before trying again.
When a task wants to receive data but the queue is empty, and it should wait for new data only up to a certain time.
When you want to avoid a task getting stuck forever waiting for queue space or data.
When you want to balance responsiveness and waiting in multitasking systems.
Syntax
FreeRTOS
/* Create a queue */
QueueHandle_t xQueue = xQueueCreate( queue_length, item_size );

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

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

xTicksToWait is the maximum time to wait in ticks. Use 0 for no wait, portMAX_DELAY for indefinite wait.

Functions return pdTRUE if successful, pdFALSE if timeout occurred.

Examples
Try to send immediately. If queue is full, return failure.
FreeRTOS
/* Send with no wait (non-blocking) */
BaseType_t result = xQueueSend(xQueue, &data, 0);
Wait up to 100 ticks for space in the queue before failing.
FreeRTOS
/* Send with 100 tick timeout */
BaseType_t result = xQueueSend(xQueue, &data, 100);
Wait forever until data is available in the queue.
FreeRTOS
/* Receive with indefinite wait */
BaseType_t result = xQueueReceive(xQueue, &buffer, portMAX_DELAY);
Wait up to 50 ticks for data, then return failure if none arrives.
FreeRTOS
/* Receive with 50 tick timeout */
BaseType_t result = xQueueReceive(xQueue, &buffer, 50);
Sample Program

This program creates a queue with space for 1 integer. The receiver task waits up to 300 ticks for data. The sender task tries to send data with a 200 tick timeout. The receiver starts first and waits, then the sender sends data. The output shows the blocking behavior with timeout.

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

QueueHandle_t xQueue;

void vSenderTask(void *pvParameters) {
    int data_to_send = 100;
    BaseType_t send_result;

    printf("Sender: Trying to send data %d with 200 tick timeout...\n", data_to_send);
    send_result = xQueueSend(xQueue, &data_to_send, 200);

    if (send_result == pdTRUE) {
        printf("Sender: Data sent successfully.\n");
    } else {
        printf("Sender: Failed to send data (timeout).\n");
    }

    vTaskDelete(NULL);
}

void vReceiverTask(void *pvParameters) {
    int received_data = 0;
    BaseType_t receive_result;

    printf("Receiver: Waiting to receive data with 300 tick timeout...\n");
    receive_result = xQueueReceive(xQueue, &received_data, 300);

    if (receive_result == pdTRUE) {
        printf("Receiver: Received data: %d\n", received_data);
    } else {
        printf("Receiver: Failed to receive data (timeout).\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");

    xTaskCreate(vReceiverTask, "Receiver", configMINIMAL_STACK_SIZE, NULL, 1, NULL);
    vTaskDelay(50); // Delay to ensure receiver starts first
    xTaskCreate(vSenderTask, "Sender", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    vTaskStartScheduler();

    // Should never reach here
    printf("Scheduler ended unexpectedly.\n");
    return 0;
}
OutputSuccess
Important Notes

Time complexity: Sending and receiving are O(1) operations.

Space complexity: Depends on queue length and item size.

Common mistake: Using zero timeout when you want to wait, causing immediate failure.

Use blocking with timeout to avoid tasks getting stuck forever and to improve system responsiveness.

Summary

Queue blocking with timeout lets tasks wait for limited time when sending or receiving.

Use xTicksToWait to control how long a task waits before giving up.

This helps keep multitasking systems responsive and safe.

Practice

(1/5)
1. What does the xTicksToWait parameter control in FreeRTOS queue functions like xQueueReceive() or xQueueSend()?
easy
A. The number of items currently in the queue.
B. The size of the queue in bytes.
C. The maximum time a task will wait for the queue operation before timing out.
D. The priority of the task accessing the queue.

Solution

  1. Step 1: Understand the role of xTicksToWait

    This parameter specifies how long a task should wait if the queue is full (for send) or empty (for receive).
  2. Step 2: Relate to queue blocking behavior

    If the queue operation cannot proceed immediately, the task blocks for up to xTicksToWait ticks before timing out.
  3. Final Answer:

    The maximum time a task will wait for the queue operation before timing out. -> Option C
  4. Quick Check:

    Timeout duration = xTicksToWait [OK]
Hint: Remember: xTicksToWait sets wait time before giving up [OK]
Common Mistakes:
  • Confusing xTicksToWait with queue size
  • Thinking it sets task priority
  • Assuming it counts queue items
2. Which of the following is the correct way to call xQueueReceive() with a timeout of 10 ticks?
easy
A. xQueueReceive(queueHandle, &data);
B. xQueueReceive(queueHandle, data, 10);
C. xQueueReceive(queueHandle, &data, "10");
D. xQueueReceive(queueHandle, &data, 10);

Solution

  1. Step 1: Check function parameters

    xQueueReceive() requires the queue handle, pointer to data buffer, and timeout in ticks as a number.
  2. Step 2: Validate correct syntax

    xQueueReceive(queueHandle, &data, 10); correctly passes the address of data and numeric timeout 10 ticks.
  3. Final Answer:

    xQueueReceive(queueHandle, &data, 10); -> Option D
  4. Quick Check:

    Correct parameters and timeout type = xQueueReceive(queueHandle, &data, 10); [OK]
Hint: Use &data and numeric timeout for xQueueReceive [OK]
Common Mistakes:
  • Passing data instead of &data
  • Using string "10" instead of number 10
  • Omitting timeout parameter
3. Consider this code snippet:
if(xQueueReceive(queue, &item, 5) == pdPASS) {
    process(item);
} else {
    handleTimeout();
}
What happens if the queue is empty and no item arrives within 5 ticks?
medium
A. The function returns after 5 ticks with a failure code, and handleTimeout() is called.
B. The task blocks indefinitely waiting for an item.
C. The function returns immediately with pdPASS.
D. The queue is deleted automatically.

Solution

  1. Step 1: Analyze xQueueReceive behavior with timeout

    If the queue is empty, the task waits up to 5 ticks for an item to arrive.
  2. Step 2: Understand return values

    If no item arrives in 5 ticks, xQueueReceive() returns a failure code (not pdPASS), so handleTimeout() runs.
  3. Final Answer:

    The function returns after 5 ticks with a failure code, and handleTimeout() is called. -> Option A
  4. Quick Check:

    Timeout triggers failure return = The function returns after 5 ticks with a failure code, and handleTimeout() is called. [OK]
Hint: Timeout means failure return, so else branch runs [OK]
Common Mistakes:
  • Assuming indefinite block without timeout
  • Thinking pdPASS is returned on timeout
  • Believing queue deletes itself
4. Which of the following correctly describes this code snippet:
BaseType_t result = xQueueSend(queue, &data, 0);
if(result == pdFAIL) {
    // handle failure
}
medium
A. Using 0 as timeout means the task will wait forever.
B. Using 0 as timeout means the function returns immediately if the queue is full.
C. The timeout parameter should be a pointer, not a number.
D. The return value should be compared to pdPASS, not pdFAIL.

Solution

  1. Step 1: Understand timeout=0 behavior in xQueueSend

    A timeout of 0 means the function does not block; it returns immediately if the queue is full.
  2. Step 2: Check the error handling logic

    If the queue is full, xQueueSend() returns pdFAIL immediately, so the failure handling code runs correctly.
  3. Final Answer:

    Using 0 as timeout means the function returns immediately if the queue is full. -> Option B
  4. Quick Check:

    Timeout 0 means no wait, immediate return = Using 0 as timeout means the function returns immediately if the queue is full. [OK]
Hint: Timeout 0 means no wait, immediate fail if full [OK]
Common Mistakes:
  • Thinking 0 means wait forever
  • Confusing timeout type with pointer
  • Comparing return to wrong constant
5. You want a task to send data to a queue but only wait up to 20 ticks if the queue is full. If the queue remains full after 20 ticks, the task should perform an alternative action. Which code snippet correctly implements this behavior?
hard
A. if(xQueueSend(queue, &data, 20) == pdPASS) { // sent successfully } else { // alternative action }
B. if(xQueueSend(queue, &data, 0) == pdFAIL) { // alternative action } else { // sent successfully }
C. if(xQueueSend(queue, &data, portMAX_DELAY) == pdPASS) { // sent successfully } else { // alternative action }
D. if(xQueueSend(queue, &data, 20) == pdFAIL) { // sent successfully } else { // alternative action }

Solution

  1. Step 1: Understand desired behavior

    The task should wait up to 20 ticks to send data, then do alternative action if it fails.
  2. Step 2: Analyze each option

    if(xQueueSend(queue, &data, 20) == pdPASS) { // sent successfully } else { // alternative action } waits 20 ticks and checks for pdPASS to confirm success; else runs alternative action. if(xQueueSend(queue, &data, 0) == pdFAIL) { // alternative action } else { // sent successfully } waits 0 ticks (no wait). if(xQueueSend(queue, &data, portMAX_DELAY) == pdPASS) { // sent successfully } else { // alternative action } waits forever. if(xQueueSend(queue, &data, 20) == pdFAIL) { // sent successfully } else { // alternative action } reverses success/failure logic.
  3. Final Answer:

    if(xQueueSend(queue, &data, 20) == pdPASS) { // sent successfully } else { // alternative action } -> Option A
  4. Quick Check:

    Wait 20 ticks, success check = if(xQueueSend(queue, &data, 20) == pdPASS) { // sent successfully } else { // alternative action } [OK]
Hint: Wait 20 ticks, check for pdPASS to confirm send success [OK]
Common Mistakes:
  • Using 0 ticks instead of 20
  • Waiting forever with portMAX_DELAY
  • Mixing up pdPASS and pdFAIL checks
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