From 735b786b65f7636025a1e34470dcbb4ded76a18e Mon Sep 17 00:00:00 2001 From: Bob Date: Fri, 5 Dec 2025 17:05:24 -0800 Subject: [PATCH] collapse detector with gdb support --- .gdbinit | 239 ++++++++ DEPLOYMENT_GUIDE.md | 66 --- ESP32-C5_GDB_Debugging_Guide.html | 951 ------------------------------ ESP32-C5_GDB_Debugging_Guide.md | 941 ----------------------------- GDB_GUIDE_README.md | 222 ------- MASS_DEPLOY.md | 363 ------------ PARALLEL_FLASH.md | 249 -------- QUICK_START.md | 70 --- README.md | 60 -- doc/GDB_THRESHOLD_TUNING_GUIDE.md | 488 +++++++++++++++ doc/THRESHOLD_QUICK_REF.md | 129 ++++ main/CMakeLists.txt | 12 +- main/main.c | 114 +++- 13 files changed, 977 insertions(+), 2927 deletions(-) create mode 100644 .gdbinit delete mode 100644 DEPLOYMENT_GUIDE.md delete mode 100644 ESP32-C5_GDB_Debugging_Guide.html delete mode 100644 ESP32-C5_GDB_Debugging_Guide.md delete mode 100644 GDB_GUIDE_README.md delete mode 100644 MASS_DEPLOY.md delete mode 100644 PARALLEL_FLASH.md delete mode 100644 QUICK_START.md delete mode 100644 README.md create mode 100644 doc/GDB_THRESHOLD_TUNING_GUIDE.md create mode 100644 doc/THRESHOLD_QUICK_REF.md diff --git a/.gdbinit b/.gdbinit new file mode 100644 index 0000000..7cea1f7 --- /dev/null +++ b/.gdbinit @@ -0,0 +1,239 @@ +# ESP32-C5 WiFi Monitor GDB Configuration +# Auto-loaded for WiFi frame analysis with PHY rate and duration + +# ============================================================ +# THRESHOLD TUNING COMMANDS +# ============================================================ + +define show_thresholds + printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" + printf "WiFi Monitor Thresholds (GDB-tunable)\n" + printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" + printf "High NAV threshold: %u us\n", threshold_high_nav_us + printf "Duration mismatch log: %u us\n", threshold_duration_mismatch_us + printf "PHY rate fallback: %u Mbps\n", threshold_phy_rate_fallback_mbps + printf "Duration multiplier: %ux expected\n", threshold_duration_multiplier + printf "\n" + printf "Collapse Detection:\n" + printf " Retry rate threshold: %.1f%%\n", threshold_retry_rate_percent + printf " Avg NAV collapse: %u us\n", threshold_avg_nav_collapse_us + printf " Collision percentage: %.1f%%\n", threshold_collision_percent + printf " Mismatch percentage: %.1f%%\n", threshold_mismatch_percent + printf "\n" + printf "Logging Control:\n" + printf " Log every N mismatches: %u (1=all, 10=every 10th)\n", log_every_n_mismatches + printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +end + +define set_high_nav + if $argc != 1 + printf "Usage: set_high_nav \n" + printf "Example: set_high_nav 8000 (set to 8ms)\n" + else + set threshold_high_nav_us = $arg0 + printf "High NAV threshold set to %u us\n", threshold_high_nav_us + end +end + +define set_mismatch_log + if $argc != 1 + printf "Usage: set_mismatch_log \n" + printf "Example: set_mismatch_log 15000 (log when NAV > 15ms)\n" + else + set threshold_duration_mismatch_us = $arg0 + printf "Duration mismatch logging threshold set to %u us\n", threshold_duration_mismatch_us + end +end + +define set_rate_fallback + if $argc != 1 + printf "Usage: set_rate_fallback \n" + printf "Example: set_rate_fallback 50 (fallback if < 50 Mbps)\n" + else + set threshold_phy_rate_fallback_mbps = $arg0 + printf "PHY rate fallback threshold set to %u Mbps\n", threshold_phy_rate_fallback_mbps + end +end + +define set_multiplier + if $argc != 1 + printf "Usage: set_multiplier \n" + printf "Example: set_multiplier 3 (NAV > 3x expected = mismatch)\n" + else + set threshold_duration_multiplier = $arg0 + printf "Duration multiplier set to %ux expected\n", threshold_duration_multiplier + end +end + +define set_log_rate + if $argc != 1 + printf "Usage: set_log_rate \n" + printf "Example: set_log_rate 10 (log every 10th mismatch)\n" + printf " set_log_rate 1 (log all mismatches)\n" + else + set log_every_n_mismatches = $arg0 + printf "Logging every %u mismatch(es)\n", log_every_n_mismatches + end +end + +define tune_sensitive + set threshold_high_nav_us = 3000 + set threshold_duration_mismatch_us = 5000 + set threshold_phy_rate_fallback_mbps = 150 + set threshold_duration_multiplier = 1.5 + set threshold_retry_rate_percent = 15.0 + set threshold_avg_nav_collapse_us = 5000 + set threshold_collision_percent = 5.0 + set threshold_mismatch_percent = 3.0 + printf "Thresholds set to SENSITIVE (catch more issues)\n" + show_thresholds +end + +define tune_normal + set threshold_high_nav_us = 5000 + set threshold_duration_mismatch_us = 10000 + set threshold_phy_rate_fallback_mbps = 100 + set threshold_duration_multiplier = 2 + set threshold_retry_rate_percent = 20.0 + set threshold_avg_nav_collapse_us = 10000 + set threshold_collision_percent = 10.0 + set threshold_mismatch_percent = 5.0 + printf "Thresholds set to NORMAL (default)\n" + show_thresholds +end + +define tune_relaxed + set threshold_high_nav_us = 10000 + set threshold_duration_mismatch_us = 20000 + set threshold_phy_rate_fallback_mbps = 50 + set threshold_duration_multiplier = 3 + set threshold_retry_rate_percent = 30.0 + set threshold_avg_nav_collapse_us = 15000 + set threshold_collision_percent = 15.0 + set threshold_mismatch_percent = 10.0 + printf "Thresholds set to RELAXED (fewer false positives)\n" + show_thresholds +end + +# ============================================================ +# FRAME ANALYSIS COMMANDS +# ============================================================ + +define show_frame_full + printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" + printf "Frame: %s\n", wifi_frame_type_str(frame->type, frame->subtype) + printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" + printf "RSSI: %d dBm\n", frame->rssi + printf "Channel: %d\n", frame->channel + printf "Retry: %s\n", frame->retry ? "YES" : "no" + printf "\n" + set $bw_str = "20MHz" + if frame->bandwidth == 1 + set $bw_str = "40MHz" + end + if frame->bandwidth == 2 + set $bw_str = "80MHz" + end + printf "PHY Rate: %u Kbps (%.1f Mbps)\n", frame->phy_rate_kbps, frame->phy_rate_kbps / 1000.0 + printf "Mode: MCS %d, BW %s, SGI %s\n", frame->mcs, $bw_str, frame->sgi ? "Yes" : "No" + printf "\n" + printf "Byte Count: %u bytes\n", frame->frame_len + if frame->phy_rate_kbps > 0 + set $tx_us = (frame->frame_len * 8000) / frame->phy_rate_kbps + set $overhead = 44 + set $expected = $tx_us + $overhead + printf "Expected Duration: %u us (%u tx + %u overhead)\n", $expected, $tx_us, $overhead + printf "Actual Duration (NAV): %u us\n", frame->duration_id + set $diff = frame->duration_id - $expected + if $diff > 0 + printf "Difference: +%d us LONGER than expected", $diff + if $diff > 5000 + printf " ⚠⚠⚠ HIGH!\n" + else + printf "\n" + end + else + set $diff = -$diff + printf "Difference: -%d us shorter\n", $diff + end + else + printf "Actual Duration (NAV): %u us\n", frame->duration_id + end + printf "\n" + printf "Dest: %02x:%02x:%02x:%02x:%02x:%02x\n", frame->addr1[0], frame->addr1[1], frame->addr1[2], frame->addr1[3], frame->addr1[4], frame->addr1[5] + printf "Source: %02x:%02x:%02x:%02x:%02x:%02x\n", frame->addr2[0], frame->addr2[1], frame->addr2[2], frame->addr2[3], frame->addr2[4], frame->addr2[5] + printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +end + +define show_duration + set $tx_us = 0 + if frame->phy_rate_kbps > 0 + set $tx_us = (frame->frame_len * 8000) / frame->phy_rate_kbps + set $expected = $tx_us + 44 + printf "%s: %u bytes @ %.1f Mbps → Expected %u us, NAV %u us", wifi_frame_type_str(frame->type, frame->subtype), frame->frame_len, frame->phy_rate_kbps/1000.0, $expected, frame->duration_id + set $diff = frame->duration_id - $expected + if $diff > 0 + printf " (+%d)\n", $diff + else + set $diff = -$diff + printf " (-%d)\n", $diff + end + else + printf "%s: %u bytes, NAV %u us\n", wifi_frame_type_str(frame->type, frame->subtype), frame->frame_len, frame->duration_id + end +end + +define find_high_nav + break monitor_frame_callback if frame->duration_id > 10000 + commands + silent + printf "⚠ HIGH NAV: " + show_duration + continue + end + printf "Watching for NAV > 10000 us\n" + continue +end + +define find_mismatch + break monitor_frame_callback if frame->phy_rate_kbps > 0 && frame->duration_id > ((frame->frame_len * 8000) / frame->phy_rate_kbps + 44) * 2 + printf "Watching for NAV 2x+ expected duration\n" + continue +end + +define watch_data + break monitor_frame_callback if frame->type == 2 + commands + silent + show_duration + continue + end + printf "Watching DATA frames\n" + continue +end + +printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +printf "WiFi Monitor GDB Commands Loaded\n" +printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +printf "Frame Analysis:\n" +printf " show_frame_full - Complete frame analysis\n" +printf " show_duration - Quick duration comparison\n" +printf " find_high_nav - Auto-break on high NAV\n" +printf " find_mismatch - Auto-break on NAV mismatch\n" +printf " watch_data - Monitor DATA frames\n" +printf "\n" +printf "Threshold Tuning:\n" +printf " show_thresholds - Display current thresholds\n" +printf " set_high_nav - Set high NAV threshold\n" +printf " set_mismatch_log - Set mismatch log threshold\n" +printf " set_rate_fallback - Set rate fallback threshold\n" +printf " set_multiplier - Set duration multiplier\n" +printf " set_log_rate - Log every Nth mismatch\n" +printf "\n" +printf "Preset Profiles:\n" +printf " tune_sensitive - Catch more issues (stricter)\n" +printf " tune_normal - Default settings (balanced)\n" +printf " tune_relaxed - Fewer false positives (lenient)\n" +printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" +printf "Type 'show_thresholds' to see current settings\n" +printf "━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━\n" diff --git a/DEPLOYMENT_GUIDE.md b/DEPLOYMENT_GUIDE.md deleted file mode 100644 index 4729248..0000000 --- a/DEPLOYMENT_GUIDE.md +++ /dev/null @@ -1,66 +0,0 @@ -# ESP32 Mass Deployment Scripts - -Scripts for deploying, configuring, and testing multiple ESP32 devices in parallel. - -## Scripts - -### 1. `mass_deploy.sh` - Basic Deployment -Simple parallel flashing and configuration. - -**Usage:** -```bash -chmod +x mass_deploy.sh -PASSWORD='your_wifi_password' ./mass_deploy.sh ~/Code/esp32/esp32-iperf -``` - -### 2. `mass_deploy_enhanced.sh` - Production Deployment (RECOMMENDED) -Enhanced version with retry logic and verification. - -**Usage:** -```bash -chmod +x mass_deploy_enhanced.sh - -# Basic usage -PASSWORD='your_wifi_password' ./mass_deploy_enhanced.sh ~/Code/esp32/esp32-iperf - -# With custom settings -PASSWORD='mypass' \ -SSID='MyNetwork' \ -START_IP='192.168.1.100' \ -./mass_deploy_enhanced.sh -``` - -**Environment Variables:** -- `PASSWORD` - WiFi password (required) -- `SSID` - WiFi SSID (default: ClubHouse2G) -- `START_IP` - Starting IP (default: 192.168.1.51) -- `MAX_RETRIES` - Retry attempts (default: 2) -- `VERIFY_PING` - Test after config (default: true) - -### 3. `test_devices.sh` - Device Testing -Tests all deployed devices with iperf. - -**Usage:** -```bash -chmod +x test_devices.sh -NUM_DEVICES=32 ./test_devices.sh -``` - -## Quick Start - -```bash -# 1. Connect all ESP32 devices via USB - -# 2. Deploy with one command -PASSWORD='your_wifi_pass' ./mass_deploy_enhanced.sh ~/Code/esp32/esp32-iperf - -# 3. Test all devices -NUM_DEVICES=32 ./test_devices.sh -``` - -## Performance - -**Before:** 60-90 minutes (sequential) -**After:** 15-20 minutes (parallel) ⚡ - -See DEPLOYMENT_GUIDE.md for full documentation. diff --git a/ESP32-C5_GDB_Debugging_Guide.html b/ESP32-C5_GDB_Debugging_Guide.html deleted file mode 100644 index d503970..0000000 --- a/ESP32-C5_GDB_Debugging_Guide.html +++ /dev/null @@ -1,951 +0,0 @@ - - - - - - ESP32-C5 GDB Debugging Guide - - - -
-

