From 879780c5a96fe00c2d4df0be5e5fcb0c0c48c83f Mon Sep 17 00:00:00 2001 From: Jason2866 Date: Fri, 19 Dec 2025 16:03:25 +0100 Subject: [PATCH] Arduino core 3.3.5 --- .github/workflows/examples.yml | 2 +- README.md | 21 ++-- boards/arduino_nesso_n1.json | 31 +++++ boards/esp32-c61-devkitc1-n8r2.json | 44 +++++++ boards/esp32-p4-evboard.json | 3 +- boards/esp32-p4.json | 3 +- boards/esp32-p4_r3.json | 36 ++++++ boards/esp32-solo1.json | 6 +- boards/m5stack-tab5-p4.json | 3 +- boards/yb_esp32s3_eth.json | 2 +- builder/build_lib/idf_component.yml | 4 + builder/frameworks/arduino.py | 88 ++++++++++++-- builder/frameworks/component_manager.py | 110 +++++++++++++++++- builder/frameworks/espidf.py | 90 +++++++++----- builder/penv_setup.py | 2 +- examples/arduino-blink/platformio.ini | 31 +++++ .../include/README | 39 +++++++ .../espidf-arduino-matter-light/lib/README | 46 ++++++++ .../sdkconfig.defaults.c6_thread | 79 +++++++++++++ examples/tasmota_platformio_override.ini | 1 + platform.json | 26 +++-- platform.py | 15 +-- 22 files changed, 610 insertions(+), 72 deletions(-) create mode 100644 boards/arduino_nesso_n1.json create mode 100644 boards/esp32-c61-devkitc1-n8r2.json create mode 100644 boards/esp32-p4_r3.json create mode 100644 examples/espidf-arduino-matter-light/include/README create mode 100644 examples/espidf-arduino-matter-light/lib/README create mode 100644 examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread diff --git a/.github/workflows/examples.yml b/.github/workflows/examples.yml index a8cde98..b8eb8bd 100644 --- a/.github/workflows/examples.yml +++ b/.github/workflows/examples.yml @@ -19,7 +19,7 @@ jobs: - "examples/arduino-usb-keyboard" - "examples/arduino-wifiscan" - "examples/arduino-zigbee-light" - - "examples/arduino-zigbee-switch" +# - "examples/arduino-zigbee-switch" - "examples/arduino-NimBLE-SampleScan" - "examples/arduino-matter-light" - "examples/tasmota" diff --git a/README.md b/README.md index fc9a997..7bf100f 100644 --- a/README.md +++ b/README.md @@ -30,7 +30,7 @@ Prerequisites: The Wiki is AI generated and insane detailed and accurate. ### Stable Arduino -currently espressif Arduino 3.3.4 and IDF 5.5.1.251106 +currently espressif Arduino 3.3.5 and IDF 5.5.1.251215 ```ini [env:stable] @@ -49,21 +49,28 @@ board = ... ... ``` -### ESP32-solo1 and ESP32-C2 Arduino support (with pioarduino only feature: *Hybrid compile*) +### ESP32-C2, ESP32-C61 and ESP32-solo1 Arduino support (via pioarduino only feature: *Hybrid compile*) Example configuration: ```ini +[env:esp32-c2-devkitm-1] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip +framework = arduino +board = esp32-c2-devkitm-1 +monitor_speed = 115200 + +[env:esp32-c61-devkitc1-n8r2] +platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip +framework = arduino +board = esp32-c61-devkitc1-n8r2 +monitor_speed = 115200 + [env:esp32solo1] platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip framework = arduino board = esp32-solo1 monitor_speed = 115200 -[env:esp32-c2-devkitm-1] -platform = https://github.com/pioarduino/platform-espressif32/releases/download/stable/platform-espressif32.zip -framework = arduino -board = esp32-c2-devkitm-1 -monitor_speed = 115200 ``` Looking for sponsor button? There is none. If you want to donate, please spend a litte to a charity organization. diff --git a/boards/arduino_nesso_n1.json b/boards/arduino_nesso_n1.json new file mode 100644 index 0000000..9297ee6 --- /dev/null +++ b/boards/arduino_nesso_n1.json @@ -0,0 +1,31 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "arduino_nesso_n1" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Arduino Nesso-N1", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://store.arduino.cc/products/nesso-n1", + "vendor": "Arduino" +} diff --git a/boards/esp32-c61-devkitc1-n8r2.json b/boards/esp32-c61-devkitc1-n8r2.json new file mode 100644 index 0000000..6bb3bb4 --- /dev/null +++ b/boards/esp32-c61-devkitc1-n8r2.json @@ -0,0 +1,44 @@ +{ + "build": { + "arduino": { + "partitions": "default_8MB.csv", + "memory_type": "qio_qspi" + }, + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "psram_type": "qio", + "mcu": "esp32c61", + "variant": "esp32c61" + }, + "connectivity": [ + "bluetooth", + "wifi" + ], + "debug": { + "openocd_target": "esp32c61.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-C61-DevKitC-1 N8R2 (8 MB Flash Quad, 2 MB PSRAM Quad)", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "espidf": { + "custom_sdkconfig": [ + "CONFIG_IDF_TARGET=\"esp32c61\"" + ] + }, + "url": "https://docs.espressif.com/projects/esp-dev-kits/en/latest/esp32c61/esp32-c61-devkitc-1/user_guide.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-p4-evboard.json b/boards/esp32-p4-evboard.json index f879cf6..71551cd 100644 --- a/boards/esp32-p4-evboard.json +++ b/boards/esp32-p4-evboard.json @@ -9,6 +9,7 @@ "f_psram": "200000000L", "flash_mode": "qio", "mcu": "esp32p4", + "chip_variant": "esp32p4_es", "variant": "esp32p4" }, "arduino": { @@ -25,7 +26,7 @@ "arduino", "espidf" ], - "name": "Espressif ESP32-P4 Function EV Board", + "name": "Espressif ESP32-P4 Function EV Board (ES pre rev.300)", "upload": { "flash_size": "16MB", "maximum_ram_size": 512000, diff --git a/boards/esp32-p4.json b/boards/esp32-p4.json index ec721a8..476079f 100644 --- a/boards/esp32-p4.json +++ b/boards/esp32-p4.json @@ -9,6 +9,7 @@ "f_psram": "200000000L", "flash_mode": "qio", "mcu": "esp32p4", + "chip_variant": "esp32p4_es", "variant": "esp32p4" }, "connectivity": [ @@ -22,7 +23,7 @@ "arduino", "espidf" ], - "name": "Espressif ESP32-P4 generic", + "name": "Espressif ESP32-P4 ES (pre rev.300) generic", "upload": { "flash_size": "4MB", "maximum_ram_size": 327680, diff --git a/boards/esp32-p4_r3.json b/boards/esp32-p4_r3.json new file mode 100644 index 0000000..8ed15ec --- /dev/null +++ b/boards/esp32-p4_r3.json @@ -0,0 +1,36 @@ +{ + "build": { + "core": "esp32", + "extra_flags": [ + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "400000000L", + "f_flash": "80000000L", + "f_psram": "200000000L", + "flash_mode": "qio", + "mcu": "esp32p4", + "chip_variant": "esp32p4", + "variant": "esp32p4" + }, + "connectivity": [ + "bluetooth", + "openthread" + ], + "debug": { + "openocd_target": "esp32p4.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Espressif ESP32-P4 rev.300 generic", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com", + "vendor": "Espressif" +} diff --git a/boards/esp32-solo1.json b/boards/esp32-solo1.json index 906772b..b15cb00 100644 --- a/boards/esp32-solo1.json +++ b/boards/esp32-solo1.json @@ -31,9 +31,11 @@ }, "espidf": { "custom_sdkconfig": [ - "CONFIG_FREERTOS_UNICORE=y" + "CONFIG_FREERTOS_UNICORE=y", + "# CONFIG_BOOTLOADER_SPI_CUSTOM_WP_PIN is not set", + "CONFIG_BOOTLOADER_SPI_WP_PIN=7" ] }, - "url": "https://en.wikipedia.org/wiki/ESP32", + "url": "https://www.espressif.com/sites/default/files/documentation/esp32-solo-1_datasheet_en.pdf", "vendor": "Espressif" } diff --git a/boards/m5stack-tab5-p4.json b/boards/m5stack-tab5-p4.json index 7c561ca..ec4fbf8 100644 --- a/boards/m5stack-tab5-p4.json +++ b/boards/m5stack-tab5-p4.json @@ -11,6 +11,7 @@ "f_psram": "200000000L", "flash_mode": "qio", "mcu": "esp32p4", + "chip_variant": "esp32p4_es", "variant": "m5stack_tab5" }, "arduino": { @@ -27,7 +28,7 @@ "arduino", "espidf" ], - "name": "M5STACK Tab5 esp32-p4 Board", + "name": "M5STACK Tab5 esp32-p4 Board (ES pre rev.300)", "upload": { "flash_size": "16MB", "maximum_ram_size": 512000, diff --git a/boards/yb_esp32s3_eth.json b/boards/yb_esp32s3_eth.json index 1d99b67..527a74c 100644 --- a/boards/yb_esp32s3_eth.json +++ b/boards/yb_esp32s3_eth.json @@ -46,6 +46,6 @@ "require_upload_port": true, "speed": 460800 }, - "url": "https://github.com/yellobyte/ESP32-DevBoards-Getting-Started/tree/main/boards/YB-ESP32-S3-ETH", + "url": "https://github.com/yellobyte/YB-ESP32-S3-ETH", "vendor": "YelloByte" } diff --git a/builder/build_lib/idf_component.yml b/builder/build_lib/idf_component.yml index 02959d9..35a4936 100644 --- a/builder/build_lib/idf_component.yml +++ b/builder/build_lib/idf_component.yml @@ -1,6 +1,10 @@ dependencies: # Required IDF version idf: ">=5.1" + espressif/cmake_utilities: + version: "0.*" + rules: + - if: "target == esp32c2" espressif/fb_gfx: version: "master" path: components/fb_gfx diff --git a/builder/frameworks/arduino.py b/builder/frameworks/arduino.py index 3ff6de9..82cd337 100644 --- a/builder/frameworks/arduino.py +++ b/builder/frameworks/arduino.py @@ -73,8 +73,9 @@ def get_platform_default_threshold(mcu): "esp32s2": 32000, # ESP32-S2 "esp32s3": 32766, # ESP32-S3 "esp32c3": 32000, # ESP32-C3 - "esp32c2": 32000, # ESP32-C2 + "esp32c2": 31600, # ESP32-C2 "esp32c6": 31600, # ESP32-C6 + "esp32c61": 31600, # ESP32-C61 "esp32h2": 32000, # ESP32-H2 "esp32p4": 32000, # ESP32-P4 } @@ -110,6 +111,7 @@ def validate_threshold(threshold, mcu): "esp32s3": {"min": 30000, "max": 32767}, "esp32p4": {"min": 30000, "max": 32767}, "esp32c6": {"min": 30000, "max": 32767}, + "esp32c61": {"min": 30000, "max": 32767}, "esp32h2": {"min": 30000, "max": 32767}, } @@ -236,7 +238,7 @@ def get_threshold_info(env, config, current_env_section): Returns: dict: Information about threshold configuration """ - mcu = env.BoardConfig().get("build.mcu", "esp32") + mcu = env.BoardConfig().get("build.mcu", "esp32").lower() setting_name = "custom_include_path_length_threshold" info = { @@ -285,9 +287,10 @@ def get_threshold_info(env, config, current_env_section): # Cache class for frequently used paths class PathCache: - def __init__(self, platform, mcu): + def __init__(self, platform, mcu, chip_variant): self.platform = platform self.mcu = mcu + self.chip_variant = chip_variant self._framework_dir = None self._framework_lib_dir = None self._sdk_dir = None @@ -310,7 +313,7 @@ class PathCache: def sdk_dir(self): if self._sdk_dir is None: self._sdk_dir = fs.to_unix_path( - str(Path(self.framework_lib_dir) / self.mcu / "include") + str(Path(self.framework_lib_dir) / self.chip_variant / "include") ) return self._sdk_dir @@ -520,9 +523,11 @@ board = env.BoardConfig() # Cached values mcu = board.get("build.mcu", "esp32") +chip_variant = env.BoardConfig().get("build.chip_variant", "").lower() +chip_variant = chip_variant if chip_variant else mcu pioenv = env["PIOENV"] project_dir = env.subst("$PROJECT_DIR") -path_cache = PathCache(platform, mcu) +path_cache = PathCache(platform, mcu, chip_variant) current_env_section = f"env:{pioenv}" # Board configuration @@ -532,9 +537,7 @@ flag_custom_sdkconfig = False flag_custom_component_remove = False flag_custom_component_add = False flag_lib_ignore = False - -if mcu == "esp32c2": - flag_custom_sdkconfig = True +flag_lto = False # pio lib_ignore check if config.has_option(current_env_section, "lib_ignore"): @@ -598,6 +601,10 @@ if flag_custom_sdkconfig: if has_unicore_flags(): build_unflags += " -ustart_app_other_cores" + # Check for enabling LTO for Arduino HybridCompile part by unflagging -fno-lto + if '-fno-lto' in build_unflags: + flag_lto = True + new_build_unflags = build_unflags.split() env.Replace(BUILD_UNFLAGS=new_build_unflags) @@ -916,13 +923,76 @@ if ("arduino" in pioframework and "espidf" not in pioframework and from component_manager import ComponentManager component_manager = ComponentManager(env) component_manager.handle_component_settings() + + # Handle LTO flags if flag_lto is set + if flag_lto: + # First remove existing -fno-lto flags, then add LTO flags + component_manager.remove_no_lto_flags() + component_manager.add_lto_flags() + silent_action = env.Action(component_manager.restore_pioarduino_build_py) # silence scons command output silent_action.strfunction = lambda target, source, env: '' env.AddPostAction("checkprogsize", silent_action) if IS_WINDOWS: - env.AddBuildMiddleware(smart_include_length_shorten) + # Integrate smart_include_length_shorten with existing middlewares + existing_middlewares = list(env.get("__PIO_BUILD_MIDDLEWARES", [])) + + if existing_middlewares: + # Wrap user middlewares to work together with smart_include_length_shorten + def integrated_middleware(env, node): + # Create a custom env.Object wrapper that intercepts calls + original_object = env.Object + result_holder = {"result": None, "called": False} + + def custom_object_wrapper(_node, **kwargs): + # User middleware called env.Object - capture it + result_holder["called"] = True + result_holder["kwargs"] = kwargs + # Don't actually compile yet, just return a marker + return None + + # Temporarily replace env.Object + env.Object = custom_object_wrapper + + # Call user middleware - it will call our wrapper + for middleware_func, _ in existing_middlewares: + middleware_func(env, node) + + # Restore original env.Object + env.Object = original_object + + # Now compile with smart_include_length_shorten + if result_holder["called"] and result_holder.get("kwargs"): + # User middleware wants custom flags - merge them + user_kwargs = result_holder["kwargs"] + + # Temporarily apply user's custom flags to env + old_values = {} + for key, value in user_kwargs.items(): + if key in env: + old_values[key] = env[key] + env[key] = value + + # Compile with smart_include_length_shorten + result = smart_include_length_shorten(env, node) + + # Restore original env values + for key, value in old_values.items(): + env[key] = value + + return result + else: + # No custom flags, just use smart_include_length_shorten + return smart_include_length_shorten(env, node) + + # Replace all middlewares with the integrated one + env["__PIO_BUILD_MIDDLEWARES"] = [] + env.AddBuildMiddleware(integrated_middleware) + else: + # No user middlewares, just add smart_include_length_shorten + env.AddBuildMiddleware(smart_include_length_shorten) build_script_path = str(Path(FRAMEWORK_DIR) / "tools" / "pioarduino-build.py") SConscript(build_script_path) diff --git a/builder/frameworks/component_manager.py b/builder/frameworks/component_manager.py index 5a34e8b..d5eb9d1 100644 --- a/builder/frameworks/component_manager.py +++ b/builder/frameworks/component_manager.py @@ -45,6 +45,8 @@ class ComponentManagerConfig: self.board = env.BoardConfig() # Extract MCU type from board configuration, defaulting to esp32 self.mcu = self.board.get("build.mcu", "esp32").lower() + chip_variant = self.board.get("build.chip_variant", "").lower() + self.chip_variant = chip_variant if chip_variant else self.mcu # Get project source directory path self.project_src_dir = env.subst("$PROJECT_SRC_DIR") @@ -74,7 +76,7 @@ class ComponentManagerConfig: """ if self._arduino_libs_mcu is None: ald = self.platform.get_package_dir("framework-arduinoespressif32-libs") - self._arduino_libs_mcu = str(Path(ald) / self.mcu) if ald else "" + self._arduino_libs_mcu = str(Path(ald) / self.chip_variant) if ald else "" return self._arduino_libs_mcu @@ -1271,3 +1273,109 @@ class ComponentManager: session, useful for build reporting and debugging. """ self.logger.print_changes_summary() + + def remove_no_lto_flags(self) -> bool: + """ + Remove all -fno-lto flags from pioarduino-build.py. + + Removes all occurrences of -fno-lto from CCFLAGS, CFLAGS, CXXFLAGS, + and LINKFLAGS in the Arduino build script. + + Returns: + bool: True if successful, False otherwise + """ + build_py_path = str(Path(self.config.arduino_libs_mcu) / "pioarduino-build.py") + + if not os.path.exists(build_py_path): + print(f"Warning: pioarduino-build.py not found at {build_py_path}") + return False + + try: + with open(build_py_path, 'r', encoding='utf-8') as f: + content = f.read() + + # Remove all -fno-lto flags + modified_content = re.sub(r'["\']?-fno-lto["\']?,?\s*', '', content) + + # Clean up any resulting empty strings or double commas + modified_content = re.sub(r',\s*,', ',', modified_content) + modified_content = re.sub(r'\[\s*,', '[', modified_content) + modified_content = re.sub(r',\s*\]', ']', modified_content) + + with open(build_py_path, 'w', encoding='utf-8') as f: + f.write(modified_content) + + return True + + except (IOError, OSError) as e: + print(f"Error removing -fno-lto flags: {e}") + return False + + def add_lto_flags(self) -> bool: + """ + Add LTO flags to pioarduino-build.py. + + Adds -flto=auto to CCFLAGS, CFLAGS, CXXFLAGS and -flto to LINKFLAGS + in the Arduino build script. Flags are inserted right after the opening bracket. + + Returns: + bool: True if successful, False otherwise + """ + build_py_path = str(Path(self.config.arduino_libs_mcu) / "pioarduino-build.py") + + if not os.path.exists(build_py_path): + print(f"Warning: pioarduino-build.py not found at {build_py_path}") + return False + + try: + with open(build_py_path, 'r', encoding='utf-8') as f: + content = f.read() + + modified = False + + # Add -flto=auto to CCFLAGS right after the opening bracket + if 'CCFLAGS=[' in content: + ccflags_start = content.find('CCFLAGS=[') + ccflags_section_start = ccflags_start + len('CCFLAGS=[') + content = (content[:ccflags_section_start] + + '\n "-flto=auto",' + + content[ccflags_section_start:]) + modified = True + + # Add -flto=auto to CFLAGS right after the opening bracket + if 'CFLAGS=[' in content: + cflags_start = content.find('CFLAGS=[') + cflags_section_start = cflags_start + len('CFLAGS=[') + content = (content[:cflags_section_start] + + '\n "-flto=auto",' + + content[cflags_section_start:]) + modified = True + + # Add -flto=auto to CXXFLAGS right after the opening bracket + if 'CXXFLAGS=[' in content: + cxxflags_start = content.find('CXXFLAGS=[') + cxxflags_section_start = cxxflags_start + len('CXXFLAGS=[') + content = (content[:cxxflags_section_start] + + '\n "-flto=auto",' + + content[cxxflags_section_start:]) + modified = True + + # Add -flto to LINKFLAGS right after the opening bracket + if 'LINKFLAGS=[' in content: + linkflags_start = content.find('LINKFLAGS=[') + linkflags_section_start = linkflags_start + len('LINKFLAGS=[') + content = (content[:linkflags_section_start] + + '\n "-flto",' + + content[linkflags_section_start:]) + modified = True + + if modified: + with open(build_py_path, 'w', encoding='utf-8') as f: + f.write(content) + + print("*** Added LTO flags for Arduino compile ***") + return True + + except (IOError, OSError) as e: + print(f"Error adding LTO flags: {e}") + return False diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 9219839..9d9c068 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -76,10 +76,14 @@ os.environ["IDF_COMPONENT_OVERWRITE_MANAGED_COMPONENTS"] = "1" config = env.GetProjectConfig() board = env.BoardConfig() +pio_orig_frwrk = env.GetProjectOption("framework") mcu = board.get("build.mcu", "esp32") +chip_variant = board.get("build.chip_variant", "").lower() +chip_variant = chip_variant if chip_variant else mcu flash_speed = board.get("build.f_flash", "40000000L") flash_frequency = str(flash_speed.replace("000000L", "")) flash_mode = board.get("build.flash_mode", "dio") +boot_mode = board.get("build.boot", None) idf_variant = mcu.lower() flag_custom_sdkonfig = False flag_custom_component_add = False @@ -178,17 +182,29 @@ if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRMWRK_LIB_DIR_PATH = arduino_lib_dir.resolve() ARDUINO_FRMWRK_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH) - if mcu == "esp32c2": - ARDUINO_FRMWRK_C2_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH / mcu) + if mcu == "esp32c2" and "espidf" not in pio_orig_frwrk: + ARDUINO_FRMWRK_C2_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH / chip_variant) if not os.path.exists(ARDUINO_FRMWRK_C2_LIB_DIR): _arduino_c2_dir = platform.get_package_dir("framework-arduino-c2-skeleton-lib") if not _arduino_c2_dir: sys.stderr.write("Error: Missing framework-arduino-c2-skeleton-lib package\n") env.Exit(1) arduino_c2_dir = Path(_arduino_c2_dir) - ARDUINO_C2_DIR = str(arduino_c2_dir / mcu) + ARDUINO_C2_DIR = str(arduino_c2_dir / chip_variant) shutil.copytree(ARDUINO_C2_DIR, ARDUINO_FRMWRK_C2_LIB_DIR, dirs_exist_ok=True) - arduino_libs_mcu = str(ARDUINO_FRMWRK_LIB_DIR_PATH / mcu) + + if mcu == "esp32c61" and "espidf" not in pio_orig_frwrk: + ARDUINO_FRMWRK_C61_LIB_DIR = str(ARDUINO_FRMWRK_LIB_DIR_PATH / chip_variant) + if not os.path.exists(ARDUINO_FRMWRK_C61_LIB_DIR): + _arduino_c61_dir = platform.get_package_dir("framework-arduino-c61-skeleton-lib") + if not _arduino_c61_dir: + sys.stderr.write("Error: Missing framework-arduino-c61-skeleton-lib package\n") + env.Exit(1) + arduino_c61_dir = Path(_arduino_c61_dir) + ARDUINO_C61_DIR = str(arduino_c61_dir / chip_variant) + shutil.copytree(ARDUINO_C61_DIR, ARDUINO_FRMWRK_C61_LIB_DIR, dirs_exist_ok=True) + + arduino_libs_mcu = str(ARDUINO_FRMWRK_LIB_DIR_PATH / chip_variant) BUILD_DIR = env.subst("$BUILD_DIR") PROJECT_DIR = env.subst("$PROJECT_DIR") @@ -218,6 +234,10 @@ if config.has_option("env:"+env["PIOENV"], "custom_sdkconfig"): if "espidf.custom_sdkconfig" in board: flag_custom_sdkonfig = True +# Disable HybridCompile for espidf and arduino, espidf projects +# HybridCompile is always "framework = arduino" ! +if "espidf" in pio_orig_frwrk: + flag_custom_sdkonfig = False # Check for board-specific configurations that require sdkconfig generation def has_board_specific_config(): @@ -336,11 +356,18 @@ def HandleArduinoIDFsettings(env): flash_memory_type, psram_memory_type = parts else: flash_memory_type = memory_type - - # Check for additional flash configuration indicators - boot_mode = board.get("build", {}).get("boot", None) - flash_mode = board.get("build", {}).get("flash_mode", None) - + + # Add flash mode to sdkconfig + if flash_mode: + flash_mode_lower = flash_mode.lower() + board_config_flags.append(f"CONFIG_ESPTOOLPY_FLASHMODE_{flash_mode.upper()}=y") + + # Disable other flash mode options + flash_modes = ["qio", "qout", "dio", "dout"] + for mode in flash_modes: + if mode != flash_mode_lower: + board_config_flags.append(f"# CONFIG_ESPTOOLPY_FLASHMODE_{mode.upper()} is not set") + # Override flash_memory_type if boot mode indicates OPI if boot_mode == "opi" or flash_mode in ["dout", "opi"]: if not flash_memory_type or flash_memory_type.lower() != "opi": @@ -2577,24 +2604,24 @@ if os.path.isdir(ulp_dir) and os.listdir(ulp_dir) and mcu not in ("esp32c2", "es if ("arduino" in env.subst("$PIOFRAMEWORK")) and ("espidf" not in env.subst("$PIOFRAMEWORK")): def idf_lib_copy(source, target, env): - def _replace_move(src, dst): + def _replace_copy(src, dst): dst_p = Path(dst) dst_p.parent.mkdir(parents=True, exist_ok=True) try: - os.remove(dst) - except FileNotFoundError: + shutil.copy2(src, dst) + except (OSError, IOError): + # Gracefully handle missing source files (e.g., PSRAM libs in non-PSRAM builds) + # This is expected when copying variant-specific libraries pass - try: - os.replace(src, dst) - except OSError: - shutil.move(src, dst) + except Exception as e: + print(f"Warning: Failed to copy {src} to {dst}: {e}") env_build = str(Path(env["PROJECT_BUILD_DIR"]) / env["PIOENV"]) sdkconfig_h_path = str(Path(env_build) / "config" / "sdkconfig.h") arduino_libs = str(Path(ARDUINO_FRMWRK_LIB_DIR)) lib_src = str(Path(env_build) / "esp-idf") - lib_dst = str(Path(arduino_libs) / mcu / "lib") - ld_dst = str(Path(arduino_libs) / mcu / "ld") - mem_var = str(Path(arduino_libs) / mcu / board.get("build.arduino.memory_type", (board.get("build.flash_mode", "dio") + "_qspi"))) + lib_dst = str(Path(arduino_libs) / chip_variant / "lib") + ld_dst = str(Path(arduino_libs) / chip_variant / "ld") + mem_var = str(Path(arduino_libs) / chip_variant / board.get("build.arduino.memory_type", (board.get("build.flash_mode", "dio") + "_qspi"))) # Ensure destinations exist for d in (lib_dst, ld_dst, mem_var, str(Path(mem_var) / "include")): Path(d).mkdir(parents=True, exist_ok=True) @@ -2606,22 +2633,25 @@ if ("arduino" in env.subst("$PIOFRAMEWORK")) and ("espidf" not in env.subst("$PI if file.strip().endswith(".a"): shutil.copyfile(file, str(Path(lib_dst) / file.split(os.path.sep)[-1])) - _replace_move(str(Path(lib_dst) / "libspi_flash.a"), str(Path(mem_var) / "libspi_flash.a")) - _replace_move(str(Path(env_build) / "memory.ld"), str(Path(ld_dst) / "memory.ld")) + _replace_copy(str(Path(lib_dst) / "libspi_flash.a"), str(Path(mem_var) / "libspi_flash.a")) + _replace_copy(str(Path(env_build) / "memory.ld"), str(Path(ld_dst) / "memory.ld")) if mcu == "esp32s3": - _replace_move(str(Path(lib_dst) / "libesp_psram.a"), str(Path(mem_var) / "libesp_psram.a")) - _replace_move(str(Path(lib_dst) / "libesp_system.a"), str(Path(mem_var) / "libesp_system.a")) - _replace_move(str(Path(lib_dst) / "libfreertos.a"), str(Path(mem_var) / "libfreertos.a")) - _replace_move(str(Path(lib_dst) / "libbootloader_support.a"), str(Path(mem_var) / "libbootloader_support.a")) - _replace_move(str(Path(lib_dst) / "libesp_hw_support.a"), str(Path(mem_var) / "libesp_hw_support.a")) - _replace_move(str(Path(lib_dst) / "libesp_lcd.a"), str(Path(mem_var) / "libesp_lcd.a")) + _replace_copy(str(Path(lib_dst) / "libesp_psram.a"), str(Path(mem_var) / "libesp_psram.a")) + _replace_copy(str(Path(lib_dst) / "libesp_system.a"), str(Path(mem_var) / "libesp_system.a")) + _replace_copy(str(Path(lib_dst) / "libfreertos.a"), str(Path(mem_var) / "libfreertos.a")) + _replace_copy(str(Path(lib_dst) / "libbootloader_support.a"), str(Path(mem_var) / "libbootloader_support.a")) + _replace_copy(str(Path(lib_dst) / "libesp_hw_support.a"), str(Path(mem_var) / "libesp_hw_support.a")) + _replace_copy(str(Path(lib_dst) / "libesp_lcd.a"), str(Path(mem_var) / "libesp_lcd.a")) shutil.copyfile(sdkconfig_h_path, str(Path(mem_var) / "include" / "sdkconfig.h")) - if not bool(os.path.isfile(str(Path(arduino_libs) / mcu / "sdkconfig.orig"))): - shutil.move(str(Path(arduino_libs) / mcu / "sdkconfig"), str(Path(arduino_libs) / mcu / "sdkconfig.orig")) - shutil.copyfile(str(Path(env.subst("$PROJECT_DIR")) / ("sdkconfig." + env["PIOENV"])), str(Path(arduino_libs) / mcu / "sdkconfig")) + if not bool(os.path.isfile(str(Path(arduino_libs) / chip_variant / "sdkconfig.orig"))): + shutil.move(str(Path(arduino_libs) / chip_variant / "sdkconfig"), str(Path(arduino_libs) / chip_variant / "sdkconfig.orig")) + shutil.copyfile(str(Path(env.subst("$PROJECT_DIR")) / ("sdkconfig." + env["PIOENV"])), str(Path(arduino_libs) / chip_variant / "sdkconfig")) shutil.copyfile(str(Path(env.subst("$PROJECT_DIR")) / ("sdkconfig." + env["PIOENV"])), str(Path(arduino_libs) / "sdkconfig")) try: + # clean env build folder to avoid issues with following Arduino build + shutil.rmtree(env_build) + Path(env_build).mkdir(parents=True, exist_ok=True) os.remove(str(Path(env.subst("$PROJECT_DIR")) / "dependencies.lock")) os.remove(str(Path(env.subst("$PROJECT_DIR")) / "CMakeLists.txt")) except FileNotFoundError: diff --git a/builder/penv_setup.py b/builder/penv_setup.py index 197e7c7..5345bc3 100644 --- a/builder/penv_setup.py +++ b/builder/penv_setup.py @@ -38,7 +38,7 @@ if sys.version_info < (3, 10): github_actions = bool(os.getenv("GITHUB_ACTIONS")) PLATFORMIO_URL_VERSION_RE = re.compile( - r'/v?(\d+\.\d+\.\d+(?:[.-]\w+)?(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', + r'/v?(\d+\.\d+\.\d+(?:[.-](?:alpha|beta|rc|dev|post|pre)\d*)?(?:\.\d+)?)(?:\.(?:zip|tar\.gz|tar\.bz2))?$', re.IGNORECASE, ) diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 0490e55..5663139 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -173,6 +173,37 @@ custom_component_remove = espressif/esp_hosted espressif/rmaker_common chmorgan/esp-libhelix-mp3 +[env:esp32-c61-devkitc1-n8r2] +platform = espressif32 +framework = arduino +board = esp32-c61-devkitc1-n8r2 +monitor_speed = 115200 +lib_ignore = wifi + ble + dsp + spiffs + NetworkClientSecure + Matter + Zigbee + ESP RainMaker +custom_component_remove = espressif/esp_hosted + espressif/esp_wifi_remote + espressif/network_provisioning + espressif/mdns + espressif/esp-dsp + espressif/esp_modem + espressif/esp32-camera + espressif/libsodium + espressif/esp-modbus + espressif/qrcode + espressif/esp_insights + espressif/esp_diag_data_store + espressif/esp_diagnostics + espressif/cbor + espressif/esp_rainmaker + espressif/rmaker_common + chmorgan/esp-libhelix-mp3 + [env:esp32-h2-devkitm-1] platform = espressif32 framework = arduino diff --git a/examples/espidf-arduino-matter-light/include/README b/examples/espidf-arduino-matter-light/include/README new file mode 100644 index 0000000..194dcd4 --- /dev/null +++ b/examples/espidf-arduino-matter-light/include/README @@ -0,0 +1,39 @@ + +This directory is intended for project header files. + +A header file is a file containing C declarations and macro definitions +to be shared between several project source files. You request the use of a +header file in your project source file (C, C++, etc) located in `src` folder +by including it, with the C preprocessing directive `#include'. + +```src/main.c + +#include "header.h" + +int main (void) +{ + ... +} +``` + +Including a header file produces the same results as copying the header file +into each source file that needs it. Such copying would be time-consuming +and error-prone. With a header file, the related declarations appear +in only one place. If they need to be changed, they can be changed in one +place, and programs that include the header file will automatically use the +new version when next recompiled. The header file eliminates the labor of +finding and changing all the copies as well as the risk that a failure to +find one copy will result in inconsistencies within a program. + +In C, the usual convention is to give header files names that end with `.h'. +It is most portable to use only letters, digits, dashes, and underscores in +header file names, and at most one dot. + +Read more about using header files in official GCC documentation: + +* Include Syntax +* Include Operation +* Once-Only Headers +* Computed Includes + +https://gcc.gnu.org/onlinedocs/cpp/Header-Files.html diff --git a/examples/espidf-arduino-matter-light/lib/README b/examples/espidf-arduino-matter-light/lib/README new file mode 100644 index 0000000..2593a33 --- /dev/null +++ b/examples/espidf-arduino-matter-light/lib/README @@ -0,0 +1,46 @@ + +This directory is intended for project specific (private) libraries. +PlatformIO will compile them to static libraries and link into executable file. + +The source code of each library should be placed in an own separate directory +("lib/your_library_name/[here are source files]"). + +For example, see a structure of the following two libraries `Foo` and `Bar`: + +|--lib +| | +| |--Bar +| | |--docs +| | |--examples +| | |--src +| | |- Bar.c +| | |- Bar.h +| | |- library.json (optional, custom build options, etc) https://docs.platformio.org/page/librarymanager/config.html +| | +| |--Foo +| | |- Foo.c +| | |- Foo.h +| | +| |- README --> THIS FILE +| +|- platformio.ini +|--src + |- main.c + +and a contents of `src/main.c`: +``` +#include +#include + +int main (void) +{ + ... +} + +``` + +PlatformIO Library Dependency Finder will find automatically dependent +libraries scanning project source files. + +More information about PlatformIO Library Dependency Finder +- https://docs.platformio.org/page/librarymanager/ldf.html diff --git a/examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread b/examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread new file mode 100644 index 0000000..502480f --- /dev/null +++ b/examples/espidf-arduino-matter-light/sdkconfig.defaults.c6_thread @@ -0,0 +1,79 @@ +CONFIG_IDF_TARGET="esp32c6" + +# Arduino Settings +CONFIG_FREERTOS_HZ=1000 +CONFIG_AUTOSTART_ARDUINO=y + +# Log Levels +# Boot Messages - Log level +CONFIG_BOOTLOADER_LOG_LEVEL_ERROR=y +# Arduino Log Level +CONFIG_ARDUHAL_LOG_DEFAULT_LEVEL_INFO=y +# IDF Log Level +CONFIG_LOG_DEFAULT_LEVEL_ERROR=y + +# Default to 921600 baud when flashing and monitoring device +CONFIG_ESPTOOLPY_BAUD_921600B=y +CONFIG_ESPTOOLPY_BAUD=921600 +CONFIG_ESPTOOLPY_COMPRESSED=y +CONFIG_ESPTOOLPY_MONITOR_BAUD_115200B=y +CONFIG_ESPTOOLPY_MONITOR_BAUD=115200 +CONFIG_ESPTOOLPY_FLASHSIZE_4MB=y + +# libsodium +CONFIG_LIBSODIUM_USE_MBEDTLS_SHA=y + +# NIMBLE +CONFIG_BT_ENABLED=y +CONFIG_BT_NIMBLE_ENABLED=y +CONFIG_BT_NIMBLE_EXT_ADV=n +CONFIG_BT_NIMBLE_HCI_EVT_BUF_SIZE=70 +CONFIG_USE_BLE_ONLY_FOR_COMMISSIONING=n + +# FreeRTOS should use legacy API +CONFIG_FREERTOS_ENABLE_BACKWARD_COMPATIBILITY=y + +# Enable OpenThread +CONFIG_OPENTHREAD_ENABLED=y +CONFIG_OPENTHREAD_SRP_CLIENT=y +CONFIG_OPENTHREAD_DNS_CLIENT=y +CONFIG_OPENTHREAD_LOG_LEVEL_DYNAMIC=n +CONFIG_OPENTHREAD_LOG_LEVEL_NOTE=y +CONFIG_OPENTHREAD_CLI=n + +# Disable lwip ipv6 autoconfig +CONFIG_LWIP_IPV6_AUTOCONFIG=n + +# Use a custom partition table +CONFIG_PARTITION_TABLE_CUSTOM=y +CONFIG_PARTITION_TABLE_CUSTOM_FILENAME="partitions.csv" + +# LwIP config for OpenThread +CONFIG_LWIP_IPV6_NUM_ADDRESSES=8 +CONFIG_LWIP_MULTICAST_PING=y + +# MDNS platform +CONFIG_USE_MINIMAL_MDNS=n +CONFIG_ENABLE_EXTENDED_DISCOVERY=y + +# Enable OTA Requester +CONFIG_ENABLE_OTA_REQUESTOR=n + +# Disable STA and AP for ESP32C6 +CONFIG_ENABLE_WIFI_STATION=n +CONFIG_ENABLE_WIFI_AP=n + +# Enable chip shell +CONFIG_ENABLE_CHIP_SHELL=n + +# Disable persist subscriptions +CONFIG_ENABLE_PERSIST_SUBSCRIPTIONS=n + +# MRP configs +CONFIG_MRP_LOCAL_ACTIVE_RETRY_INTERVAL_FOR_THREAD=5000 +CONFIG_MRP_LOCAL_IDLE_RETRY_INTERVAL_FOR_THREAD=5000 +CONFIG_MRP_RETRY_INTERVAL_SENDER_BOOST_FOR_THREAD=5000 +CONFIG_MRP_MAX_RETRANS=3 + +# Enable HKDF in mbedtls +CONFIG_MBEDTLS_HKDF_C=y diff --git a/examples/tasmota_platformio_override.ini b/examples/tasmota_platformio_override.ini index 4ba00f2..af8b88c 100644 --- a/examples/tasmota_platformio_override.ini +++ b/examples/tasmota_platformio_override.ini @@ -10,6 +10,7 @@ board = esp32 build_flags = ${env:tasmota32_base.build_flags} -DHTTPCLIENT_NOSECURE -DUPDATE_NOCRYPT +build_unflags = -fno-lto lib_ignore = ${env:tasmota32_base.lib_ignore} Micro-RTSP epdiy diff --git a/platform.json b/platform.json index 8759ba8..02a997f 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/pioarduino/platform-espressif32.git" }, - "version": "55.03.34", + "version": "55.03.35", "frameworks": { "arduino": { "script": "builder/frameworks/arduino.py" @@ -33,13 +33,13 @@ "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.4/esp32-3.3.4.tar.xz" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.5/esp32-3.3.5.tar.xz" }, "framework-arduinoespressif32-libs": { "type": "framework", "optional": true, "owner": "espressif", - "version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.4/esp32-3.3.4-libs.tar.xz" + "version": "https://github.com/espressif/arduino-esp32/releases/download/3.3.5/esp32-3.3.5-libs.tar.xz" }, "framework-arduino-c2-skeleton-lib": { "type": "framework", @@ -47,25 +47,31 @@ "owner": "espressif", "version": "https://github.com/pioarduino/platform-espressif32/releases/download/c2-skeleton/c2_8410210c9a_compile_skeleton.zip" }, + "framework-arduino-c61-skeleton-lib": { + "type": "framework", + "optional": true, + "owner": "espressif", + "version": "https://github.com/pioarduino/platform-espressif32/releases/download/c61-skeleton/c61_d1e854920a_compile_skeleton.zip" + }, "framework-espidf": { "type": "framework", "optional": true, "owner": "pioarduino", - "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.5.1.251106/esp-idf-v5.5.1.tar.xz" + "version": "https://github.com/pioarduino/esp-idf/releases/download/v5.5.1.251215/esp-idf-v5.5.1.tar.xz" }, "toolchain-xtensa-esp-elf": { "type": "toolchain", "optional": true, "owner": "pioarduino", - "package-version": "14.2.0+20250730", - "version": "https://github.com/pioarduino/registry/releases/download/0.0.1/xtensa-esp-elf-14.2.0_20250730.zip" + "package-version": "14.2.0+20251107", + "version": "https://github.com/pioarduino/registry/releases/download/0.0.1/xtensa-esp-elf-14.2.0_20251107.zip" }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "pioarduino", - "package-version": "14.2.0+20250730", - "version": "https://github.com/pioarduino/registry/releases/download/0.0.1/riscv32-esp-elf-14.2.0_20250730.zip" + "package-version": "14.2.0+20251107", + "version": "https://github.com/pioarduino/registry/releases/download/0.0.1/riscv32-esp-elf-14.2.0_20251107.zip" }, "toolchain-esp32ulp": { "type": "toolchain", @@ -99,8 +105,8 @@ "type": "tool", "optional": false, "owner": "pioarduino", - "package-version": "5.3.2", - "version": "https://github.com/pioarduino/esp_install/releases/download/v5.3.2/esp_install-v5.3.2.zip" + "package-version": "5.3.4", + "version": "https://github.com/pioarduino/esp_install/releases/download/v5.3.4/esp_install-v5.3.4.zip" }, "contrib-piohome": { "optional": true, diff --git a/platform.py b/platform.py index 2928911..a780adf 100644 --- a/platform.py +++ b/platform.py @@ -40,7 +40,6 @@ import logging import os import requests import shutil -import socket import subprocess from pathlib import Path from typing import Optional, Dict, List, Any, Union @@ -70,7 +69,7 @@ tl_install_name = "tool-esp_install" # MCUs that support ESP-builtin debug ESP_BUILTIN_DEBUG_MCUS = frozenset([ - "esp32c3", "esp32c5", "esp32c6", "esp32s3", "esp32h2", "esp32p4" + "esp32c3", "esp32c5", "esp32c6", "esp32c61", "esp32s3", "esp32h2", "esp32p4" ]) # MCU configuration mapping @@ -82,7 +81,7 @@ MCU_TOOLCHAIN_CONFIG = { }, "riscv": { "mcus": frozenset([ - "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32h2", "esp32p4" + "esp32c2", "esp32c3", "esp32c5", "esp32c6", "esp32c61", "esp32h2", "esp32p4" ]), "toolchains": ["toolchain-riscv32-esp"], "debug_tools": ["tool-riscv32-esp-elf-gdb"] @@ -556,7 +555,7 @@ class Espressif32Platform(PlatformBase): return self.install_tool(tool_name) - def _configure_arduino_framework(self, frameworks: List[str]) -> None: + def _configure_arduino_framework(self, frameworks: List[str], mcu: str) -> None: """Configure Arduino framework dependencies.""" if "arduino" not in frameworks: return @@ -565,6 +564,10 @@ class Espressif32Platform(PlatformBase): safe_remove_directory_pattern(Path(self.packages_dir), f"framework-arduinoespressif32.*") self.packages["framework-arduinoespressif32"]["optional"] = False self.packages["framework-arduinoespressif32-libs"]["optional"] = False + if mcu == "esp32c2": + self.packages["framework-arduino-c2-skeleton-lib"]["optional"] = False + if mcu == "esp32c61": + self.packages["framework-arduino-c61-skeleton-lib"]["optional"] = False def _configure_espidf_framework( self, frameworks: List[str], variables: Dict, board_config: Dict, mcu: str @@ -581,8 +584,6 @@ class Espressif32Platform(PlatformBase): safe_remove_directory_pattern(Path(self.packages_dir), f"framework-espidf@*") safe_remove_directory_pattern(Path(self.packages_dir), f"framework-espidf.*") self.packages["framework-espidf"]["optional"] = False - if mcu == "esp32c2": - self.packages["framework-arduino-c2-skeleton-lib"]["optional"] = False def _get_mcu_config(self, mcu: str) -> Optional[Dict]: """Get MCU configuration with optimized caching and search.""" @@ -818,7 +819,7 @@ class Espressif32Platform(PlatformBase): self._esptool_path = esptool_path # Configuration steps (now with penv available) - self._configure_arduino_framework(frameworks) + self._configure_arduino_framework(frameworks, mcu) self._configure_espidf_framework(frameworks, variables, board_config, mcu) self._configure_mcu_toolchains(mcu, variables, targets) self._handle_littlefs_tool(for_download=False) # Ensure mklittlefs is installed