Quando “não aparece nada no terminal”: console UART vs RTT vs USB CDC + debug.conf (sem poluir o prj.conf)
Essa é a parte que mais “trava” quem está começando: você builda, flashea… e o terminal fica mudo. Em Zephyr, quase sempre é configuração de console / backend de log + hardware (pinos/USB) + overlay/chosen.
O example-application já te aponta um caminho maduro para lidar com variações de debug: ele mostra o uso de config extra por arquivo com -DEXTRA_CONF_FILE=debug.conf.
Vamos transformar isso em um método de trabalho.
printk x LOG_*: por que um aparece e outro não
printk()depende de ter um backend de console funcional, mas tende a ser mais “tolerante” em early boot.LOG_*depende do subsistema de logging estar habilitado e do backend estar certo (UART/RTT etc.). Se você habilitarCONFIG_LOG=ymas não configurar o backend, você pode ter logs “presos” (ou indo pra outro lugar).
No template, eu recomendo manter os dois: LOG_* para normalidade, printk para emergências.
Padrão de ouro: prj.conf “limpo” + debug.conf “agressivo”
Você mantém no prj.conf o mínimo necessário para o firmware “rodar” e cria um arquivo debug.conf para o que é pesado/verboso.
app/prj.conf (produção / base)
CONFIG_CONSOLE=y
CONFIG_UART_CONSOLE=y
CONFIG_PRINTK=y
CONFIG_LOG=y
CONFIG_LOG_MODE_DEFERRED=y
CONFIG_LOG_DEFAULT_LEVEL=3
app/debug.conf (debug)
# Log mais verboso
CONFIG_LOG_DEFAULT_LEVEL=4
CONFIG_LOG_BACKEND_SHOW_COLOR=y
# Ajuda muito em bugs de memória / stacks
CONFIG_ASSERT=y
CONFIG_THREAD_NAME=y
# Em alguns targets, rastreio de stack/erro
CONFIG_STACK_SENTINEL=y
CONFIG_HW_STACK_PROTECTION=y
Build usando o arquivo extra (exatamente no estilo que o template mostra):
west build -p always -b <SUA_BOARD> app -DEXTRA_CONF_FILE=debug.conf
Esse fluxo é excelente porque você não “contamina” seu projeto com debug permanente.
UART Console: o caminho mais comum (e onde dá errado)
Para UART console funcionar, você precisa de:
CONFIG_CONSOLE=yCONFIG_UART_CONSOLE=y- uma UART válida na board (DeviceTree) e frequentemente um
chosenapontando para ela
Se sua board é oficial do Zephyr, normalmente isso já vem OK. Quando não vem (ou quando você quer mudar a UART/pinos), você faz isso com overlay.
Exemplo de ajuste de chosen (conceito)
Em algumas situações você quer garantir que zephyr,console aponte para a UART certa. Um overlay pode incluir algo como:
/ {
chosen {
zephyr,console = &uart1;
};
};
Isso é um exemplo conceitual: a UART (
&uart1) precisa existir naquela board e estarstatus = "okay".
O ponto prático: quando o console não aparece, muitas vezes é porque você está falando na UART “errada” ou o pino está diferente do que você imagina.
RTT (SEGGER): quando você não quer depender de UART/pinos
RTT é muito usado porque evita a dependência de UART e funciona via debug probe (J-Link e afins). Em boards e probes compatíveis, é um “plano B” excelente.
Em geral você habilita RTT e aponta o log/console para ele via Kconfig. O detalhe exato muda conforme versão/board, então o jeito correto (sem chute) é:
- Ver quais opções estão disponíveis:
west build -t menuconfig - Buscar por “RTT” e “LOG_BACKEND” no menuconfig e habilitar.
Esse método é consistente porque o Zephyr expõe Kconfig de acordo com a board/SoC.
USB CDC ACM (console via USB): bom para ESP32/boards com USB nativo
Se sua board tem USB device e você quer um “serial over USB”, normalmente você habilita USB e o driver CDC ACM.
Novamente: varia por board/SoC. O processo robusto é o mesmo:
- conferir o DeviceTree (USB device habilitado)
- habilitar Kconfig correspondente (USB device stack + CDC ACM + console backend)
- se necessário, overlay para
chosendo console
Se você já usa Zephyr em ESP32, isso é muito comum porque elimina adaptador USB-UART externo.
Checklist rápido de “terminal mudo” (ordem que eu uso na vida real)
- A board está correta no build? (
-b ...) - O flash realmente gravou? (às vezes o
west flashfala ok, mas a placa resetou em bootloader) - Estou olhando a porta certa? (
/dev/ttyACM0vs/dev/ttyUSB0etc.) - Baudrate certo? (muitas boards usam 115200, mas não é lei universal)
- Existe
CONFIG_PRINTK=yeCONFIG_UART_CONSOLE=y? - Overlay mudou UART/console sem querer? (principalmente
chosen) - Se ainda falhar: tenta RTT, porque ele remove “UART/pinos/baud” do caminho.
Crescendo o projeto sem virar monolito: logs por arquivo (padrão limpo)
Quando você dividir seu src/ em arquivos, faça assim:
src/app_main.c→LOG_MODULE_REGISTER(app_main, LOG_LEVEL_INF);src/sensors.c→LOG_MODULE_REGISTER(app_sensors, LOG_LEVEL_INF);src/control.c→LOG_MODULE_REGISTER(app_control, LOG_LEVEL_INF);
E no CMakeLists.txt:
target_sources(app PRIVATE
src/app_main.c
src/sensors.c
src/control.c
)
Isso te dá logs filtráveis por subsistema desde o dia 1.