ESP32-C5 GDB Debugging Guide

-

Author: Bob McMahon

-

Hardware: ESP32-C5 DevKit (RISC-V)

-

ESP-IDF: v6.0 or later

-

Last Updated: December 2025

-
- - - -
-
-

Introduction

-

The ESP32-C5 is Espressif's first RISC-V microcontroller with dual-band WiFi 6 (802.11ax) support. Unlike its Xtensa predecessors (ESP32, ESP32-S3), the ESP32-C5's RISC-V architecture and built-in USB-JTAG interface make debugging significantly easier.

- -

This guide demonstrates how to use GDB (GNU Debugger) to debug ESP32-C5 firmware, focusing on real-world scenarios like troubleshooting WiFi driver issues, CSI configuration problems, and memory corruption.

-
- -
-

Why GDB Debugging?

- -

Traditional debugging with ESP_LOGI() statements has limitations:

- - - - - - - - - - - - - - - - - - -
MethodLimitations
Printf Debugging - • Alters timing and behavior
- • Cannot inspect internal driver state
- • Requires recompilation for each change
- • Output floods serial console -
LED Blink Debugging - • Very limited information
- • Time-consuming iteration
- • Cannot show complex state -
- -
- GDB debugging solves these problems: -
    -
  • Set breakpoints without modifying code
  • -
  • Inspect variables at any point in execution
  • -
  • Step through code line by line
  • -
  • Examine memory and registers
  • -
  • Watch variables for changes
  • -
  • View call stacks to understand program flow
  • -
  • Debug ESP-IDF internals (WiFi driver, FreeRTOS, etc.)
  • -
