MCU & FPGA geral,RTOS Zephyr e Integração Avançada: Interrupções + Soft Timers + Workqueues

Zephyr e Integração Avançada: Interrupções + Soft Timers + Workqueues


2 — Interrupções no Zephyr

O papel correto das ISRs em pipelines de eventos robustos

Em sistemas embarcados de produção, interrupções (Interrupt Service Routines – ISRs) não são lugares para lógica. Elas são pontos de fronteira entre o mundo físico assíncrono e o sistema operacional. No Zephyr, isso é ainda mais explícito: a ISR deve capturar o evento e sair o mais rápido possível, delegando todo o processamento para mecanismos seguros do kernel.

2.1 O erro clássico: ISR como “mini-thread”

Em firmware imaturo, é comum ver interrupções fazendo:

  • Leitura de sensores complexos
  • Parsing de protocolos
  • Logs extensivos
  • Alocação de memória
  • Chamadas bloqueantes
  • Uso indevido de delays

Isso cria três problemas graves:

  1. Latência imprevisível (outras ISRs ficam bloqueadas).
  2. Deadlocks sutis (uso indevido de APIs não seguras em ISR).
  3. Sistema frágil (qualquer mudança quebra temporização).

No Zephyr, a regra é clara:

ISR só sinaliza. Threads processam.


2.2 O que uma ISR pode fazer no Zephyr

Dentro de uma interrupção, você deve se limitar a:

  • Capturar estado mínimo (timestamp, flag, contador).
  • Notificar o sistema por:
    • k_sem_give()
    • k_msgq_put(..., K_NO_WAIT)
    • k_work_submit()
    • k_timer_start() (em casos específicos)
  • Limpar a fonte da interrupção.

Nada além disso.


2.3 Exemplo 1 — Interrupção de GPIO bem projetada

Vamos partir de um caso real:
um sensor industrial que gera um pulso em GPIO quando um evento ocorre (ex.: encoder, sensor óptico, alarme externo).

Configuração do callback de interrupção

#include <zephyr/kernel.h>
#include <zephyr/device.h>
#include <zephyr/drivers/gpio.h>

/* Semáforo para sinalizar evento */
K_SEM_DEFINE(event_sem, 0, 1);

/* Callback da interrupção */
static void gpio_event_isr(const struct device *dev,
                           struct gpio_callback *cb,
                           uint32_t pins)
{
    /* ISR mínima: apenas sinaliza */
    k_sem_give(&event_sem);
}

static struct gpio_callback gpio_cb;

Inicialização do GPIO

static int gpio_init(void)
{
    const struct device *gpio_dev =
        DEVICE_DT_GET(DT_NODELABEL(gpio0));

    gpio_pin_configure(gpio_dev, 5,
        GPIO_INPUT | GPIO_PULL_UP);

    gpio_pin_interrupt_configure(
        gpio_dev, 5, GPIO_INT_EDGE_TO_ACTIVE);

    gpio_init_callback(&gpio_cb,
        gpio_event_isr, BIT(5));

    gpio_add_callback(gpio_dev, &gpio_cb);

    return 0;
}

📌 Observações importantes:

  • Nenhum processamento ocorre na ISR.
  • Nenhuma lógica de negócio.
  • Nenhuma temporização.
  • Apenas sinalização.

2.4 A thread consumidora do evento

Agora o processamento acontece em contexto de thread, onde tudo é seguro:

void event_thread(void)
{
    while (1) {
        /* Bloqueia até evento */
        k_sem_take(&event_sem, K_FOREVER);

        /* Aqui começa o pipeline real */
        process_event();
    }
}

Esse padrão já separa claramente:

  • Detecção (ISR)
  • Reação (thread)

Mas ainda há um problema:
👉 E se o evento gerar múltiplas etapas ou exigir temporização?

É aqui que entram Soft Timers e Workqueues — que não substituem a ISR, mas completam o pipeline.


2.5 Regra de ouro para ISRs em firmware industrial

Guarde este checklist mental:

✔ ISR deve ser curta e previsível
✔ ISR não conhece regras de negócio
✔ ISR não faz retry
✔ ISR não faz timeout
✔ ISR apenas empurra o evento para o pipeline

Tudo que cresce, escala ou muda não pertence à interrupção.

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