MCU & FPGA RTOS FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores

FreeRTOS: Uso Correto de Queue com Múltiplos Consumidores

Alternativas arquiteturais quando múltiplos consumidores precisam do mesmo evento

Quando o requisito do sistema deixa de ser “distribuir trabalho” e passa a ser “notificar múltiplas tarefas sobre o mesmo fato”, o uso direto de Queue com vários consumidores se torna conceitualmente inadequado. Nesse ponto, a maturidade do projeto aparece na escolha do mecanismo correto para cada semântica, e não na tentativa de forçar a fila a se comportar como algo que ela não é.

A alternativa mais simples e eficiente para notificação múltipla é o uso de Event Groups. Um Event Group permite que várias tarefas bloqueiem esperando por um ou mais bits, e quando esses bits são setados, todas as tarefas interessadas são desbloqueadas. Esse comportamento é, por natureza, um broadcast. É ideal para eventos de estado, como “sistema inicializado”, “falha detectada” ou “conexão estabelecida”.

EventGroupHandle_t xEvents;

#define EVT_FAULT   (1 << 0)

void vMonitorTask(void *pvParameters)
{
    xEventGroupWaitBits(
        xEvents,
        EVT_FAULT,
        pdTRUE,
        pdFALSE,
        portMAX_DELAY
    );

    handle_fault();
}

Aqui, várias tarefas podem esperar pelo mesmo bit e todas serão notificadas quando ele for setado. A principal limitação é que Event Groups não carregam dados, apenas sinalização. Se o evento precisa transportar contexto, outro mecanismo deve ser combinado.

Outra opção mais leve e extremamente eficiente é o uso de Task Notifications, especialmente no modo notify bits. Cada tarefa possui seu próprio registrador de notificação, o que permite um modelo explícito de fan-out: o produtor envia a mesma notificação para várias tarefas, uma por uma. Apesar de exigir mais código no produtor, esse modelo é determinístico, rápido e sem alocação dinâmica.

xTaskNotify(xTaskLog, EVT_FAULT, eSetBits);
xTaskNotify(xTaskControl, EVT_FAULT, eSetBits);

Esse padrão é muito utilizado em sistemas com requisitos rígidos de latência, pois evita listas internas complexas e overhead de filas. A desvantagem é que o produtor precisa conhecer explicitamente os consumidores, o que reduz o desacoplamento.

Quando é necessário broadcast com dados, a solução mais clara é o fan-out explícito com múltiplas filas. O produtor envia a mesma mensagem para várias Queue distintas, cada uma dedicada a um consumidor ou grupo de consumidores. Embora isso aumente o consumo de memória, o comportamento é previsível e alinhado com a semântica desejada.

xQueueSend(xQueueLog, &msg, portMAX_DELAY);
xQueueSend(xQueueControl, &msg, portMAX_DELAY);

Esse padrão é amplamente adotado em arquiteturas orientadas a eventos e pipelines de processamento bem definidos. Ele também facilita testes, pois cada consumidor pode ser validado isoladamente.

Por fim, existe um padrão híbrido bastante elegante: usar uma Queue única para distribuição de trabalho e Event Groups ou Notifications para sinalização global. Assim, a fila permanece responsável apenas por dados consumidos uma vez, enquanto os eventos notificam estados ou condições relevantes para todo o sistema. Essa separação semântica tende a produzir firmwares mais legíveis, escaláveis e fáceis de manter.

Em essência, quando múltiplos consumidores precisam reagir ao mesmo evento, o erro não está na implementação, mas na escolha da ferramenta. O FreeRTOS oferece mecanismos distintos exatamente porque cada um resolve um problema diferente.

Na próxima seção, vamos consolidar tudo isso em boas práticas e diretrizes de projeto, mostrando como decidir, de forma objetiva, quando usar Queue com múltiplos consumidores — e quando não usar.

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