-
-
- -
-

ESP32-C5 Debug Capabilities

- -

The ESP32-C5 has built-in USB-JTAG support, eliminating the need for external debug adapters:

- -

Hardware Features

-
    -
  • Built-in USB-JTAG: Debug over the same USB cable used for flashing
  • -
  • 4 Hardware Breakpoints: No speed penalty
  • -
  • Unlimited Software Breakpoints: Via flash patching
  • -
  • 2 Watchpoints: Trigger on memory read/write
  • -
  • Real-time Debugging: Debug live, running firmware
  • -
- -

Comparison with Other ESP32 Chips

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
FeatureESP32 (Xtensa)ESP32-S3 (Xtensa)ESP32-C5 (RISC-V)
Debug InterfaceExternal JTAG requiredBuilt-in USB-JTAGBuilt-in USB-JTAG
Debuggerxt-gdb (Xtensa)xt-gdb (Xtensa)riscv32-esp-elf-gdb
Setup ComplexityHigh (extra hardware)MediumLow (just USB)
OpenOCD SupportMatureMatureGood (ESP-IDF v6.0+)
-
- -
-

Prerequisites

- -

Hardware

-
    -
  • ESP32-C5 DevKit with USB-C cable
  • -
  • Host Computer running Linux, macOS, or Windows (WSL2)
  • -
- -

Software

-
    -
  • ESP-IDF v6.0 or later (ESP32-C5 support)
  • -
  • OpenOCD (included with ESP-IDF)
  • -
  • GDB for RISC-V (riscv32-esp-elf-gdb, included with ESP-IDF)
  • -
- -

Verify Installation

-
# Check ESP-IDF version
-idf.py --version
-# Should show: ESP-IDF v6.0 or later
-
-# Check GDB
-riscv32-esp-elf-gdb --version
-# Should show: GNU gdb (esp-gdb) 12.1 or later
-
-# Check OpenOCD
-openocd --version
-# Should show: Open On-Chip Debugger 0.12.0-esp32 or later
-
- -
-

Building with Debug Symbols

- -

Debug symbols allow GDB to map machine code back to source code, showing variable names, function names, and line numbers.

- -

Method 1: Using menuconfig (Recommended)

-
cd ~/your-project
-idf.py menuconfig
- -

Navigate to and configure:

-
Component config
-  → Compiler options
-    → Optimization Level → Debug (-Og)       ← Select this
-    → [*] Generate debug symbols (-g)        ← Enable
-    → Debug information format → DWARF-4     ← Select
- -

Additional recommended settings:

-
Component config
-  → Compiler options
-    → [*] Enable assertions (assert)         ← Enable
-    → [ ] Strip function/variable names      ← DISABLE
-
-Component config
-  → FreeRTOS
-    → [*] Enable stack overflow checks       ← Enable
-    → Check method → Canary bytes           ← Select
- -

Optimization Levels Explained

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
LevelGCC FlagCode SpeedDebug QualityUse Case
Debug-OgMediumExcellentGDB debugging
None-O0SlowExcellentExtreme debugging
Size-OsMediumPoorProduction
Performance-O2FastPoorProduction
- -
- For debugging, always use -Og (Debug level). It provides good performance while preserving all variable information for GDB. -
- -

Build Process

-
cd ~/your-project
-
-# Clean previous build
-idf.py fullclean
-
-# Build with debug symbols
-idf.py build
-
-# Flash to device
-idf.py -p /dev/ttyUSB0 flash
- -

Verify Debug Symbols

-
# Check if ELF file contains debug sections
-riscv32-esp-elf-readelf -S build/your-project.elf | grep debug
-
-# Expected output (debug sections present):
-#   [27] .debug_aranges    PROGBITS        00000000 0f8a2c 004638 00      0   0  8
-#   [28] .debug_info       PROGBITS        00000000 0fd064 19d4f4 00      0   0  1
-#   [29] .debug_abbrev     PROGBITS        00000000 29a558 02b8f9 00      0   0  1
-#   [30] .debug_line       PROGBITS        00000000 2c5e51 0e7a3c 00      0   0  1
-
- -
-

Starting a Debug Session

- -

Three-Step Debug Process

-
    -
  1. Flash the firmware to the device
  2. -
  3. Start OpenOCD to connect to the device
  4. -
  5. Start GDB to control debugging
  6. -
- -

Step 1: Flash Firmware

-
cd ~/your-project
-idf.py -p /dev/ttyUSB0 flash
- -

Step 2: Start OpenOCD (Terminal 1)

-
cd ~/your-project
-idf.py openocd
- -
- Leave this terminal running. OpenOCD acts as a bridge between GDB and the ESP32-C5. -
- -

Step 3: Start GDB (Terminal 2)

-
cd ~/your-project
-idf.py gdb
- -

You're now in the GDB prompt and ready to debug!

- -

Quick Start Commands

-
(gdb) target remote :3333
-(gdb) file build/your-project.elf
-(gdb) monitor reset halt
-(gdb) thbreak app_main
-(gdb) continue
-
- -
-

Essential GDB Commands

- -

Navigation and Execution

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandShortcutDescription
break <location>bSet breakpoint
continuecResume execution
nextnStep over (skip function calls)
stepsStep into (enter functions)
finishfinRun until function returns
- -

Inspection

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandDescriptionExample
print <var>Print variable valuep my_variable
print *<ptr>Dereference pointerp *config
x/<fmt> <addr>Examine memoryx/32xb 0x40000000
info localsShow local variablesi lo
backtraceShow call stackbt
listShow source codel
- -

Breakpoints & Watchpoints

- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
CommandDescriptionExample
break <func>Break on function entryb esp_wifi_init
break <func> if <cond>Conditional breakpointb send if len > 1000
watch <var>Break when variable changeswatch my_counter
info breakpointsList all breakpointsi b
delete <num>Delete breakpointd 1
-
- -
-

Debugging Strategies

- -

Strategy 1: Breakpoint at Function Entry

-

Use case: Understand when and why a function is called.

-
(gdb) break esp_wifi_set_csi_config
-(gdb) continue
-# When it breaks...
-(gdb) info args
-(gdb) print *config
-(gdb) backtrace
-(gdb) continue
- -

Strategy 2: Conditional Breakpoints

-

Use case: Break only when specific conditions occur.

-
# Break only when error occurs
-(gdb) break esp_wifi_set_csi_config if $a0 != 0
-
-# Break only for specific SSID
-(gdb) break wifi_connect if strcmp(ssid, "MyNetwork") == 0
-
-# Break when buffer is full
-(gdb) break send_packet if queue_size >= 100
- -

Strategy 3: Step Through Algorithm

-

Use case: Understand complex logic step by step.

-
(gdb) break process_csi_data
-(gdb) continue
-(gdb) next    # Execute current line
-(gdb) next    # Next line
-(gdb) step    # Step into function call if any
-(gdb) finish  # Complete current function
- -

Strategy 4: Watch for Variable Changes

-

Use case: Find where a variable gets corrupted.

-
(gdb) watch connection_state
-(gdb) continue
-# GDB will break when variable changes
-(gdb) backtrace
-(gdb) print connection_state
-
- -
-

Real-World Examples

- -

Example 1: Debug CSI Configuration Failure

-

Problem: esp_wifi_set_csi_config() returns ESP_FAIL but we don't know why.

- -
(gdb) break esp_wifi_set_csi_config
-Breakpoint 1 at 0x42012a4e
-
-(gdb) continue
-Breakpoint 1, esp_wifi_set_csi_config (config=0x3ffb0000)
-
-# Examine the config structure
-(gdb) print *config
-$1 = {
-  enable = 1,
-  lltf_en = 1,
-  htltf_en = 1,
-  stbc_htltf2_en = 1,
-  ltf_merge_en = 1,
-  channel_filter_en = 1,    ← Suspicious!
-  manu_scale = 0
-}
-
-# Step through to see where it fails
-(gdb) step
-(gdb) step
-...
-(gdb) print error_code
-$2 = 259  ← ESP_FAIL (0x103)
-
-# Found it! channel_filter_en must be 0 on ESP32-C5
- -
- Solution: Set channel_filter_en = 0 in the code. -
- -

Example 2: Find Memory Corruption

-

Problem: A pointer is getting corrupted, causing crashes.

