Módulo 2.2

Debugging y Troubleshooting

Herramientas y técnicas para depurar firmware NRF

Santi Scagliusi, PhD

Comenzar arrow_downward
bug_report
VS Code Debug
Breakpoints, variables
error
Errores fatales
addr2line, core dump
device_hub
Devicetree
Troubleshooting DT
cloud_upload
Memfault
Debugging remoto

Preparación para Debugging

Antes de depurar, configura el proyecto para obtener la mejor experiencia de debugging.

build Configuración de Build

Selecciona "Optimize for debugging (-Og)" en la configuración de build para habilitar símbolos de debug.

prj.conf
# Habilitado automáticamente con -Og
CONFIG_DEBUG_OPTIMIZATIONS=y
CONFIG_DEBUG_THREAD_INFO=y
# Opciones adicionales útiles
CONFIG_ASSERT=y
CONFIG_I2C_DUMP_MESSAGES=y
warning
Pristine Build: Si cambias la configuración, elimina la carpeta build/ y recompila. Los cambios de Kconfig pueden no aplicarse sin un build limpio.

¿Qué habilitan estas opciones?

check_circle
DEBUG_OPTIMIZATIONS
Compila con -Og: optimización mínima para debugging. Las variables no se optimizan y el código es más fácil de seguir.
check_circle
DEBUG_THREAD_INFO
Incluye información de threads en el binario. Necesario para ver threads en el debugger.
warning
ASSERT
Habilita comprobaciones de asserts. El programa se detiene si una condición falla, facilitando encontrar bugs.
terminal
I2C_DUMP_MESSAGES
Imprime por log todas las transacciones I2C. Útil para depurar comunicación con sensores.

Herramientas de VS Code

El entorno de debugging de VS Code con nRF Connect ofrece herramientas avanzadas.

Breakpoints

Breakpoint estándar
Detiene la ejecución en esa línea
Breakpoint condicional
Solo detiene si la expresión es verdadera
count > 100 && error_flag == true
Logpoint
Imprime mensaje sin detener ejecución
Value: {my_variable}
visibility Variables
> counter uint32_t 42
> sensor_data struct {...}
> is_connected bool true
search Watch
sensor_data.temperature 23.5
buffer[0] 0x42

Paneles Avanzados

Herramientas adicionales para inspeccionar el estado del sistema.

memory
Peripherals View

Mapa de memoria de registros de hardware. Lee y escribe registros directamente.

account_tree
Call Stack

Secuencia de llamadas a funciones hasta el punto actual. Navega por el historial.

format_list_numbered
Thread Viewer

Todos los threads de Zephyr, sus estados, prioridades y uso de stack.

list Threads
> main
Running Prio: 0 Stack: 45%
> sysworkq
Ready Prio: -1 Stack: 22%
> BT RX
Suspended Prio: -8 Stack: 18%

Monitor Mode Debugging

Depurar sin detener funciones críticas como BLE o PWM.

Modos de debugging

stop_circle
Halt Mode (por defecto)
CPU se detiene completamente en breakpoints
vs
play_circle
Monitor Mode
Funciones críticas continúan ejecutándose
lightbulb
Caso de uso: Si tu aplicación usa BLE, detener la CPU hará que la conexión se pierda. Con Monitor Mode, el stack BLE continúa funcionando.

Configuración

prj.conf
# Habilitar Monitor Mode
CONFIG_CORTEX_M_DEBUG_MONITOR_HOOK=y
CONFIG_SEGGER_DEBUGMON=y
Debug Console (VS Code)
# Activar en sesión de debug
-exec monitor exec SetMonModeDebug=1
warning
Monitor Mode tiene limitaciones: no todos los breakpoints funcionan igual y el timing puede variar.

Errores de Compilación y Fatales

Cómo interpretar y resolver errores comunes en el desarrollo.

build_circle Errores de compilación

Regla de oro: empieza por el PRIMER error en el log. Los errores posteriores suelen ser consecuencia del primero.

Errores de sintaxis
Faltan punto y coma, llaves, paréntesis...
Dependencias faltantes
Módulos no habilitados en Kconfig
Problemas de configuración
Revisa CMakeOutput.log y CMakeError.log

build/CMakeFiles/CMakeOutput.log
build/CMakeFiles/CMakeError.log

dangerous Errores fatales (crashes)

Cuando el firmware crashea, obtienes una dirección de memoria. Usa addr2line para convertirla a archivo:línea.

Terminal
$ arm-zephyr-eabi-addr2line \
-afp \
-e build/zephyr/zephyr.elf \
0x000045a2
# Output:
0x000045a2: nrfx_gpiote_init
at nrfx_gpiote.c:668
Flags de addr2line
-a
Muestra dirección
-f
Muestra función
-p
Formato legible

