[esp32] Add sram1_as_iram option for +40KB IRAM on original ESP32

Add a new `sram1_as_iram` option under `esp32 > framework > advanced`
that enables CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM, reclaiming
40KB of SRAM1 memory as additional IRAM on the original ESP32.

This requires a bootloader from ESP-IDF v5.1 or later. USB flashing
updates the bootloader automatically, but OTA does not. At boot,
ESPHome now detects the bootloader version and suggests enabling
this option when the bootloader is compatible.
This commit is contained in:
J. Nick Koston
2026-03-16 14:54:20 -10:00
parent 2142bc1b76
commit d7dc641fcb
3 changed files with 46 additions and 4 deletions
+19
View File
@@ -96,6 +96,7 @@ CONF_ENABLE_LWIP_ASSERT = "enable_lwip_assert"
CONF_EXECUTE_FROM_PSRAM = "execute_from_psram"
CONF_MINIMUM_CHIP_REVISION = "minimum_chip_revision"
CONF_RELEASE = "release"
CONF_SRAM1_AS_IRAM = "sram1_as_iram"
ARDUINO_FRAMEWORK_NAME = "framework-arduinoespressif32"
ARDUINO_FRAMEWORK_PKG = f"pioarduino/{ARDUINO_FRAMEWORK_NAME}"
@@ -882,6 +883,13 @@ def final_validate(config):
path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_MINIMUM_CHIP_REVISION],
)
)
if config[CONF_VARIANT] != VARIANT_ESP32 and advanced[CONF_SRAM1_AS_IRAM]:
errs.append(
cv.Invalid(
f"'{CONF_SRAM1_AS_IRAM}' is only supported on {VARIANT_ESP32}",
path=[CONF_FRAMEWORK, CONF_ADVANCED, CONF_SRAM1_AS_IRAM],
)
)
if (
config[CONF_VARIANT] != VARIANT_ESP32P4
and config.get(CONF_ENGINEERING_SAMPLE) is not None
@@ -1129,6 +1137,7 @@ FRAMEWORK_SCHEMA = cv.Schema(
cv.Optional(CONF_MINIMUM_CHIP_REVISION): cv.one_of(
*ESP32_CHIP_REVISIONS
),
cv.Optional(CONF_SRAM1_AS_IRAM, default=False): cv.boolean,
# DHCP server is needed for WiFi AP mode. When WiFi component is used,
# it will handle disabling DHCP server when AP is not configured.
# Default to false (disabled) when WiFi is not used.
@@ -1595,6 +1604,16 @@ async def to_code(config):
for rev, flag in ESP32_CHIP_REVISIONS.items():
add_idf_sdkconfig_option(flag, rev == min_rev)
cg.add_define("USE_ESP32_MIN_CHIP_REVISION_SET")
# Use SRAM1 region as IRAM on ESP32 (original) variant
# This provides an additional 40KB of IRAM by using SRAM1 memory that was previously
# reserved for bootloader DRAM. Requires a bootloader from ESP-IDF v5.1 or later.
# WARNING: If the device has an old bootloader (pre-v5.1), the app will fail to boot.
# A USB flash will update the bootloader automatically. OTA updates do not.
# See: https://docs.espressif.com/projects/esp-idf/en/stable/esp32/api-guides/performance/ram-usage.html
if variant == VARIANT_ESP32 and conf[CONF_ADVANCED][CONF_SRAM1_AS_IRAM]:
add_idf_sdkconfig_option("CONFIG_ESP_SYSTEM_ESP32_SRAM1_REGION_AS_IRAM", True)
cg.add_define("USE_ESP32_SRAM1_AS_IRAM")
add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_SINGLE_APP", False)
add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM", True)
add_idf_sdkconfig_option("CONFIG_PARTITION_TABLE_CUSTOM_FILENAME", "partitions.csv")
+26 -4
View File
@@ -9,6 +9,13 @@
#endif
#ifdef USE_ESP32
#include <esp_chip_info.h>
#if defined(USE_ESP32_FRAMEWORK_ESP_IDF)
#include <esp_idf_version.h>
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
#include <esp_ota_ops.h>
#include <esp_bootloader_desc.h>
#endif
#endif
#endif
#ifdef USE_LWIP_FAST_SELECT
#include "esphome/core/lwip_fast_select.h"
@@ -237,18 +244,33 @@ void Application::process_dump_config_() {
esp_chip_info(&chip_info);
ESP_LOGI(TAG, "ESP32 Chip: %s rev%d.%d, %d core(s)", ESPHOME_VARIANT, chip_info.revision / 100,
chip_info.revision % 100, chip_info.cores);
static const char *const ESP32_ADVANCED_PATH = "under esp32 > framework > advanced";
#if defined(USE_ESP32_VARIANT_ESP32) && !defined(USE_ESP32_MIN_CHIP_REVISION_SET)
// Suggest optimization for chips that don't need the PSRAM cache workaround
if (chip_info.revision >= 300) {
#ifdef USE_PSRAM
ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to save ~10KB IRAM", chip_info.revision / 100,
chip_info.revision % 100);
ESP_LOGW(TAG, "Chip rev >= 3.0 detected. Set minimum_chip_revision: \"%d.%d\" %s to save ~10KB IRAM",
chip_info.revision / 100, chip_info.revision % 100, ESP32_ADVANCED_PATH);
#else
ESP_LOGW(TAG, "Set minimum_chip_revision: \"%d.%d\" to reduce binary size", chip_info.revision / 100,
chip_info.revision % 100);
ESP_LOGW(TAG, "Chip rev >= 3.0 detected. Set minimum_chip_revision: \"%d.%d\" %s to reduce binary size",
chip_info.revision / 100, chip_info.revision % 100, ESP32_ADVANCED_PATH);
#endif
}
#endif
#if defined(USE_ESP32_VARIANT_ESP32) && defined(USE_ESP32_FRAMEWORK_ESP_IDF) && !defined(USE_ESP32_SRAM1_AS_IRAM) && \
ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(5, 2, 0)
{
// Check if bootloader supports SRAM1 as IRAM (requires ESP-IDF >= 5.1 bootloader)
// esp_bootloader_desc_t is only available in ESP-IDF >= 5.2, but any bootloader
// from 5.2+ also supports SRAM1 as IRAM (which was introduced in 5.1)
esp_bootloader_desc_t boot_desc;
if (esp_ota_get_bootloader_description(nullptr, &boot_desc) == ESP_OK) {
ESP_LOGW(TAG, "Bootloader supports SRAM1 as IRAM (+40KB). Set sram1_as_iram: true %s", ESP32_ADVANCED_PATH);
} else {
ESP_LOGW(TAG, "Bootloader too old for SRAM1 as IRAM (+40KB). Flash via USB once to update the bootloader");
}
}
#endif
#endif
}
+1
View File
@@ -200,6 +200,7 @@
#define USE_ESPHOME_TASK_LOG_BUFFER
#define USE_OTA_ROLLBACK
#define USE_ESP32_MIN_CHIP_REVISION_SET
#define USE_ESP32_SRAM1_AS_IRAM
#define USE_BLUETOOTH_PROXY
#define BLUETOOTH_PROXY_MAX_CONNECTIONS 3