5 – Exemplo Completo: Arquitetura Real com Tarefas e Soft Timers no FreeRTOS
Nesta seção, vamos consolidar os conceitos apresentados ao longo do artigo em uma arquitetura típica de sistema embarcado real, utilizando tarefas e soft timers de forma complementar, clara e escalável. O objetivo é mostrar como pensar o projeto, não apenas como escrever o código.
Cenário proposto
Considere um sistema embarcado com as seguintes responsabilidades:
- Leitura periódica de um sensor (a cada 1 segundo)
- Processamento dos dados do sensor
- Indicação visual por LED
- Comunicação serial para debug
A estratégia adotada será:
- Soft Timer → controla o período de amostragem
- Tarefa de processamento → executa a lógica principal
- Notificação direta → comunicação entre timer e tarefa
Esse arranjo evita:
- criação excessiva de tarefas,
- uso indevido de delays,
- desperdício de CPU.
Diagrama lógico da arquitetura
+------------------+
| Soft Timer 1s |
+--------+---------+
|
| Notification
v
+------------------+
| Processing Task |
+--------+---------+
|
v
+------------------+
| LED / UART |
+------------------+
Código completo do exemplo
Handles globais
#include "FreeRTOS.h"
#include "task.h"
#include "timers.h"
TaskHandle_t xProcessingTaskHandle = NULL;
TimerHandle_t xSampleTimer = NULL;
Callback do Soft Timer
void vSampleTimerCallback(TimerHandle_t xTimer)
{
xTaskNotifyFromISR(
xProcessingTaskHandle,
0,
eNoAction,
NULL
);
}
Aqui, o timer apenas sinaliza. Nenhuma lógica pesada é executada.
Tarefa de processamento
void vProcessingTask(void *pvParameters)
{
uint32_t sample;
for (;;)
{
xTaskNotifyWait(
0,
0,
NULL,
portMAX_DELAY
);
/* Simula leitura do sensor */
sample = 123;
/* Processamento */
HAL_GPIO_TogglePin(GPIOC, GPIO_PIN_13);
/* Debug */
printf("Amostra: %lu\r\n", sample);
}
}
Essa tarefa:
- permanece bloqueada a maior parte do tempo,
- acorda apenas quando o timer dispara,
- executa toda a lógica com segurança.
Inicialização do sistema
void app_main(void)
{
xTaskCreate(
vProcessingTask,
"Processing",
256,
NULL,
2,
&xProcessingTaskHandle
);
xSampleTimer = xTimerCreate(
"SampleTimer",
pdMS_TO_TICKS(1000),
pdTRUE,
NULL,
vSampleTimerCallback
);
if (xSampleTimer != NULL)
{
xTimerStart(xSampleTimer, 0);
}
vTaskStartScheduler();
}
Análise técnica da solução
Alguns pontos importantes dessa arquitetura:
- O timer define o ritmo do sistema
- A tarefa define o comportamento
- O consumo de CPU é mínimo
- A latência é previsível
- O código é fácil de escalar
Caso seja necessário adicionar:
- outro sensor → novo timer
- outra lógica → nova tarefa
- múltiplos eventos → Event Groups
A arquitetura permanece limpa e compreensível.
Quando NÃO usar Soft Timers
Mesmo sendo poderosos, soft timers não são adequados quando:
- a lógica é longa ou bloqueante
- há necessidade de prioridade específica
- o código usa drivers pesados
- há dependência de latência extremamente baixa
Nesses casos, uma tarefa dedicada é a escolha correta.