Skip to content
Open
Show file tree
Hide file tree
Changes from 10 commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
125 changes: 125 additions & 0 deletions builder/main.py
Original file line number Diff line number Diff line change
Expand Up @@ -650,6 +650,110 @@ def firmware_metrics(target, source, env):
print(f'Make sure esp-idf-size is installed: uv pip install --python "{PYTHON_EXE}" esp-idf-size')


def coredump_analysis(target, source, env):
"""
Custom target to run esp-coredump with support for command line parameters.
Usage: pio run -t coredump -- [esp-coredump arguments]

Args:
target: SCons target
source: SCons source
env: SCons environment object
"""
if terminal_cp != "utf-8":
print("Coredump analysis can not be shown. Set the terminal codepage to \"utf-8\"")
return

elf_file = str(Path(env.subst("$BUILD_DIR")) / (env.subst("$PROGNAME") + ".elf"))
if not Path(elf_file).is_file():
# elf file can be in project dir
elf_file = str(Path(get_project_dir()) / (env.subst("$PROGNAME") + ".elf"))

if not Path(elf_file).is_file():
print(f"Error: ELF file not found: {elf_file}")
print("Make sure the project is built first with 'pio run'")
return

try:
cmd = [PYTHON_EXE, "-m", "esp_coredump"]

# Command Line Parameter, after --
cli_args = []
if "--" in sys.argv:
dash_index = sys.argv.index("--")
if dash_index + 1 < len(sys.argv):
cli_args = sys.argv[dash_index + 1:]

# Add CLI arguments or use defaults
if cli_args:
cmd.extend(cli_args)
# ELF file should be at the end as positional argument
if not any(arg.endswith('.elf') for arg in cli_args):
cmd.append(elf_file)
else:
# Default arguments if none provided
# Parameters from platformio.ini
extra_args = env.GetProjectOption("custom_esp_coredump_args", "")
if extra_args:
# Parse extra args and add ELF file at the end
cmd.extend(shlex.split(extra_args))
cmd.append(elf_file)
else:
# Use defaults: --chip <mcu> info_corefile <elf_file>
cmd.extend(["--chip", mcu, "info_corefile", elf_file])

# Set up ESP-IDF environment variables and ensure required packages are installed
coredump_env = os.environ.copy()

# Check if ESP-IDF packages are available, install if missing
_framework_pkg_dir = platform.get_package_dir("framework-espidf")
_rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs")

# Install framework-espidf if not available
if not _framework_pkg_dir or not os.path.isdir(_framework_pkg_dir):
print("ESP-IDF framework not found, installing...")
try:
platform.install_package("framework-espidf")
_framework_pkg_dir = platform.get_package_dir("framework-espidf")
except Exception as e:
print(f"Warning: Failed to install framework-espidf: {e}")

# Install tool-esp-rom-elfs if not available
if not _rom_elfs_dir or not os.path.isdir(_rom_elfs_dir):
print("ESP ROM ELFs tool not found, installing...")
try:
platform.install_package("tool-esp-rom-elfs")
_rom_elfs_dir = platform.get_package_dir("tool-esp-rom-elfs")
except Exception as e:
print(f"Warning: Failed to install tool-esp-rom-elfs: {e}")

# Set environment variables if packages are available
if _framework_pkg_dir and os.path.isdir(_framework_pkg_dir):
coredump_env['IDF_PATH'] = str(Path(_framework_pkg_dir).resolve())
if _rom_elfs_dir and os.path.isdir(_rom_elfs_dir):
coredump_env['ESP_ROM_ELF_DIR'] = str(Path(_rom_elfs_dir).resolve())

# Debug-Info if wanted
if env.GetProjectOption("custom_esp_coredump_verbose", False):
print(f"Running command: {' '.join(cmd)}")
if 'IDF_PATH' in coredump_env:
print(f"IDF_PATH: {coredump_env['IDF_PATH']}")
print(f"ESP_ROM_ELF_DIR: {coredump_env.get('ESP_ROM_ELF_DIR', 'Not set')}")

# Execute esp-coredump with ESP-IDF environment
result = subprocess.run(cmd, check=False, capture_output=False, env=coredump_env)

if result.returncode != 0:
print(f"Warning: esp-coredump exited with code {result.returncode}")

except FileNotFoundError:
print("Error: Python executable not found.")
print("Check your Python installation.")
except Exception as e:
print(f"Error: Failed to run coredump analysis: {e}")
print(f'Make sure esp-coredump is installed: uv pip install --python "{PYTHON_EXE}" esp-coredump')


#
# Target: Build executable and linkable firmware or FS image
#
Expand Down Expand Up @@ -931,6 +1035,27 @@ def firmware_metrics(target, source, env):
always_build=True,
)

# Register Custom Target for coredump analysis
env.AddCustomTarget(
name="coredump",
dependencies="$BUILD_DIR/${PROGNAME}.elf",
actions=coredump_analysis,
title="Coredump Analysis",
description="Analyze coredumps using esp-coredump "
"(supports CLI args after --)",
always_build=True,
)

# Additional Target without Build-Dependency when already compiled
env.AddCustomTarget(
name="coredump-only",
dependencies=None,
actions=coredump_analysis,
title="Coredump Analysis (No Build)",
description="Analyze coredumps without building first",
always_build=True,
)

# Override memory inspection behavior
env.SConscript("sizedata.py", exports="env")

Expand Down
3 changes: 2 additions & 1 deletion builder/penv_setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,8 @@
"ecdsa": ">=0.19.1",
"bitstring": ">=4.3.1",
"reedsolo": ">=1.5.3,<1.8",
"esp-idf-size": ">=1.6.1"
"esp-idf-size": ">=1.6.1",
"esp-coredump": ">=1.14.0"
}


Expand Down