Padrões de Controle de Fluxo, Estados e Recuperação em RTOS
Em sistemas com FreeRTOS, fluxo implícito é inimigo do determinismo. if encadeado, flags globais e dependências ocultas tornam o comportamento do sistema impossível de prever sob carga, falhas ou eventos raros.
Os padrões desta seção tornam o comportamento do sistema explícito, rastreável e recuperável.
4.1 State Machine (Máquina de Estados Finita – FSM)
Problema resolvido:
Fluxo de controle espalhado por múltiplas tarefas e condicionais.
Ideia do padrão:
Representar o comportamento como estados explícitos e transições bem definidas.
Estrutura básica
typedef enum {
STATE_INIT,
STATE_IDLE,
STATE_ACTIVE,
STATE_ERROR
} SystemState;
static SystemState currentState = STATE_INIT;
Execução da máquina de estados (task dedicada)
void StateMachineTask(void *pvParameters)
{
for (;;)
{
switch (currentState)
{
case STATE_INIT:
InitHardware();
currentState = STATE_IDLE;
break;
case STATE_IDLE:
if (StartCondition())
currentState = STATE_ACTIVE;
break;
case STATE_ACTIVE:
RunControlLoop();
if (FaultDetected())
currentState = STATE_ERROR;
break;
case STATE_ERROR:
HandleFault();
currentState = STATE_IDLE;
break;
}
vTaskDelay(pdMS_TO_TICKS(10));
}
}
Vantagens:
- Fluxo claro
- Fácil depuração
- Excelente para controle e sequenciamento
Limitação:
Cresce mal quando há muitos estados e eventos → entra a HSM.
4.2 Hierarchical State Machine (HSM)
Problema resolvido:
Explosão combinatória de estados.
Ideia do padrão:
Estados possuem comportamento comum herdado de estados “pais”.
Exemplo conceitual
SYSTEM
├── OPERATIONAL
│ ├── IDLE
│ └── ACTIVE
└── FAULT
├── WARNING
└── CRITICAL
Implementação simplificada em C
typedef enum {
SUPER_OPERATIONAL,
SUPER_FAULT
} SuperState;
typedef enum {
SUB_IDLE,
SUB_ACTIVE,
SUB_WARNING,
SUB_CRITICAL
} SubState;
static SuperState superState;
static SubState subState;
void StateMachineStep(void)
{
switch (superState)
{
case SUPER_OPERATIONAL:
if (FaultDetected())
{
superState = SUPER_FAULT;
subState = SUB_WARNING;
break;
}
if (subState == SUB_IDLE && StartCondition())
subState = SUB_ACTIVE;
break;
case SUPER_FAULT:
HandleFaultCommon();
if (subState == SUB_WARNING && EscalateFault())
subState = SUB_CRITICAL;
if (FaultCleared())
{
superState = SUPER_OPERATIONAL;
subState = SUB_IDLE;
}
break;
}
}
Vantagens:
- Redução de duplicação
- Escala bem
- Muito usada em automotivo e aeroespacial
4.3 Mode Manager (Gerenciador de Modos)
Problema resolvido:
Múltiplas tarefas precisam reagir a mudanças globais de modo.
Ideia do padrão:
Uma tarefa central gerencia o modo do sistema, e os demais módulos se adaptam.
Modos típicos
typedef enum {
MODE_STARTUP,
MODE_NORMAL,
MODE_LOW_POWER,
MODE_MAINTENANCE
} SystemMode;
Mode Manager
static SystemMode currentMode;
void ModeManagerTask(void *pvParameters)
{
for (;;)
{
if (LowPowerRequested())
currentMode = MODE_LOW_POWER;
if (MaintenanceRequested())
currentMode = MODE_MAINTENANCE;
vTaskDelay(pdMS_TO_TICKS(100));
}
}
Uso pelas tarefas
void SensorTask(void *pvParameters)
{
for (;;)
{
if (currentMode == MODE_NORMAL)
ReadSensors();
vTaskDelay(pdMS_TO_TICKS(50));
}
}
Boa prática:
Substituir variável global por:
- Event Groups
- Message Queue
- Broadcast via Pub-Sub
4.4 Recovery Pattern (Padrão de Recuperação)
Problema resolvido:
Falhas transitórias travam o sistema.
Ideia do padrão:
Falhas são tratadas como estados, não exceções implícitas.
Exemplo de recuperação controlada
case STATE_ERROR:
LogFault();
ResetSubsystem();
if (RetryAllowed())
currentState = STATE_INIT;
else
EnterSafeState();
break;
Vantagens:
- Evita reboot desnecessário
- Permite retry controlado
- Essencial para sistemas remotos
4.5 Watchdog como Padrão Arquitetural
Problema resolvido:
Deadlocks silenciosos e travamentos não detectados.
Ideia do padrão:
Cada tarefa sinaliza vida periodicamente para um supervisor.
void SupervisorTask(void *pvParameters)
{
for (;;)
{
if (!AllTasksAlive())
SystemReset();
FeedWatchdog();
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
Importante:
O watchdog não substitui arquitetura correta — ele a complementa.