Software Timers no FreeRTOS: Temporização Sem Bloqueio e Execução Diferida
Os Software Timers do FreeRTOS permitem executar funções de callback após um intervalo de tempo ou de forma periódica, sem a necessidade de criar uma task dedicada. Eles são frequentemente mal compreendidos e, por isso, subutilizados ou usados de forma incorreta, principalmente como substitutos diretos de vTaskDelay(), o que nem sempre é apropriado.
Arquiteturalmente, um software timer não é uma task independente. Todos os timers são gerenciados por uma task interna do FreeRTOS, chamada Timer Service Task. Isso significa que o código executado no callback do timer:
- roda no contexto dessa task interna,
- não deve bloquear,
- e não deve executar código pesado.
Modelo Conceitual
Um software timer é ideal para:
- executar ações periódicas simples,
- implementar timeouts,
- postergar execução (deferred execution),
- substituir delays espalhados pelo código.
Existem dois tipos:
- One-shot: executa uma vez.
- Auto-reload: executa periodicamente.
Criação de um Software Timer
#include "FreeRTOS.h"
#include "timers.h"
TimerHandle_t xHeartbeatTimer;
/**
* @brief Callback executado pelo timer.
*/
void vHeartbeatCallback(TimerHandle_t xTimer)
{
toggle_status_led();
}
void vInit(void)
{
xHeartbeatTimer = xTimerCreate(
"Heartbeat",
pdMS_TO_TICKS(1000),
pdTRUE, // Auto-reload
NULL,
vHeartbeatCallback
);
xTimerStart(xHeartbeatTimer, 0);
}
Timers vs vTaskDelay()
Embora ambos envolvam temporização, o modelo mental é diferente:
vTaskDelay()
→ pausa uma task inteira, consumindo pilha e contexto.- Software Timer
→ agenda uma ação, sem criar nova task.
Use vTaskDelay() quando:
- a task tem um fluxo próprio contínuo,
- o atraso faz parte da lógica principal da task.
Use Software Timers quando:
- a ação é pontual ou periódica,
- não há necessidade de uma task dedicada,
- o código pode ser curto e não bloqueante.
Interação com Tasks
É comum que o callback de um timer sinalize uma task, ao invés de executar lógica pesada diretamente:
void vTimeoutCallback(TimerHandle_t xTimer)
{
xTaskNotify(xWorkerTaskHandle, 0x01, eSetBits);
}
Esse padrão mantém o sistema previsível e escalável.
Quando usar Software Timers
Use timers quando:
- Precisa de temporização sem bloquear tasks.
- Deseja reduzir número de tasks.
- Implementa watchdogs, heartbeats ou timeouts.
- Trabalha com máquinas de estado temporizadas.
Evite timers quando:
- A lógica é longa ou bloqueante.
- É necessário acesso direto a recursos críticos protegidos por mutex.
- A temporização depende de alta precisão em sistemas muito carregados.
Vantagens Técnicas
- Reduz consumo de RAM.
- Simplifica arquitetura.
- Centraliza temporizações.
- Evita delays espalhados pelo código.
Armadilhas comuns
- Executar código pesado no callback.
- Usar funções bloqueantes.
- Criar timers demais sem planejamento.
- Esquecer que todos compartilham a mesma task interna.