diff --git a/boards/adafruit_feather_esp32s3_tft.json b/boards/adafruit_feather_esp32s3_tft.json index 0b1d9433f..d59089e2d 100644 --- a/boards/adafruit_feather_esp32s3_tft.json +++ b/boards/adafruit_feather_esp32s3_tft.json @@ -2,14 +2,16 @@ "build": { "arduino": { "ldscript": "esp32s3_out.ld", - "partitions": "partitions-4MB-tinyuf2.csv" + "partitions": "partitions-4MB-tinyuf2.csv", + "memory_type": "qio_qspi" }, "core": "esp32", "extra_flags": [ "-DARDUINO_ADAFRUIT_FEATHER_ESP32S3_TFT", "-DARDUINO_USB_CDC_ON_BOOT=1", "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/dfrobot_romeo_esp32s3.json b/boards/dfrobot_romeo_esp32s3.json index 55e69db5c..655ddd18b 100644 --- a/boards/dfrobot_romeo_esp32s3.json +++ b/boards/dfrobot_romeo_esp32s3.json @@ -10,7 +10,8 @@ "-DARDUINO_DFROBOT_ROMEO_ESP32S3", "-DARDUINO_USB_MODE=1", "-DARDUINO_RUNNING_CORE=1", - "-DARDUINO_EVENT_RUNNING_CORE=1" + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" ], "f_cpu": "240000000L", "f_flash": "80000000L", diff --git a/boards/freenove_esp32_s3_wroom.json b/boards/freenove_esp32_s3_wroom.json new file mode 100644 index 000000000..5089f14fc --- /dev/null +++ b/boards/freenove_esp32_s3_wroom.json @@ -0,0 +1,55 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_MODE=0", + "-DARDUINO_USB_CDC_ON_BOOT=0" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "psram_type": "opi", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Freenove ESP32-S3 WROOM N8R8 (8MB Flash / 8MB PSRAM)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://github.com/Freenove/Freenove_ESP32_S3_WROOM_Board", + "vendor": "Freenove" +} diff --git a/boards/freenove_esp32_wrover.json b/boards/freenove_esp32_wrover.json new file mode 100644 index 000000000..a154f82de --- /dev/null +++ b/boards/freenove_esp32_wrover.json @@ -0,0 +1,42 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32_DEV", + "-DBOARD_HAS_PSRAM", + "-mfix-esp32-psram-cache-issue", + "-mfix-esp32-psram-cache-strategy=memw" + ], + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wrover-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Freenove ESP32-Wrover", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://store.freenove.com/products/fnk0060", + "vendor": "Freenove" +} diff --git a/boards/heltec_wireless_stick_lite.json b/boards/heltec_wireless_stick_lite.json index 6ffac9acf..7382ddec0 100644 --- a/boards/heltec_wireless_stick_lite.json +++ b/boards/heltec_wireless_stick_lite.json @@ -6,7 +6,7 @@ "core": "esp32", "extra_flags": "-DARDUINO_HELTEC_WIRELESS_STICK_LITE", "f_cpu": "240000000L", - "f_flash": "40000000L", + "f_flash": "80000000L", "flash_mode": "dio", "mcu": "esp32", "variant": "heltec_wireless_stick_lite" diff --git a/boards/lilygo-t3-s3.json b/boards/lilygo-t3-s3.json new file mode 100644 index 000000000..5c789e41c --- /dev/null +++ b/boards/lilygo-t3-s3.json @@ -0,0 +1,45 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_LILYGO_T3_S3_V1_X", + "-DBOARD_HAS_PSRAM", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_MODE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "LilyGo T3-S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://lilygo.cc/products/t3s3-v1-0", + "vendor": "LilyGo" +} diff --git a/boards/rymcu-esp32-c3-devkitm-1.json b/boards/rymcu-esp32-c3-devkitm-1.json new file mode 100644 index 000000000..a844a2c25 --- /dev/null +++ b/boards/rymcu-esp32-c3-devkitm-1.json @@ -0,0 +1,35 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32c3_out.ld" + }, + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "extra_flags": "-DARDUINO_ESP32C3_DEV", + "mcu": "esp32c3", + "variant": "esp32c3" + }, + "connectivity": [ + "wifi", + "bluetooth" + ], + "debug": { + "openocd_target": "esp32c3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "RYMCU ESP32-C3-DevKitM-1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://rymcu.com/products", + "vendor": "RYMCU" +} diff --git a/boards/rymcu-esp32-devkitc.json b/boards/rymcu-esp32-devkitc.json new file mode 100644 index 000000000..1519022f6 --- /dev/null +++ b/boards/rymcu-esp32-devkitc.json @@ -0,0 +1,37 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_ESP32_DEV", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "esp32" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "debug": { + "openocd_board": "esp-wroom-32.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "RYMCU ESP32-DevKitC", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://rymcu.com/products", + "vendor": "RYMCU" +} diff --git a/boards/rymcu-esp32-s3-devkitc-1.json b/boards/rymcu-esp32-s3-devkitc-1.json new file mode 100644 index 000000000..ecee4a454 --- /dev/null +++ b/boards/rymcu-esp32-s3-devkitc-1.json @@ -0,0 +1,52 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "default_8MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ESP32S3_DEV", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "esp32s3" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "default_tool": "esp-builtin", + "onboard_tools": [ + "esp-builtin" + ], + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "RYMCU ESP32-S3-DevKitC-1-N8R2 (8 MB QD, 2 MB PSRAM)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://rymcu.com/products", + "vendor": "RYMCU" +} diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 2ece86765..d7c865195 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -139,13 +139,15 @@ def is_cmake_reconfigure_required(cmake_api_reply_dir): ] cmake_preconf_dir = os.path.join(BUILD_DIR, "config") deafult_sdk_config = os.path.join(PROJECT_DIR, "sdkconfig.defaults") + idf_deps_lock = os.path.join(PROJECT_DIR, "dependencies.lock") + ninja_buildfile = os.path.join(BUILD_DIR, "build.ninja") for d in (cmake_api_reply_dir, cmake_preconf_dir): if not os.path.isdir(d) or not os.listdir(d): return True if not os.path.isfile(cmake_cache_file): return True - if not os.path.isfile(os.path.join(BUILD_DIR, "build.ninja")): + if not os.path.isfile(ninja_buildfile): return True if not os.path.isfile(SDKCONFIG_PATH) or os.path.getmtime( SDKCONFIG_PATH @@ -155,6 +157,10 @@ def is_cmake_reconfigure_required(cmake_api_reply_dir): deafult_sdk_config ) > os.path.getmtime(cmake_cache_file): return True + if os.path.isfile(idf_deps_lock) and os.path.getmtime( + idf_deps_lock + ) > os.path.getmtime(ninja_buildfile): + return True if any( os.path.getmtime(f) > os.path.getmtime(cmake_cache_file) for f in cmake_txt_files + [cmake_preconf_dir, FRAMEWORK_DIR] @@ -271,6 +277,13 @@ def populate_idf_env_vars(idf_env): if "IDF_TOOLS_PATH" in idf_env: del idf_env["IDF_TOOLS_PATH"] + # Unlike IDF, PlatformIO allows multiple targets per environment. This + # difference may cause CMake configuration errors if the automatically + # handled folder "managed_components" was modified on the disk by + # a previous target + if board.get("build.esp-idf.overwrite_managed_components", "yes") == "yes": + idf_env["IDF_COMPONENT_OVERWRITE_MANAGED_COMPONENTS"] = "1" + def get_target_config(project_configs, target_index, cmake_api_reply_dir): target_json = project_configs.get("targets")[target_index].get("jsonFile", "") @@ -1330,11 +1343,37 @@ def get_idf_venv_dir(): def ensure_python_venv_available(): + def _get_idf_venv_python_version(): + try: + version = subprocess.check_output( + [ + get_python_exe(), + "-c", + "import sys;print('{0}.{1}.{2}-{3}.{4}'.format(*list(sys.version_info)))" + ], text=True + ) + return version.strip() + except subprocess.CalledProcessError as e: + print("Failed to extract Python version from IDF virtual env!") + return None + def _is_venv_outdated(venv_data_file): try: with open(venv_data_file, "r", encoding="utf8") as fp: venv_data = json.load(fp) if venv_data.get("version", "") != IDF_ENV_VERSION: + print( + "Warning! IDF virtual environment version changed!" + ) + return True + if ( + venv_data.get("python_version", "") + != _get_idf_venv_python_version() + ): + print( + "Warning! Python version in the IDF virtual environment" + " differs from the current Python!" + ) return True return False except: @@ -1374,8 +1413,13 @@ def _create_venv(venv_dir): venv_data_file = os.path.join(venv_dir, "pio-idf-venv.json") if not os.path.isfile(venv_data_file) or _is_venv_outdated(venv_data_file): _create_venv(venv_dir) + + install_python_deps() with open(venv_data_file, "w", encoding="utf8") as fp: - venv_info = {"version": IDF_ENV_VERSION} + venv_info = { + "version": IDF_ENV_VERSION, + "python_version": _get_idf_venv_python_version() + } json.dump(venv_info, fp, indent=2) @@ -1394,11 +1438,10 @@ def get_python_exe(): # -# ESP-IDF requires Python packages with specific versions in a virtual environment +# Ensure Python environment contains everything required for IDF # ensure_python_venv_available() -install_python_deps() # ESP-IDF package doesn't contain .git folder, instead package version is specified # in a special file "version.h" in the root folder of the package @@ -1603,7 +1646,15 @@ def get_python_exe(): # Extra flags which need to be explicitly specified in LINKFLAGS section because SCons # cannot merge them correctly extra_flags = filter_args( - link_args["LINKFLAGS"], ["-T", "-u", "-Wl,--start-group", "-Wl,--end-group"] + link_args["LINKFLAGS"], + [ + "-T", + "-u", + "-Wl,--start-group", + "-Wl,--end-group", + "-Wl,--whole-archive", + "-Wl,--no-whole-archive", + ], ) link_args["LINKFLAGS"] = sorted(list(set(link_args["LINKFLAGS"]) - set(extra_flags))) @@ -1791,8 +1842,10 @@ def _skip_prj_source_files(node): # ulp_dir = os.path.join(PROJECT_DIR, "ulp") -if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c3", "esp32c6"): - env.SConscript("ulp.py", exports="env sdk_config project_config idf_variant") +if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu != "esp32c3": + env.SConscript( + "ulp.py", exports="env sdk_config project_config idf_variant" + ) # # Process OTA partition and image diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 89aa42011..982742295 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -28,7 +28,10 @@ FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") BUILD_DIR = ulp_env.subst("$BUILD_DIR") ULP_BUILD_DIR = os.path.join( - BUILD_DIR, "esp-idf", project_config["name"].replace("__idf_", ""), "ulp_main" + BUILD_DIR, + "esp-idf", + project_config["name"].replace("__idf_", ""), + "ulp_main", ) @@ -36,9 +39,15 @@ def prepare_ulp_env_vars(env): ulp_env.PrependENVPath("IDF_PATH", FRAMEWORK_DIR) toolchain_path = platform.get_package_dir( - "toolchain-xtensa-esp-elf" - if "arduino" not in env.subst("$PIOFRAMEWORK") - else "toolchain-xtensa-%s" % idf_variant + "toolchain-riscv32-esp" + if idf_variant in ("esp32c3", "esp32c6") + else ( + ( + "toolchain-xtensa-esp-elf" + if "arduino" not in env.subst("$PIOFRAMEWORK") + else "toolchain-xtensa-%s" % idf_variant + ) + ) ) additional_packages = [ @@ -72,9 +81,9 @@ def get_component_includes(target_config): if source["path"].endswith("ulp_main.bin.S"): return [ inc["path"] - for inc in target_config["compileGroups"][source["compileGroupIndex"]][ - "includes" - ] + for inc in target_config["compileGroups"][ + source["compileGroupIndex"] + ]["includes"] ] return [os.path.join(BUILD_DIR, "config")] @@ -85,7 +94,9 @@ def _generate_ulp_configuration_action(env, target, source): riscv_ulp_enabled = sdk_config.get("ULP_COPROC_TYPE_RISCV", False) cmd = ( - os.path.join(platform.get_package_dir("tool-cmake"), "bin", "cmake"), + os.path.join( + platform.get_package_dir("tool-cmake"), "bin", "cmake" + ), "-DCMAKE_GENERATOR=Ninja", "-DCMAKE_TOOLCHAIN_FILE=" + os.path.join( @@ -93,21 +104,52 @@ def _generate_ulp_configuration_action(env, target, source): "components", "ulp", "cmake", - "toolchain-%sulp%s.cmake" - % ( - "" if riscv_ulp_enabled else idf_variant + "-", - "-riscv" if riscv_ulp_enabled else "", + ( + "toolchain-lp-core-riscv.cmake" + if sdk_config.get("ULP_COPROC_TYPE_LP_CORE", False) + else "toolchain-%sulp%s.cmake" + % ( + "" if riscv_ulp_enabled else idf_variant + "-", + "-riscv" if riscv_ulp_enabled else "", + ) ), ), - "-DULP_S_SOURCES=%s" % ";".join([fs.to_unix_path(s.get_abspath()) for s in source]), + "-DULP_S_SOURCES=%s" + % ";".join([fs.to_unix_path(s.get_abspath()) for s in source]), "-DULP_APP_NAME=ulp_main", - "-DCOMPONENT_DIR=" + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), - "-DCOMPONENT_INCLUDES=%s" % ";".join(get_component_includes(target_config)), + "-DCOMPONENT_DIR=" + + os.path.join(ulp_env.subst("$PROJECT_DIR"), "ulp"), + "-DCOMPONENT_INCLUDES=%s" + % ";".join(get_component_includes(target_config)), "-DIDF_TARGET=%s" % idf_variant, "-DIDF_PATH=" + fs.to_unix_path(FRAMEWORK_DIR), - "-DSDKCONFIG_HEADER=" + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), + "-DSDKCONFIG_HEADER=" + + os.path.join(BUILD_DIR, "config", "sdkconfig.h"), "-DPYTHON=" + env.subst("$PYTHONEXE"), - "-DSDKCONFIG_CMAKE=" + os.path.join(BUILD_DIR, "config", "sdkconfig.cmake"), + "-DSDKCONFIG_CMAKE=" + + os.path.join(BUILD_DIR, "config", "sdkconfig.cmake"), + "-DULP_COCPU_IS_RISCV=" + + ( + "ON" + if idf_variant in ("esp32s2", "esp32s3") + and sdk_config.get("ULP_COPROC_TYPE_RISCV", False) + else "" + ), + "-DULP_COCPU_IS_LP_CORE=" + + ( + "ON" + if sdk_config.get("ULP_COPROC_TYPE_LP_CORE", False) + else "" + ), + "-DESP_ROM_HAS_LP_ROM=" + + ( + "ON" + if sdk_config.get("ESP_ROM_HAS_LP_ROM", False) + else "" + ), + "-DCMAKE_MODULE_PATH=" + + fs.to_unix_path( + os.path.join(FRAMEWORK_DIR, "components", "ulp", "cmake")), "-GNinja", "-B", ULP_BUILD_DIR, @@ -152,7 +194,9 @@ def compile_ulp_binary(): os.path.join(ULP_BUILD_DIR, "ulp_main.bin"), ], None, - ulp_binary_env.VerboseAction(" ".join(cmd), "Generating ULP project files $TARGETS"), + ulp_binary_env.VerboseAction( + " ".join(cmd), "Generating ULP project files $TARGETS" + ), ) @@ -164,14 +208,20 @@ def generate_ulp_assembly(): "-DFILE_TYPE=BINARY", "-P", os.path.join( - FRAMEWORK_DIR, "tools", "cmake", "scripts", "data_file_embed_asm.cmake" + FRAMEWORK_DIR, + "tools", + "cmake", + "scripts", + "data_file_embed_asm.cmake", ), ) return ulp_env.Command( os.path.join(BUILD_DIR, "ulp_main.bin.S"), os.path.join(ULP_BUILD_DIR, "ulp_main.bin"), - ulp_env.VerboseAction(" ".join(cmd), "Generating ULP assembly file $TARGET"), + ulp_env.VerboseAction( + " ".join(cmd), "Generating ULP assembly file $TARGET" + ), ) diff --git a/platform.json b/platform.json index ee0745b68..be03196ff 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/platformio/platform-espressif32.git" }, - "version": "6.9.0", + "version": "6.10.0", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -52,13 +52,13 @@ "optional": true, "owner": "espressif", "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["13.2.0+20240530"] + "optionalVersions": ["14.2.0+20241119"] }, "toolchain-xtensa-esp-elf": { "type": "toolchain", "optional": true, "owner": "platformio", - "version": "13.2.0+20240530" + "version": "14.2.0+20241119" }, "toolchain-esp32ulp": { "type": "toolchain", @@ -88,7 +88,7 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50301.0", + "version": "~3.50400.0", "optionalVersions": ["~3.40407.0"] }, "tool-esptoolpy": { diff --git a/platform.py b/platform.py index 895948e06..e7bdf9848 100644 --- a/platform.py +++ b/platform.py @@ -137,7 +137,7 @@ def configure_default_packages(self, variables, targets): self.packages["toolchain-riscv32-esp"]["owner"] = "platformio" self.packages["toolchain-riscv32-esp"][ "version" - ] = "13.2.0+20240530" + ] = "14.2.0+20241119" if "arduino" in frameworks: # Disable standalone GDB packages for Arduino and Arduino/IDF projects