- -
# Set watchpoint on the pointer
-(gdb) watch *(void**)&my_buffer_ptr
-Hardware watchpoint 2: *(void**)&my_buffer_ptr
-
-# Run until it changes
-(gdb) continue
-Hardware watchpoint 2: *(void**)&my_buffer_ptr
-Old value = (void *) 0x3ffb1000
-New value = (void *) 0x00000000
-
-# See what code changed it
-(gdb) backtrace
-#0  process_packet (data=0x3ffb0800) at network.c:142
-#1  0x42008654 in network_task () at network.c:201
-
-# Look at the source
-(gdb) list
-137     void process_packet(uint8_t *data) {
-138         if (data == NULL) {
-139             ESP_LOGE(TAG, "Null data!");
-140             my_buffer_ptr = NULL;    ← Found it!
-141             return;
-142         }
- -
- Solution: Fix the null-pointer handling logic. -
- -

Example 3: Understand WiFi Connection Failure

-

Problem: WiFi connects but immediately disconnects.

- -
(gdb) break event_handler
-(gdb) condition 1 event_id == WIFI_EVENT_STA_DISCONNECTED
-(gdb) continue
-
-Breakpoint 1, event_handler (event_id=3, event_data=0x3ffb2000)
-
-# Examine disconnect reason
-(gdb) print *(wifi_event_sta_disconnected_t*)event_data
-$1 = {
-  ssid = "ClubHouse",
-  ssid_len = 9,
-  bssid = {0xe0, 0x46, 0xee, 0x07, 0xdf, 0x01},
-  reason = 2,    ← WIFI_REASON_AUTH_EXPIRE
-  rssi = -75
-}
-
-# Reason 2 = Authentication expired = weak signal or interference
- -
- Solution: Improve antenna placement or reduce distance to AP. -
-
- -
-

Troubleshooting

- -

Problem: "No symbol table is loaded"

-
- Symptom: -
(gdb) break app_main
-Function "app_main" not defined.
-
- -

Solutions:

-
# 1. Rebuild with debug symbols
-idf.py menuconfig  # Set optimization to Debug (-Og)
-idf.py fullclean build
-
-# 2. Load correct ELF file in GDB
-(gdb) file build/your-project.elf
-
-# 3. Verify symbols exist
-riscv32-esp-elf-nm build/your-project.elf | grep app_main
- -

Problem: "Cannot access memory at address 0x..."

-

Causes: Variable optimized out, out of scope, or invalid pointer

- -

Solutions:

-
# Check if variable exists
-(gdb) info locals
-(gdb) info args
-
-# Examine raw memory
-(gdb) print &my_variable
-(gdb) x/4xw 0x3ffb0000
- -

Problem: Breakpoint Not Hitting

-

Solutions:

-
# Check breakpoint status
-(gdb) info breakpoints
-
-# Try software breakpoint
-(gdb) delete 1
-(gdb) break my_func
-
- -
-

Advanced Techniques

- -

Technique 1: Scripting GDB

-

Create a .gdbinit file to automate common tasks:

- -
# ~/.gdbinit or project/.gdbinit
-
-# Connect automatically
-target remote :3333
-file build/CSI.elf
-
-# Define custom commands
-define reset-and-break
-    monitor reset halt
-    thbreak app_main
-    continue
-end
-
-# Set common breakpoints
-break esp_wifi_set_csi_config
-break esp_wifi_connect
- -

Technique 2: Debugging FreeRTOS Tasks

-
# Show all tasks
-(gdb) info threads
-  Id   Target Id                    Frame 
-* 1    Remote target                vTaskDelay ()
-  2    Remote target                prvIdleTask ()
-  3    Remote target                wifi_task ()
-
-# Switch to different task
-(gdb) thread 3
-
-# See that task's stack
-(gdb) backtrace
- -

Technique 3: Live Variable Modification

-

Change variables on-the-fly without recompiling:

- -
(gdb) break send_packet
-(gdb) continue
-
-# Change packet size before sending
-(gdb) print packet_size
-$1 = 1024
-(gdb) set packet_size = 64
-
-# Continue with modified value
-(gdb) continue
-
- -
-

Resources

- -

Official Documentation

- - -

ESP32 Community

- -
- -
-

Summary

- -

GDB debugging on the ESP32-C5 provides powerful insights into firmware behavior:

- -
-
    -
  • Built-in USB-JTAG eliminates external hardware requirements
  • -
  • Hardware and software breakpoints for flexible debugging
  • -
  • Real-time variable inspection without printf statements
  • -
  • Watchpoints to catch memory corruption
  • -
  • Call stack analysis to understand program flow
  • -
  • ESP-IDF driver debugging to troubleshoot library issues
  • -
-
- -

Key takeaways:

-
    -
  1. Always build with Debug (-Og) optimization for best debug experience
  2. -
  3. Use conditional breakpoints to break only when needed
  4. -
  5. Combine watchpoints with breakpoints to find memory corruption
  6. -
  7. Script common tasks in .gdbinit for faster debugging
  8. -
  9. The WiFi driver log is still the ground truth for connection status
  10. -
- -

GDB debugging significantly reduces debug time compared to printf-based approaches, especially for complex issues like WiFi driver bugs, FreeRTOS task interactions, and memory corruption.

-
-
- -
-

About this guide: Created based on real-world ESP32-C5 development experience, specifically debugging WiFi 6 CSI (Channel State Information) capture issues for the iperf WiFi Analyzer project.

- -

- iperf2 GitHub - iperf2 SourceForge -

- -

Hardware: ESP32-C5 DevKit
- Project: WiFi Collapse Detection using CSI

- -

© 2025 Bob McMahon. Last updated: December 4, 2025

-
- - diff --git a/ESP32-C5_GDB_Debugging_Guide.md b/ESP32-C5_GDB_Debugging_Guide.md deleted file mode 100644 index 09acceb..0000000 --- a/ESP32-C5_GDB_Debugging_Guide.md +++ /dev/null @@ -1,941 +0,0 @@ -# GDB Debugging on ESP32-C5: Complete Guide - -A comprehensive guide to debugging ESP32-C5 firmware using GDB and the built-in USB-JTAG interface. - -**Author**: Bob McMahon -**Hardware**: ESP32-C5 DevKit (RISC-V) -**ESP-IDF**: v6.0 or later -**Last Updated**: December 2025 - ---- - -## Table of Contents - -1. [Introduction](#introduction) -2. [Why GDB Debugging?](#why-gdb-debugging) -3. [ESP32-C5 Debug Capabilities](#esp32-c5-debug-capabilities) -4. [Prerequisites](#prerequisites) -5. [Building with Debug Symbols](#building-with-debug-symbols) -6. [Starting a Debug Session](#starting-a-debug-session) -7. [Essential GDB Commands](#essential-gdb-commands) -8. [Debugging Strategies](#debugging-strategies) -9. [Real-World Examples](#real-world-examples) -10. [Troubleshooting](#troubleshooting) -11. [Advanced Techniques](#advanced-techniques) -12. [Resources](#resources) - ---- - -## Introduction - -The ESP32-C5 is Espressif's first RISC-V microcontroller with dual-band WiFi 6 (802.11ax) support. Unlike its Xtensa predecessors (ESP32, ESP32-S3), the ESP32-C5's RISC-V architecture and built-in USB-JTAG interface make debugging significantly easier. - -This guide demonstrates how to use GDB (GNU Debugger) to debug ESP32-C5 firmware, focusing on real-world scenarios like troubleshooting WiFi driver issues, CSI configuration problems, and memory corruption. - ---- - -## Why GDB Debugging? - -Traditional debugging with `ESP_LOGI()` statements has limitations: - -| Method | Limitations | -|--------|-------------| -| **Printf Debugging** | - Alters timing and behavior
- Cannot inspect internal driver state
- Requires recompilation for each change
- Output floods serial console | -| **LED Blink Debugging** | - Very limited information
- Time-consuming iteration
- Cannot show complex state | - -**GDB debugging solves these problems:** - -- ✅ **Set breakpoints** without modifying code -- ✅ **Inspect variables** at any point in execution -- ✅ **Step through code** line by line -- ✅ **Examine memory** and registers -- ✅ **Watch variables** for changes -- ✅ **View call stacks** to understand program flow -- ✅ **Debug ESP-IDF internals** (WiFi driver, FreeRTOS, etc.) - ---- - -## ESP32-C5 Debug Capabilities - -The ESP32-C5 has **built-in USB-JTAG** support, eliminating the need for external debug adapters: - -### Hardware Features - -- **Built-in USB-JTAG**: Debug over the same USB cable used for flashing -- **4 Hardware Breakpoints**: No speed penalty -- **Unlimited Software Breakpoints**: Via flash patching -- **2 Watchpoints**: Trigger on memory read/write -- **Real-time Debugging**: Debug live, running firmware - -### Comparison with Other ESP32 Chips - -| Feature | ESP32 (Xtensa) | ESP32-S3 (Xtensa) | ESP32-C5 (RISC-V) | -|---------|----------------|-------------------|-------------------| -| **Debug Interface** | External JTAG required | Built-in USB-JTAG | Built-in USB-JTAG | -| **Debugger** | xt-gdb (Xtensa) | xt-gdb (Xtensa) | riscv32-esp-elf-gdb | -| **Setup Complexity** | High (extra hardware) | Medium | **Low** (just USB) | -| **OpenOCD Support** | Mature | Mature | Good (ESP-IDF v6.0+) | - ---- - -## Prerequisites - -### Hardware - -- **ESP32-C5 DevKit** with USB-C cable -- **Host Computer** running Linux, macOS, or Windows (WSL2) - -### Software - -- **ESP-IDF v6.0 or later** (ESP32-C5 support) -- **OpenOCD** (included with ESP-IDF) -- **GDB for RISC-V** (riscv32-esp-elf-gdb, included with ESP-IDF) - -### Verify Installation - -```bash -# Check ESP-IDF version -idf.py --version -# Should show: ESP-IDF v6.0 or later - -# Check GDB -riscv32-esp-elf-gdb --version -# Should show: GNU gdb (esp-gdb) 12.1 or later - -# Check OpenOCD -openocd --version -# Should show: Open On-Chip Debugger 0.12.0-esp32 or later -``` - ---- - -## Building with Debug Symbols - -Debug symbols allow GDB to map machine code back to source code, showing variable names, function names, and line numbers. - -### Method 1: Using menuconfig (Recommended) - -```bash -cd ~/your-project -idf.py menuconfig -``` - -Navigate to and configure: - -``` -Component config - → Compiler options - → Optimization Level → Debug (-Og) ← Select this - → [*] Generate debug symbols (-g) ← Enable - → Debug information format → DWARF-4 ← Select -``` - -Additional recommended settings: - -``` -Component config - → Compiler options - → [*] Enable assertions (assert) ← Enable - → [ ] Strip function/variable names ← DISABLE - -Component config - → FreeRTOS - → [*] Enable stack overflow checks ← Enable - → Check method → Canary bytes ← Select -``` - -Save and exit (`S` then `Q`). - -### Method 2: Direct sdkconfig Edit - -```bash -cd ~/your-project - -# Backup current config -cp sdkconfig sdkconfig.backup - -# Add debug settings -cat >> sdkconfig << 'EOF' -# Debug optimization -CONFIG_COMPILER_OPTIMIZATION_DEBUG=y -CONFIG_COMPILER_OPTIMIZATION_LEVEL_DEBUG=y - -# Enable assertions -CONFIG_COMPILER_OPTIMIZATION_ASSERTIONS_ENABLE=y - -# Stack checking -CONFIG_COMPILER_STACK_CHECK_MODE_NORM=y -CONFIG_FREERTOS_CHECK_STACKOVERFLOW_CANARY=y - -# Debug info -CONFIG_COMPILER_CXX_EXCEPTIONS=y -EOF -``` - -### Optimization Levels Explained - -| Level | GCC Flag | Code Speed | Code Size | Debug Quality | Use Case | -|-------|----------|------------|-----------|---------------|----------| -| **Debug** | `-Og` | Medium | Medium | **Excellent** | **GDB debugging** ✅ | -| None | `-O0` | Slow | Large | Excellent | Extreme debugging | -| Size | `-Os` | Medium | **Small** | Poor | Production | -| Performance | `-O2` | **Fast** | Medium | Poor | Production | -| Max Performance | `-O3` | **Fastest** | Large | Very Poor | Benchmarks | - -**For debugging, always use `-Og` (Debug level).** It provides good performance while preserving all variable information for GDB. - -### Build Process - -```bash -cd ~/your-project - -# Clean previous build -idf.py fullclean - -# Build with debug symbols -idf.py build - -# Flash to device -idf.py -p /dev/ttyUSB0 flash -``` - -### Verify Debug Symbols - -```bash -# Check if ELF file contains debug sections -riscv32-esp-elf-readelf -S build/your-project.elf | grep debug - -# Expected output (debug sections present): -# [27] .debug_aranges PROGBITS 00000000 0f8a2c 004638 00 0 0 8 -# [28] .debug_info PROGBITS 00000000 0fd064 19d4f4 00 0 0 1 -# [29] .debug_abbrev PROGBITS 00000000 29a558 02b8f9 00 0 0 1 -# [30] .debug_line PROGBITS 00000000 2c5e51 0e7a3c 00 0 0 1 -# [31] .debug_str PROGBITS 00000000 3ad88d 036184 01 MS 0 0 1 -``` - -If you don't see `.debug_*` sections, debug symbols are missing. Check your optimization settings. - ---- - -## Starting a Debug Session - -### Three-Step Debug Process - -1. **Flash the firmware** to the device -2. **Start OpenOCD** to connect to the device -3. **Start GDB** to control debugging - -### Step 1: Flash Firmware - -```bash -cd ~/your-project -idf.py -p /dev/ttyUSB0 flash -``` - -### Step 2: Start OpenOCD (Terminal 1) - -```bash -cd ~/your-project -idf.py openocd -``` - -Expected output: -``` -Open On-Chip Debugger v0.12.0-esp32-20230419 (2023-04-19-13:01) -Licensed under GNU GPL v2 -... -Info : [esp32c5] Target halted, PC=0x42008a4e, debug_reason=00000001 -Info : [esp32c5] Reset cause (3) - (Software core reset) -``` - -**Leave this terminal running.** OpenOCD acts as a bridge between GDB and the ESP32-C5. - -### Step 3: Start GDB (Terminal 2) - -```bash -cd ~/your-project -idf.py gdb -``` - -Expected output: -``` -GNU gdb (esp-gdb) 12.1_20221002 -... -(gdb) -``` - -You're now in the GDB prompt and ready to debug! - -### Quick Start Commands - -```gdb -# Connect to OpenOCD (usually done automatically) -target remote :3333 - -# Load symbols -file build/your-project.elf - -# Reset and halt at app_main -monitor reset halt -thbreak app_main -continue -``` - ---- - -## Essential GDB Commands - -### Navigation and Execution - -| Command | Shortcut | Description | Example | -|---------|----------|-------------|---------| -| `break ` | `b` | Set breakpoint | `b app_main` | -| `continue` | `c` | Resume execution | `c` | -| `next` | `n` | Step over (skip function calls) | `n` | -| `step` | `s` | Step into (enter functions) | `s` | -| `finish` | `fin` | Run until function returns | `fin` | -| `until ` | `u` | Run until line number | `u 100` | -| `run` | `r` | Start program | `r` | - -### Inspection - -| Command | Shortcut | Description | Example | -|---------|----------|-------------|---------| -| `print ` | `p` | Print variable value | `p my_variable` | -| `print *` | `p *` | Dereference pointer | `p *config` | -| `x/ ` | `x` | Examine memory | `x/32xb 0x40000000` | -| `info locals` | `i lo` | Show local variables | `i lo` | -| `info args` | `i ar` | Show function arguments | `i ar` | -| `info registers` | `i r` | Show CPU registers | `i r` | -| `backtrace` | `bt` | Show call stack | `bt` | -| `list` | `l` | Show source code | `l` | - -### Breakpoints - -| Command | Description | Example | -|---------|-------------|---------| -| `break ` | Break on function entry | `b esp_wifi_init` | -| `break :` | Break at specific line | `b main.c:42` | -| `break *` | Break at memory address | `b *0x42008a4e` | -| `break if ` | Conditional breakpoint | `b send_data if len > 1000` | -| `tbreak ` | Temporary breakpoint (one-time) | `tb app_main` | -| `info breakpoints` | List all breakpoints | `i b` | -| `delete ` | Delete breakpoint | `d 1` | -| `disable ` | Disable breakpoint | `dis 1` | -| `enable ` | Enable breakpoint | `en 1` | - -### Watchpoints - -| Command | Description | Example | -|---------|-------------|---------| -| `watch ` | Break when variable changes | `watch my_counter` | -| `watch *` | Break when memory changes | `watch *(int*)0x3ff00000` | -| `rwatch ` | Break on read | `rwatch secret_key` | -| `awatch ` | Break on read or write | `awatch buffer[0]` | - -### Memory Examination - -| Format | Description | Example | -|--------|-------------|---------| -| `x/32xb ` | 32 bytes in hex | `x/32xb &config` | -| `x/8xw ` | 8 words (32-bit) in hex | `x/8xw 0x40000000` | -| `x/s ` | String (null-terminated) | `x/s ssid_buffer` | -| `x/i ` | Instruction (disassembly) | `x/10i $pc` | - -### Control Flow - -| Command | Description | -|---------|-------------| -| `monitor reset halt` | Reset chip and stop at bootloader | -| `monitor reset` | Reset chip and run | -| `interrupt` | Pause execution (Ctrl+C) | -| `quit` | Exit GDB | - ---- - -## Debugging Strategies - -### Strategy 1: Breakpoint at Function Entry - -**Use case**: Understand when and why a function is called. - -```gdb -# Break when WiFi CSI configuration is attempted -break esp_wifi_set_csi_config - -# Run until breakpoint -continue - -# When it breaks, examine arguments -info args -print *config - -# Check who called this function -backtrace - -# Continue execution -continue -``` - -### Strategy 2: Conditional Breakpoints - -**Use case**: Break only when specific conditions occur. - -```gdb -# Break only when error occurs -break esp_wifi_set_csi_config if $a0 != 0 - -# Break only for specific SSID -break wifi_connect if strcmp(ssid, "MyNetwork") == 0 - -# Break when buffer is full -break send_packet if queue_size >= 100 -``` - -### Strategy 3: Step Through Algorithm - -**Use case**: Understand complex logic step by step. - -```gdb -# Break at start of function -break process_csi_data - -# Run until breakpoint -continue - -# Step through line by line -next # Execute current line -next # Next line -step # Step into function call if any -finish # Complete current function -``` - -### Strategy 4: Watch for Variable Changes - -**Use case**: Find where a variable gets corrupted. - -```gdb -# Watch a variable -watch connection_state - -# Run - GDB will break when variable changes -continue - -# When it breaks, see the call stack -backtrace - -# See old and new values -print connection_state -``` - -### Strategy 5: Post-Mortem Debugging - -**Use case**: Analyze crash dumps. - -```gdb -# After a crash, examine the panic -backtrace - -# See register state at crash -info registers - -# Examine memory around crash -x/32xw $sp # Stack pointer -x/10i $pc # Instructions at crash - -# Check for stack overflow -info frame -``` - ---- - -## Real-World Examples - -### Example 1: Debug CSI Configuration Failure - -**Problem**: `esp_wifi_set_csi_config()` returns `ESP_FAIL` but we don't know why. - -```gdb -# Start GDB session -(gdb) target remote :3333 -(gdb) file build/CSI.elf -(gdb) monitor reset halt - -# Break on CSI configuration -(gdb) break esp_wifi_set_csi_config -Breakpoint 1 at 0x42012a4e - -# Run until breakpoint -(gdb) continue -Breakpoint 1, esp_wifi_set_csi_config (config=0x3ffb0000) - -# Examine the config structure being passed -(gdb) print *config -$1 = { - enable = 1, - lltf_en = 1, - htltf_en = 1, - stbc_htltf2_en = 1, - ltf_merge_en = 1, - channel_filter_en = 1, ← Suspicious! - manu_scale = 0 -} - -# channel_filter_en = 1 is known to cause ESP_FAIL on some chips -# Let's step through to confirm - -(gdb) step -(gdb) step -... -# Reaches error check for channel_filter_en - -(gdb) print error_code -$2 = 259 ← ESP_FAIL (0x103) - -# Found it! channel_filter_en must be 0 on ESP32-C5 -``` - -**Solution**: Set `channel_filter_en = 0` in the code. - -### Example 2: Find Memory Corruption - -**Problem**: A pointer is getting corrupted, causing crashes. - -```gdb -# Set watchpoint on the pointer -(gdb) watch *(void**)&my_buffer_ptr -Hardware watchpoint 2: *(void**)&my_buffer_ptr - -# Run until it changes -(gdb) continue -Hardware watchpoint 2: *(void**)&my_buffer_ptr -Old value = (void *) 0x3ffb1000 -New value = (void *) 0x00000000 - -# See what code changed it -(gdb) backtrace -#0 process_packet (data=0x3ffb0800) at network.c:142 -#1 0x42008654 in network_task () at network.c:201 -#2 0x4200a123 in vTaskDelay () at FreeRTOS.c:1543 - -# Look at the source -(gdb) list -137 void process_packet(uint8_t *data) { -138 if (data == NULL) { -139 ESP_LOGE(TAG, "Null data!"); -140 my_buffer_ptr = NULL; ← Found it! Setting to NULL here -141 return; -142 } -``` - -**Solution**: Fix the null-pointer handling logic. - -### Example 3: Understand WiFi Connection Failure - -**Problem**: WiFi connects but immediately disconnects. - -```gdb -# Break on disconnect event -(gdb) break event_handler -Breakpoint 1 at 0x42009876 - -# Add condition for disconnect events only -(gdb) condition 1 event_id == WIFI_EVENT_STA_DISCONNECTED - -(gdb) continue -Breakpoint 1, event_handler (event_id=3, event_data=0x3ffb2000) - -# Examine disconnect reason -(gdb) print *(wifi_event_sta_disconnected_t*)event_data -$1 = { - ssid = "ClubHouse", - ssid_len = 9, - bssid = {0xe0, 0x46, 0xee, 0x07, 0xdf, 0x01}, - reason = 2, ← WIFI_REASON_AUTH_EXPIRE - rssi = -75 -} - -# Reason 2 = Authentication expired = weak signal or interference -``` - -**Solution**: Improve antenna placement or reduce distance to AP. - -### Example 4: Profile Function Performance - -**Use case**: Measure time spent in a critical function. - -```gdb -# Break at function entry -(gdb) break process_csi_data -Breakpoint 1 at 0x42010a00 - -# Continue to breakpoint -(gdb) continue -Breakpoint 1, process_csi_data () - -# Get current cycle count (RISC-V has cycle counter) -(gdb) print $cycle -$1 = 12456789 - -# Step out of function -(gdb) finish - -# Check cycles again -(gdb) print $cycle -$2 = 12501234 - -# Calculate time (assuming 240 MHz clock) -# (12501234 - 12456789) / 240,000,000 = 0.185 ms -``` - -### Example 5: Debug Stack Overflow - -**Problem**: Task crashes with stack overflow. - -```gdb -# Break after crash -(gdb) backtrace -#0 0x420089a4 in panic_abort () -#1 0x4200a123 in vTaskStackOverflow () -#2 0x42012456 in my_task () - -# Check stack usage -(gdb) info frame -Stack level 2, frame at 0x3ffb0ff8: - pc = 0x42012456 in my_task - saved pc = 0x4200a123 - Arglist at 0x3ffb0ff8, args: - Locals at 0x3ffb0ff8, Previous frame's sp is 0x3ffb1000 - -# Stack grew to 0x3ffb0ff8 but task stack base is 0x3ffb1000 -# Only 8 bytes left! Stack is too small. - -# Check task stack size in code -(gdb) print task_stack_size -$1 = 2048 ← Too small! -``` - -**Solution**: Increase task stack size to 4096 or 6144 bytes. - ---- - -## Troubleshooting - -### Problem: "No symbol table is loaded" - -**Symptom**: -```gdb -(gdb) break app_main -Function "app_main" not defined. -``` - -**Causes**: -1. Debug symbols not built -2. Wrong ELF file loaded -3. Optimization stripped symbols - -**Solutions**: -```bash -# 1. Rebuild with debug symbols -cd ~/your-project -idf.py menuconfig # Set optimization to Debug (-Og) -idf.py fullclean build - -# 2. Load correct ELF file in GDB -(gdb) file build/your-project.elf - -# 3. Verify symbols exist -riscv32-esp-elf-nm build/your-project.elf | grep app_main -``` - -### Problem: "Cannot access memory at address 0x..." - -**Symptom**: -```gdb -(gdb) print my_variable -Cannot access memory at address 0x3ffb0000 -``` - -**Causes**: -1. Variable optimized out -2. Variable not in scope -3. Pointer is invalid - -**Solutions**: -```gdb -# Check if variable exists -(gdb) info locals # Show all local variables -(gdb) info args # Show function arguments - -# If optimized out, rebuild with -Og -# If out of scope, break where variable is accessible -# If pointer invalid, examine pointer value -(gdb) print &my_variable # Get address -(gdb) x/4xw 0x3ffb0000 # Examine raw memory -``` - -### Problem: Breakpoint Not Hitting - -**Symptom**: Breakpoint set but never triggers. - -**Causes**: -1. Code never executed -2. Breakpoint at wrong location -3. Out of hardware breakpoints - -**Solutions**: -```gdb -# Check breakpoint status -(gdb) info breakpoints -Num Type Disp Enb Address What -1 breakpoint keep y 0x42012000 in my_func at main.c:42 - -# If address is 0x00000000, function doesn't exist -# If "Enb" is "n", breakpoint is disabled -(gdb) enable 1 - -# Try software breakpoint instead -(gdb) delete 1 -(gdb) break my_func -``` - -### Problem: GDB Disconnects Randomly - -**Symptom**: "Remote connection closed" during debugging. - -**Causes**: -1. Watchdog timeout -2. CPU held too long at breakpoint -3. OpenOCD crash - -**Solutions**: -```gdb -# Disable watchdog in menuconfig -# Component config → ESP System Settings → -# → [*] Interrupt watchdog timeout (ms) → 0 (disabled) - -# In GDB, don't hold breakpoints too long -# Continue quickly or disable watchdog: -(gdb) monitor esp wdt off -``` - -### Problem: "Cannot insert breakpoint" - -**Symptom**: -```gdb -(gdb) break my_func -Cannot insert breakpoint 1. -Error accessing memory address 0x42012000 -``` - -**Causes**: -1. Code in flash, not RAM (need flash breakpoints) -2. Out of hardware breakpoints -3. Region not writable - -**Solutions**: -```gdb -# Use hardware breakpoint -(gdb) hbreak my_func - -# Check breakpoint count -(gdb) info breakpoints -# ESP32-C5 has 4 hardware breakpoints max - -# Delete unused breakpoints -(gdb) delete 2 3 4 -``` - ---- - -## Advanced Techniques - -### Technique 1: Scripting GDB - -Create a `.gdbinit` file to automate common tasks: - -```gdb -# ~/.gdbinit or project/.gdbinit - -# Connect automatically -target remote :3333 - -# Load symbols -file build/CSI.elf - -# Define custom commands -define reset-and-break - monitor reset halt - thbreak app_main - continue -end - -# Set common breakpoints -break esp_wifi_set_csi_config -break esp_wifi_connect - -# Custom print for WiFi config -define print-wifi-config - printf "SSID: %s\n", wifi_config.sta.ssid - printf "Password: %s\n", wifi_config.sta.password - printf "Channel: %d\n", wifi_config.sta.channel -end - -# Display instructions -echo \n=== ESP32-C5 Debug Session ===\n -echo Commands:\n -echo reset-and-break : Reset chip and break at app_main\n -echo print-wifi-config: Show WiFi configuration\n -echo \n -``` - -Usage: -```bash -idf.py gdb -# Automatically connects and loads symbols -(gdb) reset-and-break # Your custom command -``` - -### Technique 2: Debugging FreeRTOS Tasks - -List all tasks and their states: - -```gdb -# Show all tasks -(gdb) info threads - Id Target Id Frame -* 1 Remote target vTaskDelay () at FreeRTOS.c:1543 - 2 Remote target prvIdleTask () at FreeRTOS.c:2301 - 3 Remote target wifi_task () at esp_wifi_driver.c:456 - -# Switch to different task -(gdb) thread 3 -[Switching to thread 3 (Remote target)] - -# See that task's stack -(gdb) backtrace -#0 wifi_task () at esp_wifi_driver.c:456 -#1 0x4200a456 in vPortTaskWrapper () -``` - -### Technique 3: Examine WiFi Driver Internals - -```gdb -# Break in WiFi driver -(gdb) break esp_wifi_internal.c:esp_wifi_set_bandwidth - -# When it breaks, examine internal state -(gdb) print g_wifi_state -(gdb) print g_wifi_config -(gdb) print g_sta_netif - -# Step through WiFi driver code -(gdb) step -(gdb) step -``` - -### Technique 4: Live Variable Modification - -Change variables on-the-fly without recompiling: - -```gdb -# Break at function -(gdb) break send_packet -(gdb) continue - -# Change packet size before sending -(gdb) print packet_size -$1 = 1024 -(gdb) set packet_size = 64 -(gdb) print packet_size -$2 = 64 - -# Continue with modified value -(gdb) continue -``` - -### Technique 5: Reverse Debugging (Limited) - -Record execution to step backwards: - -```gdb -# Enable recording (only works for short sequences) -(gdb) target record-full - -# Run forward -(gdb) continue -(gdb) next - -# Step backwards! -(gdb) reverse-step -(gdb) reverse-next - -# Disable recording (uses lots of memory) -(gdb) record stop -``` - ---- - -## Resources - -### Official Documentation - -- **ESP-IDF GDB Guide**: https://docs.espressif.com/projects/esp-idf/en/latest/esp32c5/api-guides/jtag-debugging/ -- **ESP32-C5 Datasheet**: https://www.espressif.com/sites/default/files/documentation/esp32-c5_datasheet_en.pdf -- **OpenOCD Manual**: http://openocd.org/doc/html/index.html -- **GDB Manual**: https://sourceware.org/gdb/current/onlinedocs/gdb/ - -### GDB Cheat Sheets - -- **GDB Quick Reference**: https://darkdust.net/files/GDB%20Cheat%20Sheet.pdf -- **RISC-V GDB Guide**: https://github.com/riscv/riscv-gnu-toolchain - -### ESP32 Community - -- **ESP32 Forum**: https://esp32.com/ -- **r/esp32 Subreddit**: https://reddit.com/r/esp32 -- **Espressif GitHub**: https://github.com/espressif/esp-idf - -### GDB Tutorials - -- **Debugging with GDB**: https://sourceware.org/gdb/onlinedocs/gdb/ -- **RMS's GDB Tutorial**: https://www.gnu.org/software/gdb/documentation/ - ---- - -## Summary - -GDB debugging on the ESP32-C5 provides powerful insights into firmware behavior: - -- ✅ **Built-in USB-JTAG** eliminates external hardware requirements -- ✅ **Hardware and software breakpoints** for flexible debugging -- ✅ **Real-time variable inspection** without printf statements -- ✅ **Watchpoints** to catch memory corruption -- ✅ **Call stack analysis** to understand program flow -- ✅ **ESP-IDF driver debugging** to troubleshoot library issues - -**Key takeaways**: - -1. Always build with **Debug (-Og)** optimization for best debug experience -2. Use **conditional breakpoints** to break only when needed -3. Combine **watchpoints** with breakpoints to find memory corruption -4. **Script common tasks** in `.gdbinit` for faster debugging -5. The **WiFi driver log** is still the ground truth for connection status - -GDB debugging significantly reduces debug time compared to printf-based approaches, especially for complex issues like WiFi driver bugs, FreeRTOS task interactions, and memory corruption. - ---- - -## About - -This guide was created based on real-world ESP32-C5 development experience, specifically debugging WiFi 6 CSI (Channel State Information) capture issues for the iperf WiFi Analyzer project. - -**Hardware**: ESP32-C5 DevKit -**Project**: WiFi Collapse Detection using CSI -**Repository**: https://github.com/iperf2/iperf2 - -For questions or corrections, please open an issue on GitHub. - ---- - -**Last Updated**: December 4, 2025 diff --git a/GDB_GUIDE_README.md b/GDB_GUIDE_README.md deleted file mode 100644 index bfc63c1..0000000 --- a/GDB_GUIDE_README.md +++ /dev/null @@ -1,222 +0,0 @@ -# ESP32-C5 GDB Debugging Guide - README - -Two versions of the comprehensive GDB debugging guide have been created: - -## Files - -1. **ESP32-C5_GDB_Debugging_Guide.md** - Markdown version - - Perfect for GitHub, documentation sites, or conversion to other formats - - Clean, portable, works everywhere - -2. **ESP32-C5_GDB_Debugging_Guide.html** - HTML version - - Professional web-ready format with styling - - Responsive design (mobile-friendly) - - Direct upload to website - -## Content Overview - -### Complete Coverage: - -1. **Introduction** - ESP32-C5 overview and debugging benefits -2. **Why GDB?** - Comparison with printf debugging -3. **Hardware Capabilities** - Built-in USB-JTAG features -4. **Prerequisites** - Required software and hardware -5. **Building with Debug Symbols** - Step-by-step configuration -6. **Starting Debug Session** - Three-step process (flash, OpenOCD, GDB) -7. **Essential Commands** - Comprehensive GDB command reference -8. **Debugging Strategies** - Five proven strategies -9. **Real-World Examples** - Five complete debugging scenarios: - - CSI configuration failure (your actual problem!) - - Memory corruption detection - - WiFi connection troubleshooting - - Performance profiling - - Stack overflow debugging -10. **Troubleshooting** - Common problems and solutions -11. **Advanced Techniques** - Scripting, FreeRTOS, live modification -12. **Resources** - Links to official docs and community - -## Key Features - -- ✅ **Based on your actual ESP32-C5 experience** -- ✅ **Real debugging examples from CSI issues** -- ✅ **Complete command reference** -- ✅ **Troubleshooting guide** -- ✅ **Professional web design** (HTML version) -- ✅ **Ready to publish** - -## Publishing Options - -### Option 1: GitHub Pages -```bash -# Add to your GitHub repo docs/ -git add ESP32-C5_GDB_Debugging_Guide.md -git commit -m "Add GDB debugging guide" -git push -``` - -### Option 2: Direct Website Upload -```bash -# Upload the HTML file to your web server -scp ESP32-C5_GDB_Debugging_Guide.html user@yoursite.com:/var/www/html/ -``` - -### Option 3: Static Site Generator -```bash -# The markdown works with Jekyll, Hugo, MkDocs, etc. -cp ESP32-C5_GDB_Debugging_Guide.md docs/ -# Build your static site -``` - -## Customization - -### HTML Styling - -The HTML version includes CSS in the `