0
0
FreeRTOSprogramming~7 mins

ulTaskNotifyTake() for binary/counting notification in FreeRTOS

Choose your learning style9 modes available
Introduction

ulTaskNotifyTake() helps a task wait for a signal or event from another task or interrupt. It makes tasks sleep until something important happens.

When a task needs to wait for a simple yes/no signal from another task.
When a task should wait for multiple signals and count how many happened.
When you want to avoid busy waiting and save CPU by sleeping until notified.
When synchronizing tasks without using heavy mechanisms like semaphores.
When an interrupt signals a task to start work or update data.
Syntax
FreeRTOS
uint32_t ulTaskNotifyTake(BaseType_t xClearCountOnExit, TickType_t xTicksToWait);

xClearCountOnExit: Use 1 (pdTRUE) to reset the notification count to zero after taking it (binary behavior). Use 0 (pdFALSE) to keep counting notifications (counting behavior).

xTicksToWait: How long the task waits if no notification is available. Use portMAX_DELAY to wait forever.

Examples
Wait forever for a single notification, then clear the count (binary notification).
FreeRTOS
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
Wait up to 100 ticks for notifications, keep counting them (counting notification).
FreeRTOS
ulTaskNotifyTake(pdFALSE, 100);
Sample Program

This program creates two tasks. The sender sends three notifications with 500ms delay each. The receiver waits and counts notifications using ulTaskNotifyTake() in counting mode (xClearCountOnExit = pdFALSE). It prints how many notifications it got each time. When it receives all three, it stops.

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

TaskHandle_t xTaskHandle = NULL;

void vSenderTask(void *pvParameters) {
    for (int i = 1; i <= 3; i++) {
        vTaskDelay(pdMS_TO_TICKS(500));
        xTaskNotifyGive(xTaskHandle); // Send notification
        printf("Sender: Notification %d sent\n", i);
    }
    vTaskDelete(NULL);
}

void vReceiverTask(void *pvParameters) {
    uint32_t ulCount;
    uint32_t ulTotalCount = 0;
    while (1) {
        ulCount = ulTaskNotifyTake(pdFALSE, portMAX_DELAY); // Counting mode
        printf("Receiver: Got %lu notifications\n", ulCount);
        ulTotalCount += ulCount;
        if (ulTotalCount >= 3) {
            printf("Receiver: Received all notifications, exiting.\n");
            break;
        }
    }
    vTaskDelete(NULL);
}

int main(void) {
    xTaskCreate(vReceiverTask, "Receiver", 1000, NULL, 2, &xTaskHandle);
    xTaskCreate(vSenderTask, "Sender", 1000, NULL, 2, NULL);
    vTaskStartScheduler();
    return 0;
}
OutputSuccess
Important Notes

ulTaskNotifyTake() returns the number of notifications received since last call if counting mode is used.

Use pdTRUE for binary notification to clear count after taking it.

ulTaskNotifyTake() is efficient and lightweight compared to semaphores.

Summary

ulTaskNotifyTake() lets a task wait for notifications from other tasks or interrupts.

Use xClearCountOnExit = pdTRUE for binary (single) notification, pdFALSE for counting multiple notifications.

It helps tasks sleep and save CPU until something important happens.