Análisis de Core Dump

Captura el estado completo del programa en el momento del crash.

prj.conf
# Habilitar core dump
CONFIG_DEBUG_COREDUMP=y
CONFIG_DEBUG_COREDUMP_BACKEND_LOGGING=y

¿Qué contiene un core dump?

  • memory Registros del procesador
  • layers Contenido del stack
  • data_array Secciones de memoria

Flujo de trabajo

1
Capturar del serial
Busca #CD:BEGIN# hasta #CD:END#
2
Convertir a binario
coredump_serial_log_parser.py
3
Iniciar servidor GDB
coredump_gdbserver.py
4
Analizar con GDB
arm-zephyr-eabi-gdb zephyr.elf

Comandos GDB útiles

bt
Backtrace (call stack)
info registers
Ver registros CPU
p <var>
Imprimir variable
x <addr>
Examinar memoria

Troubleshooting Devicetree

Cómo resolver el error "Undefined reference to __device_dts_ord_XX".

Build Output
undefined reference to `__device_dts_ord_123'

¿Qué significa este error?

El código referencia un dispositivo del devicetree que existe en la descripción pero no tiene driver activo.

help Causas comunes
  • El dispositivo tiene status = "disabled"
  • El driver no está habilitado en Kconfig
  • Falta el binding del compatible

Proceso de resolución

1
Buscar el node ID
En build/zephyr/include/generated/devicetree_generated.h
Busca __device_dts_ord_123 para ver qué nodo es
2
Verificar status
Revisa build/zephyr/zephyr.dts
El nodo debe tener status = "okay"
3
Verificar driver
Busca el CONFIG correspondiente al driver
Ejemplo: CONFIG_I2C, CONFIG_SPI, etc.
4
Corregir en .overlay
Añade o modifica en tu archivo .overlay
boards/nrf52840dk_nrf52840.overlay
&my_sensor {
status = "okay";
};

Debugging Físico

Herramientas de hardware para diagnosticar problemas que el software no puede detectar.

show_chart
Analizador lógico

Señales digitales: UART, I2C, SPI

battery_charging_full
Power Profiler Kit II

Consumo de corriente + 8ch logico

electrical_services
Multímetro

Voltaje, continuidad, resistencia

waves
Osciloscopio

Formas de onda, integridad de señal

Flujo de troubleshooting hardware

power Alimentación
arrow_forward
cable Conectividad
arrow_forward
code GPIO markers
arrow_forward
analytics Power profiling
arrow_forward
schedule Clock config
Alimentación

Verifica voltajes con multímetro. Asegúrate de que el regulador entrega el voltaje correcto.

GPIO markers

Pon toggles de GPIO en puntos clave del código y observa con analizador lógico.

Power profiling

El PPK2 muestra consumo en tiempo real. Picos anormales indican problemas.

Memfault: Debugging Remoto

Plataforma de observabilidad para dispositivos en producción.

prj.conf
# Habilitar Memfault
CONFIG_MEMFAULT=y
CONFIG_MEMFAULT_NCS_PROJECT_KEY="tu-project-key"
upload_file
Importante: Sube tu zephyr.elf a Memfault para que pueda simbolizar los crashes y mostrar funciones en lugar de direcciones.

Comandos shell

mflt test heartbeat Enviar heartbeat de prueba
mflt export Exportar datos pendientes
Memfault Dashboard
my-nrf-project
Dispositivos activos
1,247
trending_up
Crashes (últimas 24h)
3
error
Reboot reason
Hard Fault @ main.c:142
restart_alt
bug_report
Crashes simbolizados
system_update
OTA updates
analytics
Métricas custom
notifications
Alertas

Resumen de Herramientas

Cuándo usar cada herramienta de debugging.

Herramienta Caso de uso Tipo
VS Code Debugger Debugging interactivo, paso a paso Software
Monitor Mode Debug sin perder conexión BLE/PWM Software
addr2line Convertir direcciones a código fuente CLI
Core Dump + GDB Análisis post-mortem de crashes CLI
Power Profiler Kit II Consumo + señales digitales Hardware
Memfault Debugging remoto, OTA, métricas Cloud
build

Preparación

Compila con -Og y habilita DEBUG_THREAD_INFO para mejor experiencia de debug.

error

Errores

Empieza por el primer error. Usa addr2line para crashes y core dump para análisis profundo.

cloud

Producción

Memfault permite debugging remoto de dispositivos en producción.

tips_and_updates

"El 90% de los bugs se resuelven con logs estratégicos y breakpoints condicionales."

No subestimes el poder de un simple LOG_INF en el lugar correcto.

arrow_forward Siguiente módulo

2.3 Periféricos analógicos: ADC

Conversión analógico-digital con el nRF.