Event-driven architecture helps your program react to things when they happen, like a button press or a sensor alert. It makes your program efficient and easy to manage.
Event-driven architecture in FreeRTOS
void vTaskFunction(void *pvParameters) {
for(;;) {
if(xEventGroupWaitBits(xEventGroup, EVENT_BIT, pdTRUE, pdFALSE, portMAX_DELAY) != 0) {
// Handle event here
}
}
}xEventGroupWaitBits waits for specific event bits to be set.
Use pdTRUE to clear bits after handling the event.
EventGroupHandle_t xEventGroup = xEventGroupCreate(); // In task: if((xEventGroupWaitBits(xEventGroup, BIT_0, pdTRUE, pdFALSE, portMAX_DELAY) & BIT_0) != 0) { // Event BIT_0 occurred }
// Setting an event bit from an ISR
BaseType_t xHigherPriorityTaskWoken = pdFALSE;
xEventGroupSetBitsFromISR(xEventGroup, BIT_0, &xHigherPriorityTaskWoken);This program creates two tasks. One simulates a button press by setting an event bit after 1 second. The other waits for that event and then prints a message when it happens.
#include "FreeRTOS.h" #include "task.h" #include "event_groups.h" #include <stdio.h> #define BUTTON_PRESS_BIT (1 << 0) EventGroupHandle_t xEventGroup; void ButtonTask(void *pvParameters) { // Simulate button press after delay vTaskDelay(pdMS_TO_TICKS(1000)); printf("Button pressed! Setting event bit.\n"); xEventGroupSetBits(xEventGroup, BUTTON_PRESS_BIT); vTaskDelete(NULL); } void EventHandlerTask(void *pvParameters) { printf("Waiting for button press event...\n"); xEventGroupWaitBits(xEventGroup, BUTTON_PRESS_BIT, pdTRUE, pdFALSE, portMAX_DELAY); printf("Button event received! Handling event.\n"); vTaskDelete(NULL); } int main(void) { xEventGroup = xEventGroupCreate(); xTaskCreate(ButtonTask, "ButtonTask", 1000, NULL, 1, NULL); xTaskCreate(EventHandlerTask, "EventHandlerTask", 1000, NULL, 1, NULL); vTaskStartScheduler(); for(;;); return 0; }
Event bits let tasks communicate without busy waiting.
Always clear event bits after handling to avoid repeated triggers.
Use event groups carefully to avoid race conditions.
Event-driven architecture lets your program react only when something happens.
FreeRTOS event groups help tasks wait for and signal events efficiently.
This approach saves CPU time and makes your program responsive.
Practice
Solution
Step 1: Understand event-driven architecture basics
Event-driven architecture means the program waits and reacts only when events happen, not running tasks all the time.Step 2: Connect to FreeRTOS event groups
FreeRTOS event groups let tasks wait efficiently for events, saving CPU time by not running unnecessarily.Final Answer:
The program reacts only when an event occurs, saving CPU time. -> Option CQuick Check:
Event-driven = React on event, save CPU [OK]
- Thinking event-driven runs all tasks continuously
- Believing it uses more CPU by checking constantly
- Confusing event-driven with disabling multitasking
Solution
Step 1: Recall FreeRTOS event group creation syntax
The official FreeRTOS function to create an event group is xEventGroupCreate(), returning EventGroupHandle_t.Step 2: Match the correct syntax
EventGroupHandle_t xEventGroup = xEventGroupCreate(); uses the correct function name and type: EventGroupHandle_t xEventGroup = xEventGroupCreate();Final Answer:
EventGroupHandle_t xEventGroup = xEventGroupCreate(); -> Option BQuick Check:
Correct function and type = EventGroupHandle_t xEventGroup = xEventGroupCreate(); [OK]
- Using wrong function names like createEventGroup()
- Missing the correct handle type EventGroupHandle_t
- Incorrect capitalization or function syntax
<pre>EventGroupHandle_t xEventGroup = xEventGroupCreate(); // Task A waits for bit 0 and bit 1 EventBits_t uxBits = xEventGroupWaitBits(xEventGroup, (1 << 0) | (1 << 1), pdTRUE, pdTRUE, portMAX_DELAY); // Task B sets bit 0 xEventGroupSetBits(xEventGroup, (1 << 0)); // Task C sets bit 1 xEventGroupSetBits(xEventGroup, (1 << 1)); // What is the value of uxBits after Task A unblocks?
Solution
Step 1: Understand xEventGroupWaitBits parameters
Task A waits for bits 0 and 1 together (bitmask 0x03), clears bits on exit (pdTRUE), waits for all bits (pdTRUE), and waits indefinitely.Step 2: Analyze bit setting by Task B and Task C
Task B sets bit 0 (0x01), Task C sets bit 1 (0x02). When both bits are set, Task A unblocks and uxBits contains both bits set (0x03).Final Answer:
0x03 (both bits 0 and 1 set) -> Option AQuick Check:
Wait for bits 0 & 1 set = 0x03 [OK]
- Assuming only one bit is set when unblocked
- Ignoring that wait is for all bits (pdTRUE)
- Confusing bit masks with decimal values
EventGroupHandle_t xEventGroup; xEventGroupSetBits(xEventGroup, (1 << 0));
Solution
Step 1: Check event group initialization
xEventGroup is declared but never created with xEventGroupCreate(), so it is uninitialized (likely NULL).Step 2: Understand consequences of uninitialized handle
Calling xEventGroupSetBits with an uninitialized handle causes undefined behavior or crash.Final Answer:
xEventGroup is not created before use. -> Option DQuick Check:
Create event group before use [OK]
- Forgetting to call xEventGroupCreate()
- Thinking bit mask is invalid
- Misunderstanding handle vs pointer usage
Solution
Step 1: Understand the parameters for xEventGroupWaitBits
The third parameter clears bits on exit (pdTRUE), the fourth parameter controls if waiting for all bits (pdTRUE) or any bit (pdFALSE).Step 2: Match requirement to wait for either bit 2 or bit 3, but not both
Waiting for any bit means pdFALSE for the fourth parameter. Using bitmask (1 << 2) | (1 << 3) waits for either bit 2 or bit 3.Final Answer:
xEventGroupWaitBits(xEventGroup, (1 << 2) | (1 << 3), pdTRUE, pdFALSE, portMAX_DELAY); -> Option AQuick Check:
Wait for any bit = pdFALSE, bitmask ORed = xEventGroupWaitBits(xEventGroup, (1 << 2) | (1 << 3), pdTRUE, pdFALSE, portMAX_DELAY); [OK]
- Using pdTRUE to wait for all bits instead of any
- Using bitwise AND instead of OR for bitmask
- Not clearing bits on exit when needed
Ready to prove it?
Pass the test and this pattern moves unknown
