diff --git a/esphome/components/esp32/__init__.py b/esphome/components/esp32/__init__.py index b6682100f7..06677006ea 100644 --- a/esphome/components/esp32/__init__.py +++ b/esphome/components/esp32/__init__.py @@ -87,6 +87,7 @@ IS_TARGET_PLATFORM = True CONF_ASSERTION_LEVEL = "assertion_level" CONF_COMPILER_OPTIMIZATION = "compiler_optimization" CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES = "enable_idf_experimental_features" +CONF_ENGINEERING_SAMPLE = "engineering_sample" CONF_INCLUDE_BUILTIN_IDF_COMPONENTS = "include_builtin_idf_components" CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert" CONF_ENABLE_OTA_ROLLBACK = "enable_ota_rollback" @@ -785,6 +786,15 @@ def _detect_variant(value): # variant has already been validated against the known set value = value.copy() value[CONF_BOARD] = STANDARD_BOARDS[variant] + if variant == VARIANT_ESP32P4: + engineering_sample = value.get(CONF_ENGINEERING_SAMPLE) + if engineering_sample is None: + _LOGGER.warning( + "No board specified for ESP32-P4. Defaulting to production silicon (rev3). " + "If you have an early engineering sample (pre-rev3), set 'engineering_sample: true'." + ) + elif engineering_sample: + value[CONF_BOARD] = "esp32-p4-evboard" elif board in BOARDS: variant = variant or BOARDS[board][KEY_VARIANT] if variant != BOARDS[board][KEY_VARIANT]: @@ -848,6 +858,30 @@ def final_validate(config): path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_MINIMUM_CHIP_REVISION], ) ) + if ( + config[CONF_VARIANT] != VARIANT_ESP32P4 + and config.get(CONF_ENGINEERING_SAMPLE) is not None + ): + errs.append( + cv.Invalid( + f"'{CONF_ENGINEERING_SAMPLE}' is only supported on {VARIANT_ESP32P4}", + path=[CONF_ENGINEERING_SAMPLE], + ) + ) + if ( + config[CONF_VARIANT] == VARIANT_ESP32P4 + and config.get(CONF_ENGINEERING_SAMPLE) is not None + ): + board_is_es = BOARDS.get(config[CONF_BOARD], {}).get( + "engineering_sample", False + ) + if config[CONF_ENGINEERING_SAMPLE] != board_is_es: + errs.append( + cv.Invalid( + f"'{CONF_ENGINEERING_SAMPLE}' does not match board '{config[CONF_BOARD]}'", + path=[CONF_ENGINEERING_SAMPLE], + ) + ) if advanced[CONF_EXECUTE_FROM_PSRAM]: if config[CONF_VARIANT] != VARIANT_ESP32S3: errs.append( @@ -1197,6 +1231,7 @@ CONFIG_SCHEMA = cv.All( cv.Optional(CONF_CPU_FREQUENCY): cv.one_of( *FULL_CPU_FREQUENCIES, upper=True ), + cv.Optional(CONF_ENGINEERING_SAMPLE): cv.boolean, cv.Optional(CONF_FLASH_SIZE, default="4MB"): cv.one_of( *FLASH_SIZES, upper=True ), @@ -1482,10 +1517,12 @@ async def to_code(config): # ESP32-P4: ESP-IDF 5.5.3 changed the default of ESP32P4_SELECTS_REV_LESS_V3 # from y to n. PlatformIO uses sections.ld.in (for rev <3) or # sections.rev3.ld.in (for rev >=3) based on board definition. - # Set the sdkconfig option to match the board's revision. + # Set the sdkconfig option to match the board's chip revision. if variant == VARIANT_ESP32P4: - is_rev3 = "_r3" in config[CONF_BOARD] - add_idf_sdkconfig_option("CONFIG_ESP32P4_SELECTS_REV_LESS_V3", not is_rev3) + is_eng_sample = BOARDS.get(config[CONF_BOARD], {}).get( + "engineering_sample", False + ) + add_idf_sdkconfig_option("CONFIG_ESP32P4_SELECTS_REV_LESS_V3", is_eng_sample) # Set minimum chip revision for ESP32 variant # Setting this to 3.0 or higher reduces flash size by excluding workaround code, diff --git a/esphome/components/esp32/boards.py b/esphome/components/esp32/boards.py index 66367d63ae..2bd08e7c39 100644 --- a/esphome/components/esp32/boards.py +++ b/esphome/components/esp32/boards.py @@ -20,7 +20,7 @@ STANDARD_BOARDS = { VARIANT_ESP32C6: "esp32-c6-devkitm-1", VARIANT_ESP32C61: "esp32-c61-devkitc1-n8r2", VARIANT_ESP32H2: "esp32-h2-devkitm-1", - VARIANT_ESP32P4: "esp32-p4-evboard", + VARIANT_ESP32P4: "esp32-p4_r3-evboard", VARIANT_ESP32S2: "esp32-s2-kaluga-1", VARIANT_ESP32S3: "esp32-s3-devkitc-1", } @@ -1713,10 +1713,12 @@ BOARDS = { "esp32-p4": { "name": "Espressif ESP32-P4 ES (pre rev.300) generic", "variant": VARIANT_ESP32P4, + "engineering_sample": True, }, "esp32-p4-evboard": { "name": "Espressif ESP32-P4 Function EV Board (ES pre rev.300)", "variant": VARIANT_ESP32P4, + "engineering_sample": True, }, "esp32-p4_r3": { "name": "Espressif ESP32-P4 rev.300 generic", @@ -2141,6 +2143,7 @@ BOARDS = { "m5stack-tab5-p4": { "name": "M5STACK Tab5 esp32-p4 Board (ES pre rev.300)", "variant": VARIANT_ESP32P4, + "engineering_sample": True, }, "m5stack-timer-cam": { "name": "M5Stack Timer CAM", diff --git a/script/generate-esp32-boards.py b/script/generate-esp32-boards.py index 81b78b04be..ab4a38ced5 100755 --- a/script/generate-esp32-boards.py +++ b/script/generate-esp32-boards.py @@ -43,10 +43,14 @@ def get_boards(): name = board_info["name"] board = fname.stem variant = mcu.upper() - boards[board] = { + chip_variant = board_info["build"].get("chip_variant", "") + entry = { "name": name, "variant": f"VARIANT_{variant}", } + if chip_variant.endswith("_es"): + entry["engineering_sample"] = True + boards[board] = entry return boards @@ -55,6 +59,12 @@ TEMPLATE = """ "%s": { "variant": %s, },""" +TEMPLATE_ES = """ "%s": { + "name": "%s", + "variant": %s, + "engineering_sample": True, + },""" + def main(check: bool): boards = get_boards() @@ -66,7 +76,8 @@ def main(check: bool): if line == "BOARDS = {": parts.append(line) parts.extend( - TEMPLATE % (board, info["name"], info["variant"]) + (TEMPLATE_ES if info.get("engineering_sample") else TEMPLATE) + % (board, info["name"], info["variant"]) for board, info in sorted(boards.items()) ) parts.append("}") diff --git a/tests/components/esp32/test.esp32-p4-idf.yaml b/tests/components/esp32/test.esp32-p4-idf.yaml index bc054f5aee..fd42fac5a3 100644 --- a/tests/components/esp32/test.esp32-p4-idf.yaml +++ b/tests/components/esp32/test.esp32-p4-idf.yaml @@ -1,5 +1,6 @@ esp32: variant: esp32p4 + engineering_sample: true flash_size: 32MB cpu_frequency: 400MHz framework: