Embedded Development Board Learning


Event Groups in FreeRTOS #12 Response to events

Date: abril 17, 2025

Author: Guillermo Garcia

Categories: RTOS Tags:

Event Groups in FreeRTOS play a crucial role in synchronizing multiple tasks based on event flags. This article explores Event Groups in FreeRTOS, explaining their functionality, benefits.

What Are Event Groups in FreeRTOS?

Event Groups in FreeRTOS are a set of binary flags (bits) used for event signaling between tasks and ISRs (Interrupt Service Routines). Each bit in an event group represents a different event, allowing multiple tasks to wait for one or more events to occur simultaneously.

  • Efficient Synchronization: Tasks can wait for multiple events at once, reducing CPU usage compared to polling mechanisms.
  • ISR Compatibility: ISRs can set event bits, enabling real-time responsiveness.
  • Flexible Event Handling: A task can block until any or all required event bits are set.
  • Reduced Complexity: Eliminates the need for multiple binary semaphores or flags.

Event Bits Event Flags

Bits are used to indicate if an event has occurred or not. Event bits are often referred to as event flags. For example, an application may:

  • Define a bit (or flag) that means A message has been received and is ready for processing when it is set to 1, and «there are no messages waiting to be processed when it is set to 0.
  • Define a bit (or flag) that means The application has queued a message that is ready to be sent to a network when it is set to 1, and there are no messages queued ready to be sent to the network when it is set to 0.
  • Define a bit (or flag) that means It is time to send a heartbeat message onto a network when it is set to 1, and it is not yet time to send another heartbeat message when it is set to 0.

Use Event Groups in FreeRTOS

Event group API functions are provided that allow a task to, among other things, set one or more event bits within an event group, clear one or more event bits within an event group, and pend (enter the Blocked state so the task does not consume any processing time) to wait for a set of one or more event bits to become set within an event group.

Create an Event Group

Use xEventGroupCreate() to create an event group.

#include "FreeRTOS.h"
#include "event_groups.h"

EventGroupHandle_t xEventGroup;

void setupEventGroup() {
    xEventGroup = xEventGroupCreate();
    if (xEventGroup == NULL) {
        // Handle error
    }
}

Set Event Bits

Tasks or ISRs can set event bits using xEventGroupSetBits().

#define EVENT_BIT_0 (1 << 0)
#define EVENT_BIT_1 (1 << 1)

void taskA(void *pvParameters) {
    while (1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
        xEventGroupSetBits(xEventGroup, EVENT_BIT_0);
    }
}

Wait for Event Bits

Tasks can block until specific event bits are set using xEventGroupWaitBits().

void taskB(void *pvParameters) {
    EventBits_t eventBits;
    while (1) {
        eventBits = xEventGroupWaitBits(xEventGroup, EVENT_BIT_0, pdTRUE, pdFALSE, portMAX_DELAY);
        if (eventBits & EVENT_BIT_0) {
            // Handle event
        }
    }
}

Clear Event Bits

If needed, use xEventGroupClearBits() to manually clear specific event bits.

xEventGroupClearBits(xEventGroup, EVENT_BIT_0);

Delete an Event Group

When no longer needed, free resources with vEventGroupDelete().

vEventGroupDelete(xEventGroup);

Synchronizing Multiple Tasks

Consider a system where Task A signals when data is available, and Task B and Task C wait for the event. In this example, taskProducer sets an event flag when data is ready. Both taskConsumer1 and taskConsumer2 unblock and process the data when the flag is set.

#include "Event_Bits.h"

#define DATA_READY_EVENT (1 << 0)

EventGroupHandle_t xEventGroup;

void taskProducer(void *NotUsed)
{
    UNUSED(NotUsed);   

    while(1) 
    {
        vTaskDelay(pdMS_TO_TICKS(2000));
        xEventGroupSetBits(xEventGroup, DATA_READY_EVENT);
        SEGGER_SYSVIEW_Print("Data ready event \n");
    }
}

void taskConsumer1(void *NotUsed) 
{
    UNUSED(NotUsed); 

    while(1) 
    {
        xEventGroupWaitBits(xEventGroup, DATA_READY_EVENT, pdTRUE, pdFALSE, portMAX_DELAY);
        SEGGER_SYSVIEW_Print("Consumer 1 \n");
    }
}

void taskConsumer2(void *NotUsed) 
{
    UNUSED(NotUsed); 

    while(1) 
    {
        xEventGroupWaitBits(xEventGroup, DATA_READY_EVENT, pdTRUE, pdFALSE, portMAX_DELAY);
        SEGGER_SYSVIEW_Print("Consumer 2 \n");
    }
}

void Respose_to_events(void)
{
    /* Create Event Group */
    xEventGroup = xEventGroupCreate();
    
    /* Create tasks */
    xTaskCreate(taskConsumer1,"Tarea 1",configMINIMAL_STACK_SIZE, NULL,tskIDLE_PRIORITY+2,NULL);
    xTaskCreate(taskConsumer2,"Tarea 2",configMINIMAL_STACK_SIZE, NULL,tskIDLE_PRIORITY+2,NULL);
    xTaskCreate(taskProducer,"Tarea 3",configMINIMAL_STACK_SIZE, NULL,tskIDLE_PRIORITY+2,NULL);
}

int main()
{
  HAL_SYSTICK_Config(SystemCoreClock / (1000U / (uint32_t)uwTickFreq));
  HAL_NVIC_SetPriority(SysTick_IRQn, 0, 0U);
  HAL_NVIC_SetPriorityGrouping(NVIC_PRIORITYGROUP_4);

  traceSTART();
  Respose_to_events();
  vTaskStartScheduler();
}

SystemView Output:

Let’s go to our STM32F407VG Discovery kit board to analyze the code.

In the example we see that Task 3 taskProducer sets the DATA_READY_EVENT bit.

Event Groups in FreeRTOS step 1

Task 1 and Task 2 representing consumers are waiting for the DATA_READY_EVENT bit to be set and they exit blocking mode to go into running mode.

Event Groups in FreeRTOS step 2

Closing

Event Groups in FreeRTOS provide an efficient and flexible way to synchronize multiple tasks based on events. By leveraging event bits, embedded developers can simplify inter-task communication and enhance system performance.

Understanding how to use Event Groups properly will help you build more responsive and scalable FreeRTOS-based applications.



Card image cap
Guillermo Garcia Thanks for reading! I am one of the editors of this site and I am committed to providing you with the best information possible by sharing my experience in embedded systems.


Comments... There are no comments.

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *

Publicidad