MCU & FPGA RTOS ISR + RTOS na Prática com FreeRTOS

ISR + RTOS na Prática com FreeRTOS

APIs FromISR: por que elas existem e como funcionam

Um dos erros mais comuns de quem começa a usar FreeRTOS é tentar chamar, a partir de uma ISR, as mesmas funções usadas dentro de uma task. Essa tentativa normalmente resulta em comportamentos imprevisíveis, porque o kernel do FreeRTOS não foi projetado para ser acessado de forma arbitrária a partir de uma interrupção. É exatamente para resolver esse problema que existem as chamadas conhecidas como APIs FromISR.

Motivação conceitual

Dentro de uma task, o FreeRTOS assume que:

  • O código pode ser interrompido a qualquer momento pelo tick ou por outra interrupção.
  • É permitido bloquear (block) a task, aguardando eventos.
  • O escalonador pode ser invocado imediatamente.

Em uma ISR, nenhuma dessas premissas é válida. Uma interrupção:

  • Não pode bloquear.
  • Não pode chamar o escalonador diretamente de forma arbitrária.
  • Executa em um contexto especial de hardware, com restrições severas de tempo e reentrância.

Por isso, as funções xQueueSend, xSemaphoreGive, xEventGroupSetBits e similares não podem ser usadas dentro de ISRs. Em seu lugar, o FreeRTOS fornece versões específicas, como:

  • xQueueSendFromISR
  • xSemaphoreGiveFromISR
  • xEventGroupSetBitsFromISR
  • xTaskNotifyFromISR

Essas funções são cuidadosamente implementadas para operar com seções críticas reduzidas, sem bloqueio e com lógica explícita para decidir se uma troca de contexto deve ocorrer ao final da interrupção.


O parâmetro xHigherPriorityTaskWoken

Todas as APIs FromISR seguem um padrão muito importante, que costuma gerar dúvidas:

BaseType_t xHigherPriorityTaskWoken = pdFALSE;

Esse parâmetro funciona como um indicador de preempção. Ele informa se a ação executada dentro da ISR (por exemplo, liberar um semáforo) fez com que uma task de prioridade maior do que a task atual se tornasse pronta para executar.

Internamente, o FreeRTOS:

  1. Executa a operação solicitada (ex: liberar semáforo).
  2. Verifica se alguma task desbloqueada possui prioridade maior que a task interrompida.
  3. Se sim, seta xHigherPriorityTaskWoken = pdTRUE.

A ISR não realiza a troca de contexto diretamente. Em vez disso, ao final da ISR, esse indicador é usado para solicitar ao kernel que execute um context switch imediatamente após o retorno da interrupção.

O padrão correto de uso é:

void EXTI0_IRQHandler(void)
{
    BaseType_t xHigherPriorityTaskWoken = pdFALSE;

    /* Limpa a flag da interrupção de hardware */

    xSemaphoreGiveFromISR(xButtonSemaphore, &xHigherPriorityTaskWoken);

    portYIELD_FROM_ISR(xHigherPriorityTaskWoken);
}

A macro portYIELD_FROM_ISR() é dependente da arquitetura e:

  • Solicita ao kernel uma troca de contexto
  • Garante que, ao sair da ISR, a task mais prioritária execute imediatamente

Por que não chamar o escalonador diretamente?

O FreeRTOS separa claramente:

  • Decisão de escalonamento
  • Execução da troca de contexto

Essa separação é essencial para manter a portabilidade do kernel entre arquiteturas (Cortex-M, RISC-V, AVR, etc.). A ISR apenas sinaliza a necessidade de troca, e o port layer cuida da implementação específica do hardware.

Essa abordagem evita:

  • Trocas de contexto aninhadas
  • Corrupção de pilha
  • Estados inconsistentes do kernel

Resumo prático desta seção

Do ponto de vista arquitetural:

  • ISR nunca deve chamar APIs normais do FreeRTOS.
  • Sempre utilize versões FromISR.
  • Sempre avalie corretamente xHigherPriorityTaskWoken.
  • Sempre finalize a ISR com portYIELD_FROM_ISR() quando aplicável.

Esse padrão garante:

  • Baixa latência
  • Determinismo temporal
  • Escalonamento correto
  • Sistema estável e previsível

0 0 votos
Classificação do artigo
Inscrever-se
Notificar de
guest
0 Comentários
mais antigos
mais recentes Mais votado
Feedbacks embutidos
Ver todos os comentários

Related Post

0
Adoraria saber sua opinião, comente.x