diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 228367821..ba729be65 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -103,7 +103,8 @@ def _get_installed_pip_packages(): "wheel": ">=0.35.1", "rich-click": ">=1.8.6", "PyYAML": ">=6.0.2", - "intelhex": ">=2.3.0" + "intelhex": ">=2.3.0", + "esp-idf-size": ">=1.6.1" } installed_packages = _get_installed_pip_packages() diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index c08456bc0..447e379a6 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -56,6 +56,11 @@ env = DefaultEnvironment() env.SConscript("_embed_files.py", exports="env") +# remove maybe existing old map file in project root +map_file = os.path.join(env.subst("$PROJECT_DIR"), env.subst("$PROGNAME") + ".map") +if os.path.exists(map_file): + os.remove(map_file) + def install_standard_python_deps(): def _get_installed_standard_pip_packages(): result = {} @@ -83,7 +88,8 @@ def _get_installed_standard_pip_packages(): deps = { "wheel": ">=0.35.1", "rich-click": ">=1.8.6", - "PyYAML": ">=6.0.2" + "PyYAML": ">=6.0.2", + "esp-idf-size": ">=1.6.1" } installed_packages = _get_installed_standard_pip_packages() @@ -147,13 +153,6 @@ def _get_installed_standard_pip_packages(): assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) -if ( - ["espidf"] == env.get("PIOFRAMEWORK") - and semantic_version.Version.coerce(__version__) - <= semantic_version.Version("6.1.10") - and "__debug" in COMMAND_LINE_TARGETS -): - print("Warning! Debugging an IDF project requires PlatformIO Core >= 6.1.11!") if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") @@ -401,7 +400,6 @@ def get_project_lib_includes(env): return paths - def is_cmake_reconfigure_required(cmake_api_reply_dir): cmake_cache_file = os.path.join(BUILD_DIR, "CMakeCache.txt") cmake_txt_files = [ @@ -1791,18 +1789,30 @@ def get_python_exe(): LIBSOURCE_DIRS=[os.path.join(ARDUINO_FRAMEWORK_DIR, "libraries")] ) +extra_cmake_args = [ + "-DIDF_TARGET=" + idf_variant, + "-DPYTHON_DEPS_CHECKED=1", + "-DEXTRA_COMPONENT_DIRS:PATH=" + ";".join(extra_components), + "-DPYTHON=" + get_python_exe(), + "-DSDKCONFIG=" + SDKCONFIG_PATH, +] + +if "CPPDEFINES" in env: + flatten_cppdefines = env.Flatten(env['CPPDEFINES']) + if "SHOW_METRICS" in flatten_cppdefines: + # This will add the linker flag for the map file + extra_cmake_args.append( + f'-DCMAKE_EXE_LINKER_FLAGS=-Wl,-Map={os.path.join(BUILD_DIR, env.subst("$PROGNAME") + ".map")}' + ) + +# Add any extra args from board config +extra_cmake_args += click.parser.split_arg_string(board.get("build.cmake_extra_args", "")) + print("Reading CMake configuration...") project_codemodel = get_cmake_code_model( PROJECT_DIR, BUILD_DIR, - [ - "-DIDF_TARGET=" + idf_variant, - "-DPYTHON_DEPS_CHECKED=1", - "-DEXTRA_COMPONENT_DIRS:PATH=" + ";".join(extra_components), - "-DPYTHON=" + get_python_exe(), - "-DSDKCONFIG=" + SDKCONFIG_PATH, - ] - + click.parser.split_arg_string(board.get("build.cmake_extra_args", "")), + extra_cmake_args ) # At this point the sdkconfig file should be generated by the underlying build system diff --git a/builder/main.py b/builder/main.py index 5c72b6822..7ac125941 100644 --- a/builder/main.py +++ b/builder/main.py @@ -21,6 +21,9 @@ DefaultEnvironment) from platformio.util import get_serial_ports +from platformio.project.helpers import get_project_dir + +import os env = DefaultEnvironment() platform = env.PioPlatform() @@ -68,12 +71,10 @@ def _normalize_frequency(frequency): frequency = str(frequency).replace("L", "") return str(int(int(frequency) / 1000000)) + "m" - def _get_board_f_flash(env): frequency = env.subst("$BOARD_F_FLASH") return _normalize_frequency(frequency) - def _get_board_f_image(env): board_config = env.BoardConfig() if "build.f_image" in board_config: @@ -88,7 +89,6 @@ def _get_board_f_boot(env): return _get_board_f_flash(env) - def _get_board_flash_mode(env): if _get_board_memory_type(env) in ( "opi_opi", @@ -101,7 +101,6 @@ def _get_board_flash_mode(env): return "dio" return mode - def _get_board_boot_mode(env): memory_type = env.BoardConfig().get("build.arduino.memory_type", "") build_boot = env.BoardConfig().get("build.boot", "$BOARD_FLASH_MODE") @@ -109,7 +108,6 @@ def _get_board_boot_mode(env): build_boot = "opi" return build_boot - def _parse_size(value): if isinstance(value, int): return value @@ -122,7 +120,6 @@ def _parse_size(value): return int(value[:-1]) * base return value - def _parse_partitions(env): partitions_csv = env.subst("$PARTITIONS_TABLE_CSV") if not isfile(partitions_csv): @@ -163,7 +160,6 @@ def _parse_partitions(env): env["INTEGRATION_EXTRA_DATA"].update({"application_offset": str(hex(app_offset))}) return result - def _update_max_upload_size(env): if not env.get("PARTITIONS_TABLE_CSV"): return @@ -192,17 +188,13 @@ def _update_max_upload_size(env): board.update("upload.maximum_size", _parse_size(p["size"])) break - - def _to_unix_slashes(path): return path.replace("\\", "/") - # # Filesystem helpers # - def fetch_fs_size(env): fs = None for p in _parse_partitions(env): @@ -226,17 +218,15 @@ def fetch_fs_size(env): env["FS_START"] += 4096 env["FS_SIZE"] -= 4096 - def __fetch_fs_size(target, source, env): fetch_fs_size(env) return (target, source) - board = env.BoardConfig() mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "spiffs") -if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4"): +if mcu in ("esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4"): toolchain_arch = "riscv32-esp" if "INTEGRATION_EXTRA_DATA" not in env: @@ -257,7 +247,7 @@ def __fetch_fs_size(target, source, env): GDB=join( platform.get_package_dir( "tool-riscv32-esp-elf-gdb" - if mcu in ("esp32c2", "esp32c3", "esp32c6", "esp32h2", "esp32p4") + if mcu in ("esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4") else "tool-xtensa-esp-elf-gdb" ) or "", @@ -367,6 +357,24 @@ def check_lib_archive_exists(): if not env.get("PIOFRAMEWORK"): env.SConscript("frameworks/_bare.py", exports="env") + +def firmware_metrics(target, source, env): + map_file = os.path.join(env.subst("$BUILD_DIR"), env.subst("$PROGNAME") + ".map") + if not os.path.isfile(map_file): + # map file can be in project dir + map_file = os.path.join(get_project_dir(), env.subst("$PROGNAME") + ".map") + + if os.path.isfile(map_file): + try: + import subprocess + # Show output of esp_idf_size, but suppresses the command echo + subprocess.run([ + env.subst("$PYTHONEXE"), "-m", "esp_idf_size", "--ng", map_file + ], check=False) + except Exception: + print("Warning: Failed to run firmware metrics. Is esp-idf-size installed?") + pass + # # Target: Build executable and linkable firmware or FS image # @@ -381,6 +389,9 @@ def check_lib_archive_exists(): target_firm = join("$BUILD_DIR", "${PROGNAME}.bin") else: target_elf = env.BuildProgram() + silent_action = env.Action(firmware_metrics) + silent_action.strfunction = lambda target, source, env: '' # hack to silence scons command output + env.AddPostAction(target_elf, silent_action) if set(["buildfs", "uploadfs", "uploadfsota"]) & set(COMMAND_LINE_TARGETS): target_firm = env.DataToBin( join("$BUILD_DIR", "${ESP32_FS_IMAGE_NAME}"), "$PROJECT_DATA_DIR" @@ -565,6 +576,7 @@ def check_lib_archive_exists(): else: sys.stderr.write("Warning! Unknown upload protocol %s\n" % upload_protocol) + env.AddPlatformTarget("upload", target_firm, upload_actions, "Upload") env.AddPlatformTarget("uploadfs", target_firm, upload_actions, "Upload Filesystem Image") env.AddPlatformTarget( diff --git a/examples/espidf-blink/platformio.ini b/examples/espidf-blink/platformio.ini index 44b4ff9a1..cff4f24aa 100644 --- a/examples/espidf-blink/platformio.ini +++ b/examples/espidf-blink/platformio.ini @@ -17,6 +17,7 @@ build_flags = -D CONFIG_BLINK_GPIO=2 -D CONFIG_BLINK_LED_GPIO=2 -D CONFIG_BLINK_PERIOD=1000 + -D SHOW_METRICS [env:esp32-c2-devkitm-1] platform = espressif32 @@ -27,6 +28,7 @@ build_flags = -D CONFIG_BLINK_GPIO=8 -D CONFIG_BLINK_LED_GPIO=8 -D CONFIG_BLINK_PERIOD=1000 + -D SHOW_METRICS [env:esp32-c6-devkitc-1] platform = espressif32 @@ -37,3 +39,4 @@ build_flags = -D CONFIG_BLINK_GPIO=2 -D CONFIG_BLINK_LED_GPIO=2 -D CONFIG_BLINK_PERIOD=1000 + -D SHOW_METRICS diff --git a/examples/espidf-coap-server/platformio.ini b/examples/espidf-coap-server/platformio.ini index c26b3222a..a64ed1426 100644 --- a/examples/espidf-coap-server/platformio.ini +++ b/examples/espidf-coap-server/platformio.ini @@ -18,3 +18,6 @@ board_build.embed_txtfiles = [env:esp-wrover-kit] board = esp-wrover-kit +build_flags = + -D SHOW_METRICS +