Idle Hook (vApplicationIdleHook): extensão segura do comportamento da Idle Task
A Idle Hook, implementada pela função vApplicationIdleHook(), é o principal mecanismo fornecido pelo FreeRTOS para permitir que o desenvolvedor injete comportamento customizado sempre que a Idle Task estiver em execução. Conceitualmente, ela funciona como um gancho de extensão do kernel, chamado repetidamente em todos os instantes em que o sistema não possui tarefas prontas para executar.
Para que a Idle Hook seja ativada, é necessário habilitar explicitamente esse recurso no arquivo FreeRTOSConfig.h, definindo a macro:
#define configUSE_IDLE_HOOK 1
Uma vez habilitada, o kernel passa a chamar automaticamente a função abaixo, que deve ser implementada pelo usuário em algum arquivo de código da aplicação:
void vApplicationIdleHook(void)
{
/* Código do usuário */
}
Do ponto de vista temporal, essa função é chamada com frequência potencialmente muito alta, dependendo do comportamento do sistema. Em um sistema com poucas tarefas ou com longos períodos ociosos, a Idle Hook pode ser executada milhares ou até milhões de vezes por segundo. Por isso, qualquer código colocado nela deve ser extremamente leve, não bloqueante e determinístico.
As restrições da Idle Hook são as mesmas da Idle Task, pois ela é executada dentro do contexto da própria Idle Task. Isso significa que não é permitido chamar funções que possam bloquear, nem acessar primitivas de sincronização que dependam de espera. Por exemplo, o código abaixo é incorreto:
void vApplicationIdleHook(void)
{
/* ERRADO: nunca usar delays ou esperas aqui */
vTaskDelay(pdMS_TO_TICKS(10));
}
O uso correto da Idle Hook está associado a tarefas de manutenção passiva, como:
- Incrementar contadores simples de tempo ocioso.
- Alimentar watchdogs que exigem chamadas frequentes.
- Coletar estatísticas de uso da CPU.
- Executar instruções de baixo consumo como
WFI(Wait For Interrupt).
Um exemplo clássico e seguro é a contabilização do tempo ocioso do sistema para cálculo de CPU Load:
volatile uint32_t idleCounter = 0;
void vApplicationIdleHook(void)
{
idleCounter++;
}
Esse contador pode ser lido periodicamente por uma tarefa de monitoramento, que compara o valor obtido com uma referência medida em condições de 100% ociosidade. Esse padrão é amplamente utilizado em sistemas industriais e embarcados críticos.
Outro uso extremamente comum — e recomendado — da Idle Hook é a entrada explícita em modo de baixo consumo, especialmente em sistemas que não utilizam Tickless Idle completo. Em arquiteturas ARM Cortex-M, por exemplo, a instrução __WFI() pode ser chamada diretamente:
#include "cmsis_gcc.h"
void vApplicationIdleHook(void)
{
__WFI(); /* Wait For Interrupt */
}
Nesse caso, o processador entra em modo sleep até que qualquer interrupção ocorra (tick, GPIO, DMA, etc.). Como a Idle Task só executa quando não há tarefas prontas, essa abordagem garante que o processador só consuma energia quando necessário, sem comprometer o escalonamento.
Entretanto, é importante destacar que esse método é uma forma manual e simplificada de economia de energia. Em sistemas mais sofisticados — especialmente aqueles com requisitos rigorosos de consumo — o FreeRTOS oferece um mecanismo mais avançado e integrado, conhecido como Tickless Idle, que envolve não apenas a Idle Task, mas também o controle do timer de sistema e do próprio scheduler.
Na próxima seção, vamos introduzir o conceito de Hook Functions em geral, incluindo a Tick Hook, explicando as diferenças conceituais e arquiteturais entre elas e preparando o terreno para o entendimento completo do Low Power e Tickless Idle no FreeRTOS.