[esp32] Add flash_mode and flash_frequency config options (#16920)

Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com>
This commit is contained in:
Jonathan Swoboda
2026-06-14 18:56:18 -04:00
committed by GitHub
parent e191fc5d47
commit efebea3296
4 changed files with 66 additions and 0 deletions

View File

@@ -1615,8 +1615,14 @@ FLASH_SIZES = [
]
CONF_FLASH_SIZE = "flash_size"
CONF_FLASH_MODE = "flash_mode"
CONF_FLASH_FREQUENCY = "flash_frequency"
CONF_CPU_FREQUENCY = "cpu_frequency"
CONF_PARTITIONS = "partitions"
FLASH_MODES = ["qio", "qout", "dio", "dout", "opi"]
FLASH_FREQUENCIES = [
f"{freq}MHZ" for freq in (120, 80, 64, 60, 48, 40, 32, 30, 26, 24, 20, 16)
]
CONFIG_SCHEMA = cv.All(
cv.Schema(
{
@@ -1630,6 +1636,10 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_FLASH_SIZE, default="4MB"): cv.one_of(
*FLASH_SIZES, upper=True
),
cv.Optional(CONF_FLASH_MODE): cv.one_of(*FLASH_MODES, lower=True),
cv.Optional(CONF_FLASH_FREQUENCY): cv.one_of(
*FLASH_FREQUENCIES, upper=True
),
cv.Optional(CONF_PARTITIONS): cv.Any(
cv.file_,
cv.ensure_list(
@@ -1866,6 +1876,12 @@ async def to_code(config):
"board_upload.maximum_size",
int(config[CONF_FLASH_SIZE].removesuffix("MB")) * 1024 * 1024,
)
if flash_mode := config.get(CONF_FLASH_MODE):
cg.add_platformio_option("board_build.flash_mode", flash_mode)
if flash_frequency := config.get(CONF_FLASH_FREQUENCY):
cg.add_platformio_option(
"board_build.f_flash", f"{flash_frequency[:-3]}000000L"
)
if CONF_SOURCE in conf:
cg.add_platformio_option("platform_packages", [conf[CONF_SOURCE]])
@@ -2016,6 +2032,14 @@ async def to_code(config):
add_idf_sdkconfig_option(
f"CONFIG_ESPTOOLPY_FLASHSIZE_{config[CONF_FLASH_SIZE]}", True
)
if flash_mode := config.get(CONF_FLASH_MODE):
add_idf_sdkconfig_option(
f"CONFIG_ESPTOOLPY_FLASHMODE_{flash_mode.upper()}", True
)
if flash_frequency := config.get(CONF_FLASH_FREQUENCY):
add_idf_sdkconfig_option(
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

View File

@@ -0,0 +1,7 @@
esphome:
name: test
esp32:
board: esp32dev
framework:
type: esp-idf

View File

@@ -0,0 +1,9 @@
esphome:
name: test
esp32:
board: esp32dev
flash_mode: qio
flash_frequency: 80MHz
framework:
type: esp-idf

View File

@@ -285,3 +285,29 @@ def test_native_idf_enables_reproducible_build(
sdkconfig = CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS]
assert sdkconfig.get("CONFIG_APP_REPRODUCIBLE_BUILD") is True
def test_flash_mode_sets_sdkconfig_and_pio_option(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""flash_mode/flash_frequency select the esptool flash parameters on both backends."""
generate_main(component_config_path("flash_mode_idf.yaml"))
sdkconfig = CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS]
assert sdkconfig.get("CONFIG_ESPTOOLPY_FLASHMODE_QIO") is True
assert sdkconfig.get("CONFIG_ESPTOOLPY_FLASHFREQ_80M") is True
assert CORE.platformio_options.get("board_build.flash_mode") == "qio"
assert CORE.platformio_options.get("board_build.f_flash") == "80000000L"
def test_flash_mode_unset_leaves_defaults(
generate_main: Callable[[str | Path], str],
component_config_path: Callable[[str], Path],
) -> None:
"""Without flash_mode the board/sdkconfig defaults stay untouched."""
generate_main(component_config_path("flash_mode_default.yaml"))
sdkconfig = CORE.data[KEY_ESP32][KEY_SDKCONFIG_OPTIONS]
assert not any(key.startswith("CONFIG_ESPTOOLPY_FLASHMODE_") for key in sdkconfig)
assert not any(key.startswith("CONFIG_ESPTOOLPY_FLASHFREQ_") for key in sdkconfig)
assert "board_build.flash_mode" not in CORE.platformio_options
assert "board_build.f_flash" not in CORE.platformio_options