0
0
FreeRTOSprogramming~7 mins

Task notification vs queue performance in FreeRTOS

Choose your learning style9 modes available
Introduction

Task notifications and queues are ways tasks in FreeRTOS communicate. Understanding their speed helps you pick the best one for your program.

You want to send simple signals or small data between tasks quickly.
You need to send multiple messages or larger data chunks between tasks.
You want to avoid blocking a task for too long while waiting for data.
You want to optimize your system for speed and memory use.
You want to handle task synchronization efficiently.
Syntax
FreeRTOS
/* Task Notification Example */
void vTaskFunction(void *pvParameters) {
    uint32_t ulNotificationValue;
    for (;;) {
        /* Wait for notification */
        xTaskNotifyWait(0x00, 0xffffffff, &ulNotificationValue, portMAX_DELAY);
        /* Process notification value */
    }
}

/* Queue Example */
QueueHandle_t xQueue;

void vSenderTask(void *pvParameters) {
    int dataToSend = 100;
    for (;;) {
        xQueueSend(xQueue, &dataToSend, portMAX_DELAY);
    }
}

void vReceiverTask(void *pvParameters) {
    int receivedData;
    for (;;) {
        xQueueReceive(xQueue, &receivedData, portMAX_DELAY);
        /* Process receivedData */
    }
}

Task notifications are like fast signals with optional 32-bit data.

Queues can hold multiple items and are more flexible but slower.

Examples
This shows how to check if a queue is empty without waiting.
FreeRTOS
/* Empty queue scenario */
QueueHandle_t xQueue = xQueueCreate(5, sizeof(int));
int receivedValue;
if (xQueueReceive(xQueue, &receivedValue, 0) == pdPASS) {
    // Got data
} else {
    // Queue empty
}
Task waits for a single notification signal.
FreeRTOS
/* Single element notification */
uint32_t notificationValue = 0;
xTaskNotifyGive(taskHandle);
if (xTaskNotifyWait(0, 0xffffffff, &notificationValue, portMAX_DELAY) == pdTRUE) {
    // Notification received
}
Task blocks until it gets a notification.
FreeRTOS
/* Notification at task start */
// Task waits indefinitely for notification before proceeding
xTaskNotifyWait(0, 0xffffffff, NULL, portMAX_DELAY);
Shows what happens if you try to send to a full queue without waiting.
FreeRTOS
/* Queue full scenario */
QueueHandle_t xQueue = xQueueCreate(2, sizeof(int));
int data = 10;
xQueueSend(xQueue, &data, 0);
xQueueSend(xQueue, &data, 0);
BaseType_t result = xQueueSend(xQueue, &data, 0);
// result will be errQUEUE_FULL
Sample Program

This program creates two tasks: one waits for a task notification, the other waits for data from a queue. It sends a notification and queue data, then prints what each task receives.

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

QueueHandle_t xQueue;
TaskHandle_t xTaskHandle;

void vTaskNotificationReceiver(void *pvParameters) {
    uint32_t ulNotificationValue;
    printf("TaskNotificationReceiver: Waiting for notification...\n");
    xTaskNotifyWait(0x00, 0xffffffff, &ulNotificationValue, portMAX_DELAY);
    printf("TaskNotificationReceiver: Received notification with value %lu\n", ulNotificationValue);
    vTaskDelete(NULL);
}

void vQueueReceiver(void *pvParameters) {
    int receivedValue;
    printf("QueueReceiver: Waiting for queue data...\n");
    xQueueReceive(xQueue, &receivedValue, portMAX_DELAY);
    printf("QueueReceiver: Received queue data %d\n", receivedValue);
    vTaskDelete(NULL);
}

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

    xTaskCreate(vTaskNotificationReceiver, "NotifyReceiver", configMINIMAL_STACK_SIZE, NULL, 1, &xTaskHandle);
    xTaskCreate(vQueueReceiver, "QueueReceiver", configMINIMAL_STACK_SIZE, NULL, 1, NULL);

    printf("Sending notification to task...\n");
    xTaskNotifyGive(xTaskHandle);

    int dataToSend = 42;
    printf("Sending data to queue...\n");
    xQueueSend(xQueue, &dataToSend, 0);

    vTaskStartScheduler();

    // Should never reach here
    return 0;
}
OutputSuccess
Important Notes

Task notifications are faster because they avoid the overhead of queues and copying data.

Queues use more memory and CPU time but can hold multiple messages and larger data.

Common mistake: Using task notifications for large or multiple messages instead of queues.

Use task notifications for simple signaling or small data; use queues for complex or multiple messages.

Summary

Task notifications are lightweight and fast for simple signals.

Queues are flexible and can hold multiple or larger messages but are slower.

Choose based on your data size and communication needs.