Extra 5% OFF Use Code: OL05
Free Shipping over ₹999

Task Notifications

In FreeRTOS, task notifications provide a lightweight mechanism for inter-task communication and synchronization, acting as a simpler alternative to semaphores and queues. Each task has its own notification value, which other tasks or ISRs (Interrupt Service Routines) can increment, decrement, or set directly.

Key Features of Task Notifications

  1. Lightweight: Less overhead than using semaphores or queues.
  2. Direct-to-task: Notifications are sent directly to a specific task, making them ideal for simple signaling.
  3. Binary or Counting: Notifications can act as either binary (similar to a binary semaphore) or counting (similar to a counting semaphore).

Example Scenario: Using Task Notifications for Inter-Task Communication

Let’s say we have two tasks:

  • Task 1: Simulates sensor data processing.
  • Task 2: Notified by Task 1 to perform an action (like toggling an LED) after Task 1 completes processing.

In this example, Task 1 will send a notification to Task 2 after completing its work, and Task 2 will respond when it receives the notification.

Example Code:

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"

#define LED_PIN 2  // GPIO for LED output

TaskHandle_t xTask2Handle = NULL;  // Handle for Task 2

// Task 1: Simulates sensor processing and notifies Task 2
void vTask1(void *pvParameters) {
    while (1) {
        printf("Task 1: Processing sensor data...\n");
        vTaskDelay(pdMS_TO_TICKS(2000));  // Simulate data processing time

        // Send notification to Task 2 after processing
        printf("Task 1: Notifying Task 2\n");
        xTaskNotifyGive(xTask2Handle);

        // Delay to simulate periodic sensor processing
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

// Task 2: Waits for notification from Task 1 and toggles LED
void vTask2(void *pvParameters) {
    // Configure LED_PIN as output
    gpio_pad_select_gpio(LED_PIN);
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
    
    while (1) {
        // Wait for notification from Task 1
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);

        // Toggle LED and print message
        static int ledState = 0;
        ledState = !ledState;
        gpio_set_level(LED_PIN, ledState);
        printf("Task 2: Received notification, toggling LED\n");
    }
}

void app_main() {
    // Create Task 2
    xTaskCreate(vTask2, "Task 2", 2048, NULL, 1, &xTask2Handle);

    // Create Task 1
    xTaskCreate(vTask1, "Task 1", 2048, NULL, 1, NULL);
}

Explanation of the Code

  1. Defining the LED Pin:
    • LED_PIN is the GPIO pin connected to an LED, which will be toggled by Task 2.
  2. Task 1 (Sensor Processing):
    • Task 1 simulates sensor data processing, which takes 2 seconds.
    • After processing, Task 1 sends a notification to Task 2 using xTaskNotifyGive(xTask2Handle).
    • It then waits for a second before processing again, simulating periodic sensor reads.
  3. Task 2 (LED Toggle on Notification):
    • Task 2 waits for a notification using ulTaskNotifyTake(), which blocks it until a notification is received.
    • When notified by Task 1, Task 2 toggles the LED and prints a message.
  4. Task Creation in app_main():
    • Task 2 is created first and assigned a handle (xTask2Handle) so that Task 1 can send it notifications.
    • Task 1 is created afterward and does not need a handle, as it does not need notifications from other tasks.

Explanation of Task Notification Functions

  1. xTaskNotifyGive():
    • Sends a notification to a specified task. Here, Task 1 uses xTaskNotifyGive() to notify Task 2.
  2. ulTaskNotifyTake():
    • Blocks the calling task (in this case, Task 2) until it receives a notification.
    • The first parameter (pdTRUE) clears the notification value after receiving it, treating this as a binary notification.
    • The second parameter (portMAX_DELAY) indicates that the task will wait indefinitely for a notification.

Output Explanation

When running this code, you should see:

  1. Task 1 repeatedly printing:
Task 1: Processing sensor data...
Task 1: Notifying Task 2

2. Task 2 responding each time with:

Task 2: Received notification, toggling LED

The LED connected to LED_PIN will toggle each time Task 2 receives a notification from Task 1.

Summary

  • Task Notifications: Provide simple, efficient inter-task signaling.
  • xTaskNotifyGive(): Used by Task 1 to notify Task 2 upon completing a task.
  • ulTaskNotifyTake(): Allows Task 2 to wait for a notification and toggle the LED upon receiving it.

This approach is efficient for scenarios requiring lightweight task synchronization without needing the complexity of semaphores or queues.

    Leave a Reply

    Your email address will not be published.

    Need Help?