Checklist definitivo de boas práticas no Zephyr para comunicação serial
(o que fazer, o que evitar e como pensar como engenheiro de sistemas)
Esta seção fecha o artigo:
menos romantismo com “serial” e mais engenharia de sistemas.
Não é um checklist de API.
É um checklist de decisão arquitetural.
4.1 Mentalidade correta (antes de qualquer linha de código)
✔ Pense em bytes, não em strings
UART, SPI e I²C transportam bytes. Strings são uma convenção frágil, não um contrato.
✔ Assuma falha desde o primeiro dia
Bytes vão se perder, resets vão acontecer, versões vão divergir.
✔ Separação absoluta de camadas
Captura ≠ Framing ≠ Parsing ≠ Aplicação.
❌ Nunca trate comunicação como “debug melhorado”.
4.2 Captura de dados (driver / ISR / callback)
FAÇA:
- Use UART Async API ou interrupção
- Copie bytes rapidamente para um buffer
- Meça overflow e conte perdas
NÃO FAÇA:
printf()no callback- parsing no ISR
- lógica de aplicação em driver
👉 Regra de ouro:
Callback só move bytes. Ele não decide nada.
4.3 Bufferização (o desacoplamento que salva sistemas)
FAÇA:
ring_bufferpara streamsk_fifoouk_msgqpara mensagens completas- buffers com tamanho baseado em pior caso, não “funcionou aqui”
NÃO FAÇA:
- buffer global único sem proteção
- assumir que o consumidor sempre vai rodar a tempo
- ignorar overflow silenciosamente
👉 Se você não sabe quanto buffer precisa, você não conhece seu protocolo.
4.4 Framing (onde protocolos nascem ou morrem)
FAÇA:
- Start-of-frame explícito
- Length explícito
- CRC ou checksum
- Máquina de estados
NÃO FAÇA:
- depender de
\n - usar timeout como framing
- confiar em “pacote completo” implícito
👉 Sem framing, não existe protocolo.
4.5 Parsing (determinismo acima de tudo)
FAÇA:
- parsing byte-a-byte
- estados bem definidos
- reset automático em erro
- rejeição explícita de pacotes inválidos
NÃO FAÇA:
- casting direto de buffer para
struct - confiar em alinhamento
- aceitar dados sem validação
👉 Parsing bom não quebra, ele se recupera.
4.6 Integridade (CRC não é luxo)
FAÇA:
- CRC (mesmo simples) desde o início
- descarte silencioso de pacotes inválidos
- contadores de erro para diagnóstico
NÃO FAÇA:
- “confiar no barramento”
- achar que SPI/I²C “não precisa”
- validar só em debug
👉 CRC barato agora evita horas de campo depois.
4.7 Threads, prioridades e tempo real (Zephyr específico)
FAÇA:
- parsing em thread dedicada ou workqueue
- prioridade maior que a aplicação, menor que drivers críticos
- tempos de execução curtos e previsíveis
NÃO FAÇA:
- parsing pesado em thread de baixa prioridade
- lógica de protocolo bloqueante
k_sleep()dentro de callbacks
👉 Comunicação é infraestrutura, não feature.
4.8 Reuso entre UART, SPI e I²C (prova de arquitetura)
FAÇA:
- mesmo parser para todos os meios
- mesma estrutura de pacote
- abstração clara do transporte
NÃO FAÇA:
- protocolo “UART-only”
- duplicar parser por barramento
- misturar driver e protocolo
👉 Se seu protocolo não sobrevive à troca de barramento, ele é frágil.
4.9 Testabilidade (onde poucos chegam)
FAÇA:
- teste o parser em PC (host)
- injete bytes artificiais
- teste ruído, perda e reorder
NÃO FAÇA:
- testar só “com terminal”
- confiar apenas em hardware
- ignorar casos de erro
👉 Parser bom passa em teste sem hardware.
4.10 O erro final (e mais comum)
“Funciona no laboratório.”
Isso não é critério de aceitação.
Critério real é:
- sobrevive a ruído
- sobrevive a reset
- sobrevive a versão diferente
- se recupera sozinho
Encerramento
UART, SPI e I²C não revelam quem você é como engenheiro.
Seu protocolo revela.
O Zephyr oferece todas as ferramentas para fazer isso direito —
mas ele não impede que você faça errado.
Essa escolha ainda é sua.