@@ -650,6 +650,132 @@ def firmware_metrics(target, source, env):
650650 print (f'Make sure esp-idf-size is installed: uv pip install --python "{ PYTHON_EXE } " esp-idf-size' )
651651
652652
653+ def coredump_analysis (target , source , env ):
654+ """
655+ Custom target to run esp-coredump with support for command line parameters.
656+ Usage: pio run -t coredump -- [esp-coredump arguments]
657+
658+ Args:
659+ target: SCons target
660+ source: SCons source
661+ env: SCons environment object
662+ """
663+ if terminal_cp != "utf-8" :
664+ print ("Coredump analysis can not be shown. Set the terminal codepage to \" utf-8\" " )
665+ return
666+
667+ elf_file = str (Path (env .subst ("$BUILD_DIR" )) / (env .subst ("$PROGNAME" ) + ".elf" ))
668+ if not Path (elf_file ).is_file ():
669+ # elf file can be in project dir
670+ elf_file = str (Path (get_project_dir ()) / (env .subst ("$PROGNAME" ) + ".elf" ))
671+
672+ if not Path (elf_file ).is_file ():
673+ print (f"Error: ELF file not found: { elf_file } " )
674+ print ("Make sure the project is built first with 'pio run'" )
675+ return
676+
677+ try :
678+ cmd = [PYTHON_EXE , "-m" , "esp_coredump" ]
679+
680+ # Command Line Parameter, after --
681+ cli_args = []
682+ if "--" in sys .argv :
683+ dash_index = sys .argv .index ("--" )
684+ if dash_index + 1 < len (sys .argv ):
685+ cli_args = sys .argv [dash_index + 1 :]
686+
687+ # Add CLI arguments or use defaults
688+ if cli_args :
689+ cmd .extend (cli_args )
690+ # ELF file should be at the end as positional argument
691+ if not any (arg .endswith ('.elf' ) for arg in cli_args ):
692+ cmd .append (elf_file )
693+ else :
694+ # Default arguments if none provided
695+ # Parameters from platformio.ini
696+ extra_args = env .GetProjectOption ("custom_esp_coredump_args" , "" )
697+ if extra_args :
698+ args = shlex .split (extra_args )
699+ cmd .extend (args )
700+ # Ensure ELF is last positional if not present
701+ if not any (a .endswith (".elf" ) for a in args ):
702+ cmd .append (elf_file )
703+ else :
704+ # Prefer an explicit core file if configured or present; else read from flash
705+ core_file = env .GetProjectOption ("custom_esp_coredump_corefile" , "" )
706+ if not core_file :
707+ for name in ("coredump.bin" , "coredump.b64" ):
708+ cand = Path (get_project_dir ()) / name
709+ if cand .is_file ():
710+ core_file = str (cand )
711+ break
712+
713+ # Global options
714+ cmd .extend (["--chip" , mcu ])
715+ upload_port = env .subst ("$UPLOAD_PORT" )
716+ if upload_port :
717+ cmd .extend (["--port" , upload_port ])
718+
719+ # Subcommand and arguments
720+ cmd .append ("info_corefile" )
721+ if core_file :
722+ cmd .extend (["--core" , core_file ])
723+ if core_file .lower ().endswith (".b64" ):
724+ cmd .extend (["--core-format" , "b64" ])
725+ # ELF is the required positional
726+ cmd .append (elf_file )
727+
728+ # Set up ESP-IDF environment variables and ensure required packages are installed
729+ coredump_env = os .environ .copy ()
730+
731+ # Check if ESP-IDF packages are available, install if missing
732+ _framework_pkg_dir = platform .get_package_dir ("framework-espidf" )
733+ _rom_elfs_dir = platform .get_package_dir ("tool-esp-rom-elfs" )
734+
735+ # Install framework-espidf if not available
736+ if not _framework_pkg_dir or not os .path .isdir (_framework_pkg_dir ):
737+ print ("ESP-IDF framework not found, installing..." )
738+ try :
739+ platform .install_package ("framework-espidf" )
740+ _framework_pkg_dir = platform .get_package_dir ("framework-espidf" )
741+ except Exception as e :
742+ print (f"Warning: Failed to install framework-espidf: { e } " )
743+
744+ # Install tool-esp-rom-elfs if not available
745+ if not _rom_elfs_dir or not os .path .isdir (_rom_elfs_dir ):
746+ print ("ESP ROM ELFs tool not found, installing..." )
747+ try :
748+ platform .install_package ("tool-esp-rom-elfs" )
749+ _rom_elfs_dir = platform .get_package_dir ("tool-esp-rom-elfs" )
750+ except Exception as e :
751+ print (f"Warning: Failed to install tool-esp-rom-elfs: { e } " )
752+
753+ # Set environment variables if packages are available
754+ if _framework_pkg_dir and os .path .isdir (_framework_pkg_dir ):
755+ coredump_env ['IDF_PATH' ] = str (Path (_framework_pkg_dir ).resolve ())
756+ if _rom_elfs_dir and os .path .isdir (_rom_elfs_dir ):
757+ coredump_env ['ESP_ROM_ELF_DIR' ] = str (Path (_rom_elfs_dir ).resolve ())
758+
759+ # Debug-Info if wanted
760+ if env .GetProjectOption ("custom_esp_coredump_verbose" , False ):
761+ print (f"Running command: { ' ' .join (cmd )} " )
762+ if 'IDF_PATH' in coredump_env :
763+ print (f"IDF_PATH: { coredump_env ['IDF_PATH' ]} " )
764+ print (f"ESP_ROM_ELF_DIR: { coredump_env .get ('ESP_ROM_ELF_DIR' , 'Not set' )} " )
765+
766+ # Execute esp-coredump with ESP-IDF environment
767+ result = subprocess .run (cmd , check = False , capture_output = False , env = coredump_env )
768+
769+ if result .returncode != 0 :
770+ print (f"Warning: esp-coredump exited with code { result .returncode } " )
771+
772+ except FileNotFoundError :
773+ print ("Error: Python executable not found." )
774+ print ("Check your Python installation." )
775+ except Exception as e :
776+ print (f"Error: Failed to run coredump analysis: { e } " )
777+ print (f'Make sure esp-coredump is installed: uv pip install --python "{ PYTHON_EXE } " esp-coredump' )
778+
653779#
654780# Target: Build executable and linkable firmware or FS image
655781#
@@ -931,6 +1057,27 @@ def firmware_metrics(target, source, env):
9311057 always_build = True ,
9321058)
9331059
1060+ # Register Custom Target for coredump analysis
1061+ env .AddCustomTarget (
1062+ name = "coredump" ,
1063+ dependencies = "$BUILD_DIR/${PROGNAME}.elf" ,
1064+ actions = coredump_analysis ,
1065+ title = "Coredump Analysis" ,
1066+ description = "Analyze coredumps using esp-coredump "
1067+ "(supports CLI args after --)" ,
1068+ always_build = True ,
1069+ )
1070+
1071+ # Additional Target without Build-Dependency when already compiled
1072+ env .AddCustomTarget (
1073+ name = "coredump-only" ,
1074+ dependencies = None ,
1075+ actions = coredump_analysis ,
1076+ title = "Coredump Analysis (No Build)" ,
1077+ description = "Analyze coredumps without building first" ,
1078+ always_build = True ,
1079+ )
1080+
9341081# Override memory inspection behavior
9351082env .SConscript ("sizedata.py" , exports = "env" )
9361083
0 commit comments