MCU & FPGA RTOS Arquitetura Orientada a Eventos no FreeRTOS

Arquitetura Orientada a Eventos no FreeRTOS

Composição Arquitetural de Eventos no FreeRTOS

Até aqui, analisamos isoladamente cada mecanismo de evento do FreeRTOS. Porém, sistemas reais raramente usam apenas um deles. O verdadeiro ganho arquitetural surge quando combinamos conscientemente esses mecanismos, criando uma malha de eventos clara, previsível e de baixo acoplamento. Esta seção trata exatamente de como orquestrar múltiplos tipos de eventos sem comprometer o determinismo do sistema.

O princípio fundamental é simples: cada mecanismo deve ter um papel bem definido. Task Notifications sinalizam eventos direcionados, Event Groups representam estados globais, Queues transportam dados estruturados, Stream/Message Buffers lidam com fluxo, e Timers geram eventos temporais. Misturar responsabilidades é o caminho mais curto para arquiteturas frágeis.


Padrão 1 — ISR mínima + Evento Direcionado

Este é o padrão mais importante em sistemas orientados a eventos.

void DMA_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;
    vTaskNotifyGiveFromISR(dmaTaskHandle, &xHigherPriorityTaskWoken);
    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

A tarefa:

void vDmaTask(void *pvParameters)
{
    for (;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        processDmaBuffer();
    }
}

Aqui, a ISR não carrega lógica, apenas converte um evento físico em evento lógico. Esse padrão reduz latência, evita jitter e simplifica análise de tempo real.


Padrão 2 — Evento acorda, fila transporta

Um erro comum é usar filas apenas para acordar tarefas. Em arquiteturas maduras, eventos acordam tarefas; filas entregam dados.

void vProducerTask(void *pvParameters)
{
    Data_t data;

    for (;;)
    {
        data = acquireData();
        xQueueSend(dataQueue, &data, 0);
        xTaskNotifyGive(consumerTaskHandle);
    }
}

A tarefa consumidora:

void vConsumerTask(void *pvParameters)
{
    for (;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        drainQueueAndProcess();
    }
}

Esse padrão reduz wake-ups redundantes e melhora eficiência energética.


Padrão 3 — Event Group como estado global, não evento

#define EVT_SYSTEM_READY (1 << 0)

void vInitTask(void *pvParameters)
{
    initializeSubsystems();
    xEventGroupSetBits(systemEventGroup, EVT_SYSTEM_READY);
    vTaskDelete(NULL);
}

Tarefas dependentes:

void vAppTask(void *pvParameters)
{
    xEventGroupWaitBits(
        systemEventGroup,
        EVT_SYSTEM_READY,
        pdFALSE,
        pdTRUE,
        portMAX_DELAY
    );

    runApplication();
}

Aqui, o Event Group representa um estado permanente, não um evento transitório. Essa distinção é crucial para evitar perda de sinalização.


Padrão 4 — Timer → Evento → Task

void vPeriodicTimerCallback(TimerHandle_t xTimer)
{
    xTaskNotifyGive(periodicTaskHandle);
}

A tarefa:

void vPeriodicTask(void *pvParameters)
{
    for (;;)
    {
        ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
        performPeriodicAction();
    }
}

Esse padrão elimina delays ativos e centraliza controle temporal.


Padrão 5 — Máquina de estados orientada a eventos

Arquiteturas orientadas a eventos se integram naturalmente com State Machines.

typedef enum {
    EVT_START,
    EVT_STOP,
    EVT_ERROR
} Event_t;
void vControllerTask(void *pvParameters)
{
    Event_t evt;

    for (;;)
    {
        xQueueReceive(eventQueue, &evt, portMAX_DELAY);
        stateMachineDispatch(evt);
    }
}

Esse modelo é extremamente poderoso para sistemas complexos, como comunicação, controle e supervisão.


0 0 votos
Classificação do artigo
Inscrever-se
Notificar de
guest
0 Comentários
mais antigos
mais recentes Mais votado
Feedbacks embutidos
Ver todos os comentários

Related Post

0
Adoraria saber sua opinião, comente.x