diff --git a/boards/adafruit_matrixportal_esp32s3.json b/boards/adafruit_matrixportal_esp32s3.json new file mode 100644 index 000000000..3446cd217 --- /dev/null +++ b/boards/adafruit_matrixportal_esp32s3.json @@ -0,0 +1,65 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "partitions-8MB-tinyuf2.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_ADAFRUIT_MATRIXPORTAL_ESP32S3", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DBOARD_HAS_PSRAM" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x239A", + "0x8125" + ], + [ + "0x239A", + "0x0125" + ], + [ + "0x239A", + "0x8126" + ] + ], + "mcu": "esp32s3", + "variant": "adafruit_matrixportal_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Adafruit MatrixPortal ESP32-S3", + "upload": { + "arduino": { + "flash_extra_images": [ + [ + "0x410000", + "variants/adafruit_matrixportal_esp32s3/tinyuf2.bin" + ] + ] + }, + "flash_size": "8MB", + "maximum_ram_size": 327680, + "maximum_size": 8388608, + "use_1200bps_touch": true, + "wait_for_upload_port": true, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://www.adafruit.com/product/5778", + "vendor": "Adafruit" +} diff --git a/boards/arduino_nano_esp32.json b/boards/arduino_nano_esp32.json new file mode 100644 index 000000000..c6da4e227 --- /dev/null +++ b/boards/arduino_nano_esp32.json @@ -0,0 +1,53 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32s3_out.ld", + "partitions": "app3M_fat9M_fact512k_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NANO_ESP32", + "-DBOARD_HAS_PIN_REMAP", + "-DBOARD_HAS_PSRAM", + "-DUSB_MANUFACTURER=\\\"Arduino\\\"", + "-DUSB_PRODUCT=\\\"NanoESP32\\\"", + "-DARDUINO_USB_CDC_ON_BOOT=1", + "-DARDUINO_USB_DFU_ON_BOOT=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x2341", + "0x0070" + ] + ], + "mcu": "esp32s3", + "variant": "arduino_nano_nora" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Arduino Nano ESP32", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800, + "protocol": "dfu" + }, + "url": "https://docs.arduino.cc/hardware/nano-esp32", + "vendor": "Arduino" +} diff --git a/boards/bee_motion_s3.json b/boards/bee_motion_s3.json index c620b80c3..c1cae0fd0 100644 --- a/boards/bee_motion_s3.json +++ b/boards/bee_motion_s3.json @@ -1,7 +1,7 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s3_out.ld" }, "core": "esp32", "extra_flags": [ diff --git a/boards/bee_s3.json b/boards/bee_s3.json index 2f65542fd..16e47ee79 100644 --- a/boards/bee_s3.json +++ b/boards/bee_s3.json @@ -1,7 +1,7 @@ { "build": { "arduino": { - "ldscript": "esp32s2_out.ld" + "ldscript": "esp32s3_out.ld" }, "core": "esp32", "extra_flags": [ diff --git a/boards/dfrobot_romeo_esp32s3.json b/boards/dfrobot_romeo_esp32s3.json new file mode 100644 index 000000000..63a7cb472 --- /dev/null +++ b/boards/dfrobot_romeo_esp32s3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "app3M_fat9M_16MB.csv", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_DFROBOT_ROMEO_ESP32S3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "dfrobot_romeo_esp32s3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "DFRobot Romeo ESP32-S3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://wiki.dfrobot.com/", + "vendor": "DFRobot" +} diff --git a/boards/esp32-c6-devkitc-1.json b/boards/esp32-c6-devkitc-1.json new file mode 100644 index 000000000..6e90aee03 --- /dev/null +++ b/boards/esp32-c6-devkitc-1.json @@ -0,0 +1,25 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6" + }, + "connectivity": [ + "wifi" + ], + "frameworks": [ + "espidf" + ], + "name": "Espressif ESP32-C6-DevKitC-1", + "upload": { + "flash_size": "8MB", + "maximum_ram_size": 524288, + "maximum_size": 8388608, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitc-1/index.html", + "vendor": "Espressif" +} diff --git a/boards/esp32-c6-devkitm-1.json b/boards/esp32-c6-devkitm-1.json new file mode 100644 index 000000000..c30687fa9 --- /dev/null +++ b/boards/esp32-c6-devkitm-1.json @@ -0,0 +1,29 @@ +{ + "build": { + "core": "esp32", + "f_cpu": "160000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "mcu": "esp32c6", + "variant": "esp32c6" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32c6.cfg" + }, + "frameworks": [ + "espidf" + ], + "name": "Espressif ESP32-C6-DevKitM-1", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://docs.espressif.com/projects/espressif-esp-dev-kits/en/latest/esp32c6/esp32-c6-devkitm-1/index.html", + "vendor": "Espressif" +} diff --git a/boards/esp32s3camlcd.json b/boards/esp32s3camlcd.json index 5a807a858..1d7e0c497 100644 --- a/boards/esp32s3camlcd.json +++ b/boards/esp32s3camlcd.json @@ -1,7 +1,7 @@ { "build": { "arduino":{ - "ldscript": "esp32_out.ld", + "ldscript": "esp32s3_out.ld", "memory_type": "opi_opi" }, "boot": "opi", diff --git a/boards/lolin_s2_mini.json b/boards/lolin_s2_mini.json index 3fe4f7122..59832f8cb 100644 --- a/boards/lolin_s2_mini.json +++ b/boards/lolin_s2_mini.json @@ -25,7 +25,7 @@ "wifi" ], "debug": { - "openocd_board": "esp32s2.cfg" + "openocd_target": "esp32s2.cfg" }, "frameworks": [ "arduino", diff --git a/boards/lolin_s2_pico.json b/boards/lolin_s2_pico.json index dab2b7ec0..0214a0eea 100644 --- a/boards/lolin_s2_pico.json +++ b/boards/lolin_s2_pico.json @@ -25,7 +25,7 @@ "wifi" ], "debug": { - "openocd_board": "esp32s2.cfg" + "openocd_target": "esp32s2.cfg" }, "frameworks": [ "arduino", diff --git a/boards/m5stack-cores3.json b/boards/m5stack-cores3.json new file mode 100644 index 000000000..72571e0b7 --- /dev/null +++ b/boards/m5stack-cores3.json @@ -0,0 +1,46 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "partitions": "default_16MB.csv" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_M5STACK_CORES3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x8119" + ] + ], + "mcu": "esp32s3", + "variant": "m5stack_cores3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stack CoreS3", + "upload": { + "flash_size": "16MB", + "maximum_ram_size": 327680, + "maximum_size": 16777216, + "require_upload_port": true, + "speed": 921600 + }, + "url": "https://docs.m5stack.com/en/core/CoreS3", + "vendor": "M5Stack" +} diff --git a/boards/m5stamp-pico.json b/boards/m5stamp-pico.json new file mode 100644 index 000000000..8f39fe5ce --- /dev/null +++ b/boards/m5stamp-pico.json @@ -0,0 +1,34 @@ +{ + "build": { + "arduino":{ + "ldscript": "esp32_out.ld" + }, + "core": "esp32", + "extra_flags": "-DARDUINO_M5Stamp_Pico", + "f_cpu": "240000000L", + "f_flash": "40000000L", + "flash_mode": "dio", + "mcu": "esp32", + "variant": "m5stack_stamp_pico" + }, + "connectivity": [ + "wifi", + "bluetooth", + "ethernet", + "can" + ], + "frameworks": [ + "arduino", + "espidf" + ], + "name": "M5Stamp-Pico", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 1500000 + }, + "url": "https://shop.m5stack.com/products/m5stamp-pico-mate-with-pin-headers", + "vendor": "M5Stack" +} diff --git a/boards/nebulas3.json b/boards/nebulas3.json new file mode 100644 index 000000000..dc6236494 --- /dev/null +++ b/boards/nebulas3.json @@ -0,0 +1,47 @@ +{ + "build": { + "arduino": { + "ldscript": "esp32s3_out.ld", + "memory_type": "qio_opi" + }, + "core": "esp32", + "extra_flags": [ + "-DARDUINO_NEBULAS3", + "-DARDUINO_USB_MODE=1", + "-DARDUINO_RUNNING_CORE=1", + "-DARDUINO_EVENT_RUNNING_CORE=1", + "-DARDUINO_USB_CDC_ON_BOOT=1" + ], + "f_cpu": "240000000L", + "f_flash": "80000000L", + "flash_mode": "qio", + "hwids": [ + [ + "0x303A", + "0x1001" + ] + ], + "mcu": "esp32s3", + "variant": "Nebula_S3" + }, + "connectivity": [ + "wifi" + ], + "debug": { + "openocd_target": "esp32s3.cfg" + }, + "frameworks": [ + "arduino", + "espidf" + ], + "name": "Kinetic Dynamics Nebula S3", + "upload": { + "flash_size": "4MB", + "maximum_ram_size": 327680, + "maximum_size": 4194304, + "require_upload_port": true, + "speed": 460800 + }, + "url": "https://kineticdynamics.in/product/nebula-s3/", + "vendor": "Kinetic Dynamics" +} diff --git a/builder/frameworks/_embed_files.py b/builder/frameworks/_embed_files.py index 5469e3bce..c89dc4338 100644 --- a/builder/frameworks/_embed_files.py +++ b/builder/frameworks/_embed_files.py @@ -110,14 +110,14 @@ def transform_to_asm(target, source, env): " ".join( [ "riscv32-esp-elf-objcopy" - if mcu == "esp32c3" + if mcu in ("esp32c3", "esp32c6") else "xtensa-%s-elf-objcopy" % mcu, "--input-target", "binary", "--output-target", - "elf32-littleriscv" if mcu == "esp32c3" else "elf32-xtensa-le", + "elf32-littleriscv" if mcu in ("esp32c3","esp32c6") else "elf32-xtensa-le", "--binary-architecture", - "riscv" if mcu == "esp32c3" else "xtensa", + "riscv" if mcu in ("esp32c3","esp32c6") else "xtensa", "--rename-section", ".data=.rodata.embedded", "$SOURCE", diff --git a/builder/frameworks/espidf.py b/builder/frameworks/espidf.py index 71cce2923..41739557b 100644 --- a/builder/frameworks/espidf.py +++ b/builder/frameworks/espidf.py @@ -27,6 +27,7 @@ import shutil import os import pkg_resources +import platform as sys_platform import click import semantic_version @@ -37,7 +38,7 @@ DefaultEnvironment, ) -from platformio import fs +from platformio import fs, __version__ from platformio.compat import IS_WINDOWS from platformio.proc import exec_command from platformio.builder.tools.piolib import ProjectAsLibBuilder @@ -62,13 +63,22 @@ IDF_ENV_VERSION = "1.0.0" FRAMEWORK_DIR = platform.get_package_dir("framework-espidf") TOOLCHAIN_DIR = platform.get_package_dir( - "toolchain-%s" % ("riscv32-esp" if mcu == "esp32c3" else ("xtensa-%s" % mcu)) + "toolchain-%s" % ("riscv32-esp" if mcu in ("esp32c3","esp32c6") else ("xtensa-%s" % mcu)) ) assert os.path.isdir(FRAMEWORK_DIR) assert os.path.isdir(TOOLCHAIN_DIR) +# The latest IDF uses a standalone GDB package which requires at least PlatformIO 6.1.11 +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!") + # Arduino framework as a component is not compatible with ESP-IDF >=4.1 if "arduino" in env.subst("$PIOFRAMEWORK"): ARDUINO_FRAMEWORK_DIR = platform.get_package_dir("framework-arduinoespressif32") @@ -234,7 +244,7 @@ def populate_idf_env_vars(idf_env): os.path.dirname(get_python_exe()), ] - if mcu != "esp32c3": + if mcu not in ("esp32c3", "esp32c6"): additional_packages.append( os.path.join(platform.get_package_dir("toolchain-esp32ulp"), "bin"), ) @@ -351,7 +361,7 @@ def _add_archive(archive_path, link_args): args = click.parser.split_arg_string(fragment) if fragment_role == "flags": link_args["LINKFLAGS"].extend(args) - elif fragment_role == "libraries": + elif fragment_role in ("libraries", "libraryPath"): if fragment.startswith("-l"): link_args["LIBS"].extend(args) elif fragment.startswith("-L"): @@ -489,7 +499,7 @@ def extract_linker_script_fragments(framework_components_dir, sdk_config): sys.stderr.write("Error: Failed to extract paths to linker script fragments\n") env.Exit(1) - if mcu == "esp32c3": + if mcu in ("esp32c3", "esp32c6"): result.append(os.path.join(framework_components_dir, "riscv", "linker.lf")) # Add extra linker fragments @@ -624,6 +634,7 @@ def prepare_build_envs(config, default_env, debug_allowed=True): defines = extract_defines(cg) compile_commands = cg.get("compileCommandFragments", []) build_env = default_env.Clone() + build_env.SetOption("implicit_cache", 1) for cc in compile_commands: build_flags = cc.get("fragment") if not build_flags.startswith("-D"): @@ -1104,8 +1115,12 @@ def _get_installed_pip_packages(python_exe_path): "pyparsing": "~=3.0.9" if IDF5 else ">=2.0.3,<2.4.0", "kconfiglib": "~=14.1.0" if IDF5 else "~=13.7.1", "idf-component-manager": "~=1.2.3" if IDF5 else "~=1.0", + "esp-idf-kconfig": "~=1.2.0" } + if sys_platform.system() == "Darwin" and "arm" in sys_platform.machine().lower(): + deps["chardet"] = ">=3.0.2,<4" + python_exe_path = get_python_exe() installed_packages = _get_installed_pip_packages(python_exe_path) packages_to_install = [] @@ -1498,7 +1513,7 @@ def _skip_prj_source_files(node): ( board.get( "upload.bootloader_offset", - "0x0" if mcu in ("esp32c3", "esp32s3") else "0x1000", + "0x0" if mcu in ("esp32c3", "esp32c6", "esp32s3") else "0x1000", ), os.path.join("$BUILD_DIR", "bootloader.bin"), ), @@ -1543,10 +1558,11 @@ def _skip_prj_source_files(node): # Add include dirs from PlatformIO build system to project CPPPATH so # they're visible to PIOBUILDFILES project_env.AppendUnique( - CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR"] + CPPPATH=["$PROJECT_INCLUDE_DIR", "$PROJECT_SRC_DIR", "$PROJECT_DIR"] + get_project_lib_includes(env) ) + project_env.ProcessFlags(env.get("SRC_BUILD_FLAGS")) env.Append( PIOBUILDFILES=compile_source_files( target_configs.get(project_target_name), @@ -1577,7 +1593,7 @@ 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 != "esp32c3": +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") # diff --git a/builder/frameworks/ulp.py b/builder/frameworks/ulp.py index 416b5b20d..5af8f87d1 100644 --- a/builder/frameworks/ulp.py +++ b/builder/frameworks/ulp.py @@ -129,7 +129,6 @@ def compile_ulp_binary(): os.path.join(ULP_BUILD_DIR, "ulp_main.h"), os.path.join(ULP_BUILD_DIR, "ulp_main.ld"), os.path.join(ULP_BUILD_DIR, "ulp_main.bin"), - os.path.join(ULP_BUILD_DIR, "esp32.ulp.ld"), ], None, ulp_env.VerboseAction(" ".join(cmd), "Generating ULP project files $TARGETS"), diff --git a/builder/main.py b/builder/main.py index 21348d37d..1f493503a 100644 --- a/builder/main.py +++ b/builder/main.py @@ -108,7 +108,9 @@ def _parse_partitions(env): return result = [] - next_offset = 0 + # The first offset is 0x9000 because partition table is flashed to 0x8000 and + # occupies an entire flash sector, which size is 0x1000 + next_offset = 0x9000 with open(partitions_csv) as fp: for line in fp.readlines(): line = line.strip() @@ -117,11 +119,14 @@ def _parse_partitions(env): tokens = [t.strip() for t in line.split(",")] if len(tokens) < 5: continue + + bound = 0x10000 if tokens[1] in ("0", "app") else 4 + calculated_offset = (next_offset + bound - 1) & ~(bound - 1) partition = { "name": tokens[0], "type": tokens[1], "subtype": tokens[2], - "offset": tokens[3] or next_offset, + "offset": tokens[3] or calculated_offset, "size": tokens[4], "flags": tokens[5] if len(tokens) > 5 else None } @@ -130,21 +135,41 @@ def _parse_partitions(env): partition["size"] ) - bound = 0x10000 if partition["type"] in ("0", "app") else 4 - next_offset = (next_offset + bound - 1) & ~(bound - 1) - return result def _update_max_upload_size(env): if not env.get("PARTITIONS_TABLE_CSV"): return - sizes = [ - _parse_size(p["size"]) for p in _parse_partitions(env) + sizes = { + p["subtype"]: _parse_size(p["size"]) for p in _parse_partitions(env) if p["type"] in ("0", "app") - ] - if sizes: - board.update("upload.maximum_size", max(sizes)) + } + + partitions = {p["name"]: p for p in _parse_partitions(env)} + + # User-specified partition name has the highest priority + custom_app_partition_name = board.get("build.app_partition_name", "") + if custom_app_partition_name: + selected_partition = partitions.get(custom_app_partition_name, {}) + if selected_partition: + board.update("upload.maximum_size", _parse_size(selected_partition["size"])) + return + else: + print( + "Warning! Selected partition `%s` is not available in the partition " \ + "table! Default partition will be used!" % custom_app_partition_name + ) + + # Otherwise, one of the `factory` or `ota_0` partitions is used to determine + # available memory size. If both partitions are set, we should prefer the `factory`, + # but there are cases (e.g. Adafruit's `partitions-4MB-tinyuf2.csv`) that uses the + # `factory` partition for their UF2 bootloader. So let's use the first match + # https://docs.espressif.com/projects/esp-idf/en/latest/esp32/api-guides/partition-tables.html#subtype + for p in partitions.values(): + if p["type"] in ("0", "app") and p["subtype"] in ("factory", "ota_0"): + board.update("upload.maximum_size", _parse_size(p["size"])) + break def _to_unix_slashes(path): @@ -191,7 +216,7 @@ def __fetch_fs_size(target, source, env): mcu = board.get("build.mcu", "esp32") toolchain_arch = "xtensa-%s" % mcu filesystem = board.get("build.filesystem", "spiffs") -if mcu == "esp32c3": +if mcu in ("esp32c3", "esp32c6"): toolchain_arch = "riscv32-esp" if "INTEGRATION_EXTRA_DATA" not in env: @@ -207,7 +232,16 @@ def __fetch_fs_size(target, source, env): AS="%s-elf-as" % toolchain_arch, CC="%s-elf-gcc" % toolchain_arch, CXX="%s-elf-g++" % toolchain_arch, - GDB="%s-elf-gdb" % toolchain_arch, + GDB=join( + platform.get_package_dir( + "tool-riscv32-esp-elf-gdb" + if mcu in ("esp32c3", "esp32c6") + else "tool-xtensa-esp-elf-gdb" + ) + or "", + "bin", + "%s-elf-gdb" % toolchain_arch, + ) if env.get("PIOFRAMEWORK") == ["espidf"] else "%s-elf-gdb" % toolchain_arch, OBJCOPY=join( platform.get_package_dir("tool-esptoolpy") or "", "esptool.py"), RANLIB="%s-elf-ranlib" % toolchain_arch, @@ -259,7 +293,7 @@ def __fetch_fs_size(target, source, env): BUILDERS=dict( ElfToBin=Builder( action=env.VerboseAction(" ".join([ - '"$PYTHONEXE" "$OBJCOPY"', + '"$PYTHONEXE" "$OBJCOPY"', "--chip", mcu, "elf2image", "--flash_mode", "${__get_board_flash_mode(__env__)}", "--flash_freq", "${__get_board_f_flash(__env__)}", @@ -455,6 +489,27 @@ def __fetch_fs_size(target, source, env): env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE") ] +elif upload_protocol == "dfu": + + hwids = board.get("build.hwids", [["0x2341", "0x0070"]]) + vid = hwids[0][0] + pid = hwids[0][1] + + upload_actions = [env.VerboseAction("$UPLOADCMD", "Uploading $SOURCE")] + + env.Replace( + UPLOADER=join( + platform.get_package_dir("tool-dfuutil-arduino") or "", "dfu-util" + ), + UPLOADERFLAGS=[ + "-d", + ",".join(["%s:%s" % (hwid[0], hwid[1]) for hwid in hwids]), + "-Q", + "-D" + ], + UPLOADCMD='"$UPLOADER" $UPLOADERFLAGS "$SOURCE"', + ) + elif upload_protocol in debug_tools: openocd_args = ["-d%d" % (2 if int(ARGUMENTS.get("PIOVERBOSE", 0)) else 1)] @@ -533,6 +588,12 @@ def __fetch_fs_size(target, source, env): print("Warning! '-Wl,-T' option for specifying linker scripts is deprecated. " "Please use 'board_build.ldscript' option in your 'platformio.ini' file.") +# +# Override memory inspection behavior +# + +env.SConscript("sizedata.py", exports="env") + # # Default targets # diff --git a/builder/sizedata.py b/builder/sizedata.py new file mode 100644 index 000000000..e6e947627 --- /dev/null +++ b/builder/sizedata.py @@ -0,0 +1,26 @@ +import re + +Import("env") + + +def pioSizeIsRamSectionCustom(env, section): + if section and re.search( + r"\.dram0\.data|\.dram0\.bss|\.noinit", section.get("name", "") + ): + return True + + return False + + +def pioSizeIsFlashectionCustom(env, section): + if section and re.search( + r"\.iram0\.text|\.iram0\.vectors|\.dram0\.data|\.flash\.text|\.flash\.rodata|\.flash\.appdesc", + section.get("name", ""), + ): + return True + + return False + + +env.AddMethod(pioSizeIsRamSectionCustom, "pioSizeIsRamSection") +env.AddMethod(pioSizeIsFlashectionCustom, "pioSizeIsFlashSection") diff --git a/examples/arduino-blink/platformio.ini b/examples/arduino-blink/platformio.ini index 808c16f65..85e0fab00 100644 --- a/examples/arduino-blink/platformio.ini +++ b/examples/arduino-blink/platformio.ini @@ -34,9 +34,13 @@ framework = arduino board = lolin_c3_mini monitor_speed = 115200 - [env:esp32-s3-devkitc-1] platform = espressif32 framework = arduino board = esp32-s3-devkitc-1 monitor_speed = 115200 + +[env:arduino_nano_esp32] +platform = espressif32 +framework = arduino +board = arduino_nano_esp32 diff --git a/examples/espidf-hello-world/platformio.ini b/examples/espidf-hello-world/platformio.ini index 226510eb1..8347b1654 100644 --- a/examples/espidf-hello-world/platformio.ini +++ b/examples/espidf-hello-world/platformio.ini @@ -20,3 +20,6 @@ board = esp32-s2-kaluga-1 [env:esp32-c3-devkitm-1] board = esp32-c3-devkitm-1 + +[env:esp32-c6-devkitc-1] +board = esp32-c6-devkitc-1 diff --git a/examples/espidf-ulp-adc/main/ulp_adc_example_main.c b/examples/espidf-ulp-adc/main/ulp_adc_example_main.c index 6b3ff5648..882128329 100644 --- a/examples/espidf-ulp-adc/main/ulp_adc_example_main.c +++ b/examples/espidf-ulp-adc/main/ulp_adc_example_main.c @@ -9,17 +9,20 @@ #include #include +#include #include "esp_sleep.h" -#include "nvs.h" -#include "nvs_flash.h" #include "soc/rtc_cntl_reg.h" #include "soc/sens_reg.h" #include "driver/gpio.h" #include "driver/rtc_io.h" -#include "driver/dac.h" -#include "esp32/ulp.h" +#include "ulp.h" #include "ulp_main.h" #include "esp_adc/adc_oneshot.h" +#include "ulp/example_config.h" +#include "ulp_adc.h" + +#include "freertos/FreeRTOS.h" +#include "freertos/task.h" extern const uint8_t ulp_main_bin_start[] asm("_binary_ulp_main_bin_start"); extern const uint8_t ulp_main_bin_end[] asm("_binary_ulp_main_bin_end"); @@ -42,15 +45,21 @@ void app_main(void) init_ulp_program(); } else { printf("Deep sleep wakeup\n"); - printf("ULP did %d measurements since last reset\n", ulp_sample_counter & UINT16_MAX); - printf("Thresholds: low=%d high=%d\n", ulp_low_thr, ulp_high_thr); + printf("ULP did %"PRIu32" measurements since last reset\n", ulp_sample_counter & UINT16_MAX); + printf("Thresholds: low=%"PRIu32" high=%"PRIu32"\n", ulp_low_thr, ulp_high_thr); ulp_last_result &= UINT16_MAX; - printf("Value=%d was %s threshold\n", ulp_last_result, + printf("Value=%"PRIu32" was %s threshold\n", ulp_last_result, ulp_last_result < ulp_low_thr ? "below" : "above"); } printf("Entering deep sleep\n\n"); start_ulp_program(); ESP_ERROR_CHECK( esp_sleep_enable_ulp_wakeup() ); + +#if !CONFIG_IDF_TARGET_ESP32 + /* RTC peripheral power domain needs to be kept on to keep SAR ADC related configs during sleep */ + esp_sleep_pd_config(ESP_PD_DOMAIN_RTC_PERIPH, ESP_PD_OPTION_ON); +#endif + esp_deep_sleep_start(); } @@ -60,35 +69,31 @@ static void init_ulp_program(void) (ulp_main_bin_end - ulp_main_bin_start) / sizeof(uint32_t)); ESP_ERROR_CHECK(err); - //-------------ADC1 Init---------------// - adc_oneshot_unit_handle_t adc1_handle; - adc_oneshot_unit_init_cfg_t init_config1 = { - .unit_id = ADC_UNIT_1, + ulp_adc_cfg_t cfg = { + .adc_n = EXAMPLE_ADC_UNIT, + .channel = EXAMPLE_ADC_CHANNEL, + .width = EXAMPLE_ADC_WIDTH, + .atten = EXAMPLE_ADC_ATTEN, .ulp_mode = ADC_ULP_MODE_FSM, }; - ESP_ERROR_CHECK(adc_oneshot_new_unit(&init_config1, &adc1_handle)); - //-------------ADC1 Channel Config---------------// - // Note: when changing channel here, also change 'adc_channel' constant in adc.S - adc_oneshot_chan_cfg_t config = { - .bitwidth = ADC_BITWIDTH_DEFAULT, - .atten = ADC_ATTEN_DB_11, - }; - ESP_ERROR_CHECK(adc_oneshot_config_channel(adc1_handle, ADC_CHANNEL_6, &config)); + ESP_ERROR_CHECK(ulp_adc_init(&cfg)); - /* Set low and high thresholds, approx. 1.35V - 1.75V*/ - ulp_low_thr = 1500; - ulp_high_thr = 2000; + ulp_low_thr = EXAMPLE_ADC_LOW_TRESHOLD; + ulp_high_thr = EXAMPLE_ADC_HIGH_TRESHOLD; /* Set ULP wake up period to 20ms */ ulp_set_wakeup_period(0, 20000); +#if CONFIG_IDF_TARGET_ESP32 /* Disconnect GPIO12 and GPIO15 to remove current drain through - * pullup/pulldown resistors. + * pullup/pulldown resistors on modules which have these (e.g. ESP32-WROVER) * GPIO12 may be pulled high to select flash voltage. */ rtc_gpio_isolate(GPIO_NUM_12); rtc_gpio_isolate(GPIO_NUM_15); +#endif // CONFIG_IDF_TARGET_ESP32 + esp_deep_sleep_disable_rom_logging(); // suppress boot messages } diff --git a/examples/espidf-ulp-adc/ulp/adc.S b/examples/espidf-ulp-adc/ulp/adc.S index 1b59ccee7..b96f51c3b 100644 --- a/examples/espidf-ulp-adc/ulp/adc.S +++ b/examples/espidf-ulp-adc/ulp/adc.S @@ -1,3 +1,8 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ /* ULP Example: using ADC in deep sleep This example code is in the Public Domain (or CC0 licensed, at your option.) @@ -22,9 +27,9 @@ */ #include "soc/rtc_cntl_reg.h" #include "soc/soc_ulp.h" +#include "example_config.h" - /* ADC1 channel 6, GPIO34 */ - .set adc_channel, 6 + .set adc_channel, EXAMPLE_ADC_CHANNEL /* Configure the number of ADC samples to average on each measurement. For convenience, make it a power of 2. */ diff --git a/examples/espidf-ulp-adc/ulp/example_config.h b/examples/espidf-ulp-adc/ulp/example_config.h new file mode 100644 index 000000000..baa86dd84 --- /dev/null +++ b/examples/espidf-ulp-adc/ulp/example_config.h @@ -0,0 +1,16 @@ +/* + * SPDX-FileCopyrightText: 2022 Espressif Systems (Shanghai) CO LTD + * + * SPDX-License-Identifier: Unlicense OR CC0-1.0 + */ +#pragma once + +/* Ints are used here to be able to include the file in assembly as well */ +#define EXAMPLE_ADC_CHANNEL 6 // ADC_CHANNEL_6, GPIO34 on ESP32, GPIO7 on ESP32-S3 +#define EXAMPLE_ADC_UNIT 0 // ADC_UNIT_1 +#define EXAMPLE_ADC_ATTEN 3 // ADC_ATTEN_DB_11 +#define EXAMPLE_ADC_WIDTH 0 // ADC_BITWIDTH_DEFAULT + +/* Set low and high thresholds, approx. 1.35V - 1.75V*/ +#define EXAMPLE_ADC_LOW_TRESHOLD 1500 +#define EXAMPLE_ADC_HIGH_TRESHOLD 2000 diff --git a/monitor/filter_exception_decoder.py b/monitor/filter_exception_decoder.py index f3c680669..5a646e838 100644 --- a/monitor/filter_exception_decoder.py +++ b/monitor/filter_exception_decoder.py @@ -17,7 +17,7 @@ import subprocess import sys -from platformio.project.exception import PlatformioException +from platformio.exception import PlatformioException from platformio.public import ( DeviceMonitorFilterBase, load_build_metadata, diff --git a/platform.json b/platform.json index 818fffa79..5bf959b7b 100644 --- a/platform.json +++ b/platform.json @@ -18,7 +18,7 @@ "type": "git", "url": "https://github.com/platformio/platform-espressif32.git" }, - "version": "6.3.2", + "version": "6.4.0", "frameworks": { "arduino": { "package": "framework-arduinoespressif32", @@ -34,28 +34,28 @@ "type": "toolchain", "owner": "espressif", "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "optionalVersions": ["12.2.0+20230208"] }, "toolchain-xtensa-esp32s2": { "type": "toolchain", "optional": true, "owner": "espressif", "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "optionalVersions": ["12.2.0+20230208"] }, "toolchain-xtensa-esp32s3": { "type": "toolchain", "optional": true, "owner": "espressif", "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "optionalVersions": ["12.2.0+20230208"] }, "toolchain-riscv32-esp": { "type": "toolchain", "optional": true, "owner": "espressif", "version": "8.4.0+2021r2-patch5", - "optionalVersions": ["11.2.0+2022r1"] + "optionalVersions": ["12.2.0+20230208"] }, "toolchain-esp32ulp": { "type": "toolchain", @@ -63,11 +63,23 @@ "owner": "platformio", "version": "~1.23500.0" }, + "tool-xtensa-esp-elf-gdb": { + "type": "debugger", + "optional": true, + "owner": "espressif", + "version": "~12.1.0" + }, + "tool-riscv32-esp-elf-gdb": { + "type": "debugger", + "optional": true, + "owner": "espressif", + "version": "~12.1.0" + }, "framework-arduinoespressif32": { "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.20009.0" + "version": "~3.20011.0" }, "framework-arduino-mbcwb": { "type": "framework", @@ -79,8 +91,8 @@ "type": "framework", "optional": true, "owner": "platformio", - "version": "~3.50002.0", - "optionalVersions": ["~3.40404.0"] + "version": "~3.50101.0", + "optionalVersions": ["~3.40405.0"] }, "tool-esptoolpy": { "type": "uploader", @@ -92,6 +104,12 @@ "owner": "meteca", "version": ">=2.0.0" }, + "tool-dfuutil-arduino": { + "type": "uploader", + "optional": true, + "owner": "platformio", + "version": "~1.11.0" + }, "tool-openocd-esp32": { "type": "debugger", "optional": true, diff --git a/platform.py b/platform.py index 516fed44b..dfdb7c785 100644 --- a/platform.py +++ b/platform.py @@ -17,7 +17,6 @@ import sys import json import re -import requests from platformio.public import PlatformBase, to_unix_path @@ -47,11 +46,17 @@ def configure_default_packages(self, variables, targets): if os.path.isdir("ulp"): self.packages["toolchain-esp32ulp"]["optional"] = False + # Currently only Arduino Nano ESP32 uses the dfuutil tool as uploader + if variables.get("board") == "arduino_nano_esp32": + self.packages["tool-dfuutil-arduino"]["optional"] = False + else: + del self.packages["tool-dfuutil-arduino"] + build_core = variables.get( "board_build.core", board_config.get("build.core", "arduino") ).lower() - if len(frameworks) == 1 and "arduino" in frameworks and build_core == "esp32": + if frameworks == ["arduino"] and build_core == "esp32": # In case the upstream Arduino framework is specified in the configuration # file then we need to dynamically extract toolchain versions from the # Arduino index file. This feature can be disabled via a special option: @@ -88,6 +93,17 @@ def configure_default_packages(self, variables, targets): sys.exit(1) if "espidf" in frameworks: + if frameworks == ["espidf"]: + # Starting from v12, Espressif's toolchains are shipped without + # bundled GDB. Instead, it's distributed as separate packages for Xtensa + # and RISC-V targets. Currently only IDF depends on the latest toolchain + for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): + self.packages[gdb_package]["optional"] = False + if IS_WINDOWS: + # Note: On Windows GDB v12 is not able to + # launch a GDB server in pipe mode while v11 works fine + self.packages[gdb_package]["version"] = "~11.2.0" + # Common packages for IDF and mixed Arduino+IDF projects for p in self.packages: if p in ("tool-cmake", "tool-ninja", "toolchain-esp32ulp"): @@ -97,7 +113,7 @@ def configure_default_packages(self, variables, targets): if "arduino" in frameworks: # Downgrade the IDF version for mixed Arduino+IDF projects - self.packages["framework-espidf"]["version"] = "~3.40404.0" + self.packages["framework-espidf"]["version"] = "~3.40405.0" else: # Use the latest toolchains available for IDF v5.0 for target in ( @@ -106,7 +122,12 @@ def configure_default_packages(self, variables, targets): "xtensa-esp32s3", "riscv32-esp" ): - self.packages["toolchain-%s" % target]["version"] = "11.2.0+2022r1" + self.packages["toolchain-%s" % target]["version"] = "12.2.0+20230208" + + if "arduino" in frameworks: + # Disable standalone GDB packages for Arduino and Arduino/IDF projects + for gdb_package in ("tool-xtensa-esp-elf-gdb", "tool-riscv32-esp-elf-gdb"): + self.packages.pop(gdb_package, None) for available_mcu in ("esp32", "esp32s2", "esp32s3"): if available_mcu == mcu: @@ -114,8 +135,8 @@ def configure_default_packages(self, variables, targets): else: self.packages.pop("toolchain-xtensa-%s" % available_mcu, None) - if mcu in ("esp32s2", "esp32s3", "esp32c3"): - # RISC-V based toolchain for ESP32C3, ESP32S2, ESP32S3 ULP + if mcu in ("esp32s2", "esp32s3", "esp32c3", "esp32c6"): + # RISC-V based toolchain for ESP32C3, ESP32C6 ESP32S2, ESP32S3 ULP self.packages["toolchain-riscv32-esp"]["optional"] = False if build_core == "mbcwb": @@ -178,7 +199,7 @@ def _add_dynamic_options(self, board): "tumpa", ] - if board.get("build.mcu", "") in ("esp32c3", "esp32s3"): + if board.get("build.mcu", "") in ("esp32c3", "esp32c6", "esp32s3"): supported_debug_tools.append("esp-builtin") upload_protocol = board.manifest.get("upload", {}).get("protocol") @@ -248,6 +269,10 @@ def _add_dynamic_options(self, board): "default": link == debug.get("default_tool"), } + # Avoid erasing Arduino Nano bootloader by preloading app binary + if board.id == "arduino_nano_esp32": + debug["tools"][link]["load_cmds"] = "preload" + board.manifest["debug"] = debug return board @@ -349,16 +374,15 @@ def _prepare_url_for_index_file(url_items): ) index_file_url = _prepare_url_for_index_file(url_items) - r = requests.get(index_file_url, timeout=10) - if r.status_code != 200: - raise ValueError( - ( - "Failed to download package index file due to a bad response (%d) " - "from the remote `%s`" - ) - % (r.status_code, index_file_url) - ) - return r.json() + + try: + from platformio.public import fetch_http_content + content = fetch_http_content(index_file_url) + except ImportError: + import requests + content = requests.get(index_file_url, timeout=5).text + + return json.loads(content) def configure_arduino_toolchains(self, package_index): if not package_index: