Introduction to Embedded Debugging
Embedded Systems Mastery
Fundamentals & Architecture
Microcontrollers, memory, interruptsSTM32 & ARM Cortex-M Development
ARM architecture, peripherals, HALRTOS Fundamentals (FreeRTOS/Zephyr)
Task management, scheduling, synchronizationCommunication Protocols Deep Dive
UART, SPI, I2C, CAN, USBEmbedded Linux Fundamentals
Linux kernel, userspace, filesystemU-Boot Bootloader Mastery
Boot process, configuration, customizationLinux Device Drivers
Character, platform, network driversLinux Kernel Customization
Configuration, modules, debuggingAndroid System Architecture
AOSP layers, services, BinderAndroid HAL & Native Development
HIDL, AIDL, NDK, JNIAndroid BSP & Kernel
BSP development, kernel integrationDebugging & Optimization
JTAG, GDB, profiling, optimizationDebugging embedded systems requires specialized tools—JTAG probes, logic analyzers, and hardware debuggers. Unlike desktop development, you're often debugging without a display or keyboard.
JTAG & SWD Debugging
JTAG vs SWD
- JTAG: 4-5 pins (TCK, TMS, TDI, TDO, TRST), boundary scan, multi-core
- SWD: 2 pins (SWDIO, SWCLK), ARM Cortex-M specific, simpler
# Popular debug probes
# J-Link (Segger) - Most common professional probe
# ST-Link - Bundled with STM32 dev boards
# CMSIS-DAP - Open standard
# OpenOCD - Open On-Chip Debugger
openocd -f interface/stlink.cfg -f target/stm32f4x.cfg
# OpenOCD commands
> reset halt # Stop CPU
> flash write_image firmware.elf
> resume # Continue execution
> reg # Show registers
> mdw 0x40000000 10 # Memory dump (10 words)
GDB for Embedded Systems
# Connect to OpenOCD
arm-none-eabi-gdb firmware.elf
(gdb) target remote localhost:3333
(gdb) monitor reset halt
(gdb) load # Flash firmware
# Debugging commands
(gdb) break main # Set breakpoint
(gdb) continue # Run
(gdb) next # Step over
(gdb) step # Step into
(gdb) print variable # Inspect variable
(gdb) info registers # Show registers
(gdb) x/10xw 0x20000000 # Examine memory
# Watchpoints (trigger on memory access)
(gdb) watch my_variable # Break on write
(gdb) rwatch my_variable # Break on read
(gdb) awatch my_variable # Break on access
Logic Analyzers & Oscilloscopes
- Logic Analyzer: Digital signals, protocol decode (SPI, I2C, UART)
- Oscilloscope: Analog signals, timing, signal integrity, power rails
# Protocol analysis with sigrok
sigrok-cli -d fx2lafw -c samplerate=1M -o capture.sr
# Decode I2C
sigrok-cli -i capture.sr -P i2c:scl=D0:sda=D1
# Decode SPI
sigrok-cli -i capture.sr -P spi:clk=D0:mosi=D1:miso=D2:cs=D3
Trace Analysis (ETM/ITM)
ETM (Embedded Trace Macrocell) provides non-intrusive instruction tracing; ITM (Instrumentation Trace Macrocell) provides printf-style debugging via SWO pin.
// ITM printf via SWO (ARM Cortex-M)
#include "core_cm4.h"
int _write(int file, char *ptr, int len) {
for (int i = 0; i < len; i++) {
ITM_SendChar(*ptr++);
}
return len;
}
// Usage
printf("Debug: value = %d\n", value);
Memory Debugging
// Stack overflow detection (FreeRTOS)
#define configCHECK_FOR_STACK_OVERFLOW 2
void vApplicationStackOverflowHook(TaskHandle_t xTask,
char *pcTaskName) {
printf("Stack overflow in: %s\n", pcTaskName);
while(1);
}
// Heap usage tracking
size_t xPortGetFreeHeapSize(void); // Current free
size_t xPortGetMinimumEverFreeHeapSize(void); // Minimum ever
// Memory corruption detection
// Use canary values at memory boundaries
#define CANARY 0xDEADBEEF
Profiling & Performance Analysis
// DWT cycle counter (ARM Cortex-M)
CoreDebug->DEMCR |= CoreDebug_DEMCR_TRCENA_Msk;
DWT->CYCCNT = 0;
DWT->CTRL |= DWT_CTRL_CYCCNTENA_Msk;
// Measure cycles
uint32_t start = DWT->CYCCNT;
my_function();
uint32_t cycles = DWT->CYCCNT - start;
float us = cycles / (SystemCoreClock / 1000000.0f);
# Linux perf (embedded Linux)
perf stat ./my_program
perf record -g ./my_program
perf report
# ftrace for kernel
echo function_graph > /sys/kernel/debug/tracing/current_tracer
cat /sys/kernel/debug/tracing/trace
Power Optimization
// Low power modes (STM32)
HAL_PWR_EnterSLEEPMode(PWR_MAINREGULATOR_ON, PWR_SLEEPENTRY_WFI);
HAL_PWR_EnterSTOPMode(PWR_LOWPOWERREGULATOR_ON, PWR_STOPENTRY_WFI);
HAL_PWR_EnterSTANDBYMode();
// Clock gating - disable unused peripherals
__HAL_RCC_GPIOB_CLK_DISABLE();
__HAL_RCC_USART2_CLK_DISABLE();
// Reduce clock speed when idle
SystemClock_Config_8MHz(); // Low speed
SystemClock_Config_168MHz(); // Full speed when needed
- Use sleep modes aggressively (WFI/WFE)
- Disable unused peripherals and clocks
- Reduce CPU frequency when possible
- Use DMA instead of CPU polling
- Optimize interrupt handlers (keep short)
Code Size & Speed Optimization
# Compiler optimization flags
-Os # Optimize for size
-O2 # Optimize for speed
-O3 # Aggressive speed (larger code)
-flto # Link-time optimization
# Size analysis
arm-none-eabi-size firmware.elf
arm-none-eabi-nm --size-sort firmware.elf | tail -20
# Linker garbage collection
-ffunction-sections -fdata-sections
-Wl,--gc-sections
Conclusion & Series Summary
Congratulations! You've completed the Complete Embedded Systems Series. From bare-metal MCU programming through RTOS, Linux, Android, and debugging—you now have a comprehensive foundation for embedded systems development.
- ? MCU fundamentals, architectures, memory
- ? ARM Cortex-M and STM32 development
- ? RTOS (FreeRTOS, Zephyr) task management
- ? Communication protocols (UART, SPI, I2C, CAN, USB)
- ? Embedded Linux, U-Boot, device drivers
- ? Linux kernel customization
- ? Android system architecture, HAL, BSP
- ? Debugging and optimization techniques