Event groups help tasks wait for or signal multiple events easily. They let tasks work together by sharing simple flags.
Event group for task synchronization in FreeRTOS
EventGroupHandle_t xEventGroupCreate(void);
EventBits_t xEventGroupWaitBits(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToWaitFor,
const BaseType_t xClearOnExit,
const BaseType_t xWaitForAllBits,
TickType_t xTicksToWait
);
EventBits_t xEventGroupSetBits(
EventGroupHandle_t xEventGroup,
const EventBits_t uxBitsToSet
);xEventGroupCreate() creates a new event group and returns its handle.
xEventGroupWaitBits() waits for specified bits to be set in the event group.
EventGroupHandle_t xEventGroup = xEventGroupCreate(); // Create an event group
EventBits_t uxBits = xEventGroupWaitBits(
xEventGroup,
BIT_0 | BIT_1,
pdTRUE,
pdFALSE,
portMAX_DELAY
);
// Wait for BIT_0 or BIT_1 to be set, clear bits on exit, wait foreverxEventGroupSetBits(xEventGroup, BIT_0);
// Set BIT_0 in the event group to signal an eventThis program creates an event group and three tasks. Task1 waits for BIT_0, Task2 waits for BIT_1, and Task3 sets both bits after 1 second. Tasks 1 and 2 print messages when their bits are received.
#include "FreeRTOS.h" #include "task.h" #include "event_groups.h" #include <stdio.h> #define BIT_0 (1 << 0) #define BIT_1 (1 << 1) EventGroupHandle_t xEventGroup; void vTask1(void *pvParameters) { printf("Task1: Waiting for BIT_0...\n"); xEventGroupWaitBits(xEventGroup, BIT_0, pdTRUE, pdFALSE, portMAX_DELAY); printf("Task1: BIT_0 received!\n"); vTaskDelete(NULL); } void vTask2(void *pvParameters) { printf("Task2: Waiting for BIT_1...\n"); xEventGroupWaitBits(xEventGroup, BIT_1, pdTRUE, pdFALSE, portMAX_DELAY); printf("Task2: BIT_1 received!\n"); vTaskDelete(NULL); } void vTask3(void *pvParameters) { printf("Task3: Setting BIT_0 and BIT_1 after delay...\n"); vTaskDelay(pdMS_TO_TICKS(1000)); xEventGroupSetBits(xEventGroup, BIT_0 | BIT_1); printf("Task3: Bits set!\n"); vTaskDelete(NULL); } int main(void) { xEventGroup = xEventGroupCreate(); if (xEventGroup == NULL) { printf("Failed to create event group\n"); return 1; } xTaskCreate(vTask1, "Task1", 1000, NULL, 1, NULL); xTaskCreate(vTask2, "Task2", 1000, NULL, 1, NULL); xTaskCreate(vTask3, "Task3", 1000, NULL, 1, NULL); vTaskStartScheduler(); // Should never reach here for(;;); return 0; }
Always check if xEventGroupCreate() returns NULL, which means creation failed.
Use pdTRUE for xClearOnExit if you want bits cleared after a task wakes up.
Event bits are limited to 24 bits in FreeRTOS.
Event groups let tasks wait for or signal multiple events using bits.
They help tasks synchronize without busy waiting.
Use xEventGroupWaitBits() to wait and xEventGroupSetBits() to signal.
Practice
Solution
Step 1: Understand event groups in FreeRTOS
Event groups use bits to represent events that tasks can wait for or signal.Step 2: Identify the main use of event groups
They help tasks synchronize by waiting on or setting bits representing events.Final Answer:
To allow tasks to wait for multiple events using bits -> Option BQuick Check:
Event groups = wait for multiple events [OK]
- Confusing event groups with queues
- Thinking event groups manage memory
- Assuming event groups change task priorities
Solution
Step 1: Recall FreeRTOS event group functions
xEventGroupWaitBits() is used to wait for specific bits to be set.Step 2: Differentiate from other functions
xEventGroupSetBits() sets bits, ClearBits clears bits, Create creates the group.Final Answer:
xEventGroupWaitBits() -> Option CQuick Check:
Wait for bits = xEventGroupWaitBits() [OK]
- Using xEventGroupSetBits() to wait
- Confusing create with wait functions
- Mixing clear bits with wait bits
bits after xEventGroupWaitBits() returns?
EventBits_t bits; bits = xEventGroupWaitBits(eventGroup, BIT_0 | BIT_1, pdTRUE, pdFALSE, portMAX_DELAY);Assume BIT_0 and BIT_1 are both set in
eventGroup before the call.Solution
Step 1: Understand xEventGroupWaitBits parameters
The function waits for BIT_0 or BIT_1 to be set, clears bits on exit (pdTRUE), and does not wait for all bits (pdFALSE).Step 2: Analyze the bits set before call
Both BIT_0 and BIT_1 are set, so the function returns with both bits set in the return value.Final Answer:
Both BIT_0 and BIT_1 set -> Option DQuick Check:
WaitBits returns bits set before clearing [OK]
- Assuming only one bit is returned
- Ignoring bits cleared on exit
- Confusing wait for all bits with wait for any
EventGroupHandle_t eventGroup = xEventGroupCreate();
void Task1(void *pvParameters) {
xEventGroupWaitBits(eventGroup, BIT_0, pdFALSE, pdTRUE, portMAX_DELAY);
// Task code
}
void Task2(void *pvParameters) {
xEventGroupSetBits(eventGroup, BIT_0);
}Solution
Step 1: Check event group creation
xEventGroupCreate() can return NULL if creation fails; code does not check this.Step 2: Verify other parameters
Using pdFALSE for clearOnExit is valid; portMAX_DELAY is valid; bits are set after creation.Final Answer:
Not checking if eventGroup creation succeeded -> Option AQuick Check:
Always check event group creation success [OK]
- Ignoring NULL return from xEventGroupCreate
- Misusing clearOnExit parameter
- Setting bits before creating event group
xEventGroupWaitBits() call correctly waits for both bits before continuing?Solution
Step 1: Understand wait for all bits parameter
The fourth parameter (xWaitForAllBits) must be pdTRUE to wait for both bits together.Step 2: Check bit mask and parameters
Use BIT_0 | BIT_1 to specify both bits; pdTRUE for clearOnExit clears bits after wait.Final Answer:
xEventGroupWaitBits(eventGroup, BIT_0 | BIT_1, pdTRUE, pdTRUE, portMAX_DELAY); -> Option AQuick Check:
Wait for all bits = xEventGroupWaitBits with xWaitForAllBits = pdTRUE [OK]
- Using bitwise AND (&) instead of OR (|) for bit mask
- Setting xWaitForAllBits to pdFALSE when waiting for all bits
- Confusing clearOnExit with wait for all bits
Ready to prove it?
Pass the test and this pattern moves unknown
