Back to Home

MCU Firmware Debugging: Diagnostic Methods

Article describes microcontroller firmware diagnostic methods: from basic HeartBeat LED and MCO indicators to CLI with logging and GPIO tracing. Details on tools without violating real-time timings, with code examples for STM32. Recommendations for senior developers.

Firmware Diagnostics: CLI, GDB, GPIO for MCU
Advertisement 728x90

Debugging Microcontroller Firmware: Proven Diagnostic Methods

Firmware diagnostics on microcontrollers start with basic system parameter checks. Without them, development turns into guesswork. We'll cover proven techniques, from simple LEDs to advanced interfaces, focusing on real-world scenarios for STM32 and similar platforms.

First step: output the system clock to MCO pins. This lets you measure the actual HSE or SYSCLK frequency with an oscilloscope after division.

HAL_RCC_MCOConfig(RCC_MCO1, RCC_MCO1SOURCE_HSE, RCC_MCODIV_4);
HAL_RCC_MCOConfig(RCC_MCO2, RCC_MCO2SOURCE_SYSCLK, RCC_MCODIV_5);

{.pad.port=PORT_C, .pad.pin=9, .name="MCO_2",   .stm_mode=GPIO_MODE_AF_PP,      .gpio_pull=GPIO__PULL_AIR, .speed=GPIO_SPEED_FREQ_VERY_HIGH,  .alternate= GPIO_AF0_MCO,},
{.pad.port=PORT_A, .pad.pin=8, .name="MCO_1",   .stm_mode=GPIO_MODE_AF_PP,      .gpio_pull=GPIO__PULL_AIR, .speed=GPIO_SPEED_FREQ_VERY_HIGH,  .alternate= GPIO_AF0_MCO,},

Comparing measurements against your code reveals clock configuration errors.

Google AdInline article slot

Status Indicators and Basic Checks

A heartbeat LED is a must-have in any firmware. A 1 Hz blinking LED confirms the code is running, verifies timing, and shows the system is alive. Add a separate red LED for software or hardware errors.

  • Advantages: Visual smoke test—no extra gear needed.
  • Implementation: Timer with 500 ms period to toggle the pin.
  • Extensions: Multiple LEDs for subsystems (clocks, peripherals).

No blinking LED? Further debugging is pointless—the firmware didn't start or it's hung.

Assert functions add robust checks. They trigger on zero arguments:

Google AdInline article slot
  • makeAssert: Build-time checks from Makefile.
  • preprocAssert: Preprocessor validations.
  • staticAssert: Compile-time config validation.
  • DynamicAssert: Runtime with GDB breakpoint support.

Strategic assert placement pinpoints failures across project phases.

Advanced Debugging via Interfaces

CLI over UART is the most flexible tool. A full-duplex text interface on Rx/Tx/GND enables:

  • Reading/writing memory by address.
  • Calling functions by pointer.
  • Monitoring counters, sending I2C/SPI/UART packets.
  • Interpreting timer registers.

Minimal CLI features:

Google AdInline article slot
  • Input echo.
  • Command history in non-volatile memory.
  • Help and TAB completion.
  • Authentication.
  • Colored output (red for errors, yellow for warnings).
  • Table rendering (GPIO, ADC).

CLI preserves real-time timing, unlike JTAG/SWD. RAM logging with UART flush post-init diagnoses early boot, including clocks. Support levels: LOG_ERROR, LOG_WARNING, LOG_INFO, LOG_DEBUG with module filters (e.g., ll usb debug).

Signal Analysis Tools

For real-time processes, use GPIO as markers:

  • Toggle pins to count steps in system init.
  • GPIO mapper: Convert numbers to binary codes across pins.

An oscilloscope (at least 2 channels, digital) captures edges. Logic analyzers (Saleae, 8–16 channels) shine for buses like MII/I2S/SDIO: USB 3.0 speeds, PC-based period/frequency/duty cycle analysis.

DAC (10–12 bits) outputs analog values to the scope. Great for scheduler debugging: voltage steps reveal thread priorities.

Limitations of Step Debugging and Alternatives

GDB over SWD/JTAG halts on breakpoints (PC/LR from HardFault). But it messes with timing: hardware timers race ahead, WDT resets the MCU. Optimizations (-O0 -g3) eat Flash space, often unavailable.

Alternative: arm-none-eabi-addr2line to map HardFault addresses to source lines:

set ELF_FILE=C:/ncs/v2.1.0/nrf/applications/nrf5340_audio/build/gateway_app/zephyr/zephyr.elf
set ADDR2LINE="C:\Program Files (x86)\GNU Arm Embedded Toolchain\10 2021.10\bin\arm-none-eabi-addr2line.exe"
%ADDR2LINE% -e %ELF_FILE% 0x000054cd
%ADDR2LINE% -e %ELF_FILE% 0x0000857e

OLED displays provide standalone metrics: Tamagotchi-style monitoring without UART. Unit tests cover code sans debugger, enabling safe refactoring.

Key Takeaways

  • Heartbeat LED and MCO: Essential smoke tests—skip them, and you're flying blind.
  • CLI with logging levels: Total control without timing disruption.
  • GPIO/DAC + scope/analyzer: Real-time signal insights.
  • Asserts and addr2line: Pinpoint HardFaults without full debug.
  • GDB/SWD: Last resort due to timing distortions.

— Editorial Team

Advertisement 728x90

Read Next