[esp32] Fix ESP32-P4 bootloop on rev3 (v3.x) chips when only variant is set (#18500)

This commit is contained in:
Jonathan Swoboda
2026-08-18 21:25:09 -04:00
committed by GitHub
parent 8b637b339b
commit 8aa7db15e5
+41 -37
View File
@@ -1073,6 +1073,26 @@ def _parse_pio_platform_version(value):
return value
def _normalize_p4_engineering_sample(value: ConfigType) -> bool:
"""Fill in CONF_ENGINEERING_SAMPLE when unset, warning that production
silicon (rev3) is assumed. Returns the normalized flag."""
if (engineering_sample := value.get(CONF_ENGINEERING_SAMPLE)) is None:
_LOGGER.warning(
"Defaulting to ESP32-P4 production silicon (rev3).\n"
"If you have an early engineering sample (pre-rev3), add this to your config:\n"
"\n"
" esp32:\n"
" engineering_sample: true\n"
"\n"
"To check your chip revision, look for 'chip revision: vX.Y' in the boot log.\n"
"Engineering samples will show a revision below v3.0.\n"
"The 'debug:' component also reports the revision (e.g. Revision: 100 = v1.0, 300 = v3.0)."
)
engineering_sample = False
value[CONF_ENGINEERING_SAMPLE] = engineering_sample
return engineering_sample
def _detect_variant(value):
board = value.get(CONF_BOARD)
variant = value.get(CONF_VARIANT)
@@ -1085,6 +1105,8 @@ def _detect_variant(value):
# name rather than carrying a PIO board name through the IDF build.
if CORE.using_toolchain_esp_idf:
value = value.copy()
if variant == VARIANT_ESP32P4:
_normalize_p4_engineering_sample(value)
value[CONF_BOARD] = VARIANT_FRIENDLY[variant].lower()
return value
if variant not in STANDARD_BOARDS:
@@ -1095,22 +1117,8 @@ def _detect_variant(value):
)
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).\n"
"If you have an early engineering sample (pre-rev3), add this to your config:\n"
"\n"
" esp32:\n"
" engineering_sample: true\n"
"\n"
"To check your chip revision, look for 'chip revision: vX.Y' in the boot log.\n"
"Engineering samples will show a revision below v3.0.\n"
"The 'debug:' component also reports the revision (e.g. Revision: 100 = v1.0, 300 = v3.0)."
)
elif engineering_sample:
value[CONF_BOARD] = "esp32-p4-evboard"
if variant == VARIANT_ESP32P4 and _normalize_p4_engineering_sample(value):
value[CONF_BOARD] = "esp32-p4-evboard"
elif board in BOARDS:
variant = variant or BOARDS[board][KEY_VARIANT]
if variant != BOARDS[board][KEY_VARIANT]:
@@ -1120,6 +1128,14 @@ def _detect_variant(value):
)
value = value.copy()
value[CONF_VARIANT] = variant
if variant == VARIANT_ESP32P4:
board_is_es = BOARDS[board].get("engineering_sample", False)
engineering_sample = value.setdefault(CONF_ENGINEERING_SAMPLE, board_is_es)
if engineering_sample != board_is_es:
raise cv.Invalid(
f"'{CONF_ENGINEERING_SAMPLE}' does not match board '{board}'",
path=[CONF_ENGINEERING_SAMPLE],
)
elif not variant:
raise cv.Invalid(
"This board is unknown, if you are sure you want to compile with this board selection, "
@@ -1131,6 +1147,9 @@ def _detect_variant(value):
"This board is unknown; the specified variant '%s' will be used but this may not work as expected.",
variant,
)
if variant == VARIANT_ESP32P4:
value = value.copy()
_normalize_p4_engineering_sample(value)
return value
@@ -1434,20 +1453,6 @@ def final_validate(config) -> None:
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] not in {VARIANT_ESP32S3, VARIANT_ESP32P4}:
errs.append(
@@ -2518,15 +2523,14 @@ async def to_code(config):
f"CONFIG_ESPTOOLPY_FLASHFREQ_{flash_frequency[:-3]}M", True
)
# 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 chip revision.
# ESP32-P4: pre-v3 and rev3 (v3.0+) silicon are not binary compatible.
# CONFIG_ESP32P4_SELECTS_REV_LESS_V3 selects which layout ESP-IDF links;
# validation normalizes CONF_ENGINEERING_SAMPLE from the board when unset.
if variant == VARIANT_ESP32P4:
is_eng_sample = BOARDS.get(config[CONF_BOARD], {}).get(
"engineering_sample", False
add_idf_sdkconfig_option(
"CONFIG_ESP32P4_SELECTS_REV_LESS_V3",
config.get(CONF_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,