Software Timers como Geradores de Eventos Temporais
Em uma arquitetura orientada a eventos madura, tempo também é um evento. A necessidade de executar ações periódicas, atrasadas ou condicionadas ao tempo não deve ser tratada com vTaskDelay() espalhado pelo código, pois isso rapidamente cria acoplamento temporal difícil de manter. No FreeRTOS, o mecanismo correto para transformar tempo em eventos são os Software Timers.
Um Software Timer não executa lógica pesada. Ele apenas dispara um callback curto, executado no contexto da Timer Service Task. A partir desse callback, o evento temporal deve ser encaminhado para tarefas apropriadas, mantendo a arquitetura orientada a eventos limpa e determinística.
Modelo conceitual correto para Software Timers
O erro mais comum é tratar o callback do timer como uma mini-task. Arquiteturalmente, isso é incorreto. O callback deve ser visto como um produtor de eventos temporais, não como consumidor.
O fluxo ideal é:
- O timer expira
- O callback gera um evento
- Uma tarefa acorda e executa a lógica
Esse padrão preserva isolamento, evita bloqueios indevidos e mantém o controle de prioridades sob o escalonador.
Exemplo 1 — Timer gerando evento simples
TimerHandle_t watchdogTimer;
void vWatchdogTimerCallback(TimerHandle_t xTimer)
{
xTaskNotifyGive(watchdogTaskHandle);
}
A tarefa consumidora:
void vWatchdogTask(void *pvParameters)
{
for (;;)
{
ulTaskNotifyTake(pdTRUE, portMAX_DELAY);
checkSystemHealth();
}
}
Nesse modelo, o timer é apenas o gatilho temporal, e toda a lógica reside na tarefa correta.
Exemplo 2 — Timer periódico como evento de sistema
#define EVT_HEARTBEAT (1 << 0)
void vHeartbeatTimerCallback(TimerHandle_t xTimer)
{
xEventGroupSetBits(systemEventGroup, EVT_HEARTBEAT);
}
Tarefa consumidora:
void vSystemMonitorTask(void *pvParameters)
{
for (;;)
{
xEventGroupWaitBits(
systemEventGroup,
EVT_HEARTBEAT,
pdTRUE,
pdFALSE,
portMAX_DELAY
);
sendHeartbeat();
}
}
Esse padrão é comum em monitoramento, telemetria e supervisão.
Exemplo 3 — Timer como agendador leve de eventos
typedef enum
{
EVT_SAMPLE,
EVT_REPORT
} TimerEvent_t;
void vSchedulerTimerCallback(TimerHandle_t xTimer)
{
TimerEvent_t evt = (TimerEvent_t)pvTimerGetTimerID(xTimer);
xQueueSend(timerEventQueue, &evt, 0);
}
Esse modelo permite criar um agendador orientado a eventos, sem tasks extras e com excelente previsibilidade.
Prioridade da Timer Service Task
Um ponto arquitetural crítico é que todos os Software Timers compartilham a Timer Service Task. Se essa task for mal configurada ou sobrecarregada, todos os eventos temporais do sistema serão afetados.
Boas práticas incluem:
- Callbacks extremamente curtos
- Nunca bloquear dentro do callback
- Encaminhar eventos, não executar lógica
- Ajustar
configTIMER_TASK_PRIORITYconscientemente
Integração com arquiteturas orientadas a eventos
Quando bem utilizados, Software Timers permitem:
- Eliminar delays ativos
- Centralizar lógica temporal
- Criar sistemas mais reativos
- Reduzir jitter
- Facilitar testes e simulação
Eles são o elo entre tempo físico e eventos lógicos dentro do sistema.
Na próxima seção, entraremos em um dos pontos mais importantes do artigo: como combinar múltiplos mecanismos de eventos de forma arquiteturalmente correta, evitando acoplamento, latência excessiva e comportamentos não determinísticos.
Vamos para uma das partes mais importantes do artigo.