xTaskNotifyGive() lets tasks signal each other quickly and simply, like passing a small note to say 'I'm done' or 'Go ahead'. It works like a lightweight semaphore to control access or sync tasks without heavy overhead.
xTaskNotifyGive() as lightweight semaphore in FreeRTOS
void xTaskNotifyGive(TaskHandle_t xTaskToNotify);
xTaskToNotify is the handle of the task you want to notify.
This function sends a notification that increments the notified task's notification value by 1.
xTaskHandle that an event occurred.xTaskNotifyGive(xTaskHandle);
xTaskNotifyGiveFromISR(xTaskHandle, &xHigherPriorityTaskWoken);
This program creates two tasks. Task 1 does some work, then notifies Task 2 using xTaskNotifyGive(). Task 2 waits for this notification using ulTaskNotifyTake() and runs when notified. This shows how xTaskNotifyGive() acts like a lightweight semaphore to sync tasks.
#include "FreeRTOS.h" #include "task.h" #include <stdio.h> TaskHandle_t xTask1Handle = NULL; TaskHandle_t xTask2Handle = NULL; void vTask1(void *pvParameters) { while (1) { printf("Task 1: Doing work...\n"); vTaskDelay(pdMS_TO_TICKS(1000)); printf("Task 1: Notifying Task 2\n"); xTaskNotifyGive(xTask2Handle); // Signal Task 2 } } void vTask2(void *pvParameters) { while (1) { ulTaskNotifyTake(pdTRUE, portMAX_DELAY); // Wait for notification printf("Task 2: Received notification, running...\n"); } } int main(void) { xTaskCreate(vTask1, "Task1", 1000, NULL, 1, &xTask1Handle); xTaskCreate(vTask2, "Task2", 1000, NULL, 1, &xTask2Handle); vTaskStartScheduler(); return 0; }
ulTaskNotifyTake() is used by the receiving task to wait for the notification and optionally clear it.
This method is lighter and faster than traditional semaphores but only supports one notification count per task.
Use xTaskNotifyGiveFromISR() if notifying from an interrupt.
xTaskNotifyGive() sends a simple signal from one task to another.
It works like a lightweight semaphore to sync tasks with less overhead.
Use ulTaskNotifyTake() to wait for the signal and continue work.
Practice
xTaskNotifyGive() in FreeRTOS?Solution
Step 1: Understand the function role
xTaskNotifyGive()is designed to send a notification signal from one task to another.Step 2: Compare with other options
Creating or deleting tasks and memory allocation are unrelated toxTaskNotifyGive().Final Answer:
To send a simple signal from one task to another as a lightweight semaphore -> Option AQuick Check:
Signal sending = To send a simple signal from one task to another as a lightweight semaphore [OK]
- Confusing it with task creation or deletion functions
- Thinking it manages memory
- Assuming it blocks tasks directly
xTaskNotifyGive() to a task handle named xTaskHandle?Solution
Step 1: Recall function signature
xTaskNotifyGive()takes a task handle as a parameter, not a pointer or extra arguments.Step 2: Check each option
xTaskNotifyGive(xTaskHandle); correctly passes the task handle. xTaskNotifyGive(&xTaskHandle); passes address (wrong), C adds an extra argument (wrong), D has no argument (wrong).Final Answer:
xTaskNotifyGive(xTaskHandle); -> Option CQuick Check:
Correct syntax = xTaskNotifyGive(xTaskHandle); [OK]
- Passing pointer to task handle instead of handle itself
- Adding extra parameters
- Calling without any argument
void Task1(void *pvParameters) {
// Wait for notification
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
// Continue after notification
printf("Task1 resumed\n");
}
void Task2(void *pvParameters) {
// Notify Task1
xTaskNotifyGive(Task1Handle);
}
What will be printed when Task2 calls xTaskNotifyGive()?Solution
Step 1: Understand notification flow
Task1waits for a notification withulTaskNotifyTake(). WhenTask2callsxTaskNotifyGive(), it sends the notification.Step 2: Effect of notification
The notification unblocksTask1, so it prints "Task1 resumed".Final Answer:
Task1 resumed -> Option BQuick Check:
Notification received = Task1 prints [OK]
- Assuming Task1 never resumes
- Confusing which task prints output
- Thinking code causes compile error
xTaskNotifyGive():
void TaskA(void *pvParameters) {
ulTaskNotifyTake(pdFALSE, portMAX_DELAY);
printf("TaskA running\n");
}
void TaskB(void *pvParameters) {
xTaskNotifyGive(&TaskAHandle);
}Solution
Step 1: Check parameter passed to xTaskNotifyGive()
The function expects a task handle, but&TaskAHandlepasses its address, which is incorrect.Step 2: Validate other parts
UsingpdFALSEis valid to clear notification count, no syntax error in printf, and delay is optional.Final Answer:
Passing address of task handle instead of task handle to xTaskNotifyGive() -> Option AQuick Check:
Correct parameter type needed = Passing address of task handle instead of task handle to xTaskNotifyGive() [OK]
- Passing pointer to handle instead of handle
- Misunderstanding pdFALSE effect
- Assuming printf syntax error
xTaskNotifyGive() as a lightweight semaphore to synchronize two tasks: Producer and Consumer. The Consumer waits for the notification before processing data. Which sequence correctly implements this synchronization?Solution
Step 1: Identify roles of tasks
The Consumer should wait for a signal before processing, so it usesulTaskNotifyTake()to block until notified.Step 2: Producer signals Consumer
The Producer sends the notification usingxTaskNotifyGive()with the Consumer's task handle.Final Answer:
Consumer calls ulTaskNotifyTake(pdTRUE, portMAX_DELAY); to wait, Producer calls xTaskNotifyGive(ConsumerHandle); to signal -> Option DQuick Check:
Wait then signal = Consumer callsulTaskNotifyTake(pdTRUE, portMAX_DELAY);to wait, Producer callsxTaskNotifyGive(ConsumerHandle);to signal [OK]
- Reversing roles of Producer and Consumer
- Both tasks signaling without waiting
- Using wrong task handles in calls
Ready to prove it?
Pass the test and this pattern moves unknown
