1
0
mirror of https://github.com/esphome/esphome.git synced 2025-04-08 03:40:28 +01:00

[psram] Allow use of experimental 120MHz octal mode (#8519)

This commit is contained in:
Clyde Stubbs 2025-04-07 22:49:40 +10:00 committed by GitHub
parent 9637ef35bd
commit 23dec912ad
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
8 changed files with 98 additions and 17 deletions

View File

@ -67,6 +67,7 @@ AUTO_LOAD = ["preferences"]
IS_TARGET_PLATFORM = True IS_TARGET_PLATFORM = True
CONF_RELEASE = "release" CONF_RELEASE = "release"
CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES = "enable_idf_experimental_features"
def set_core_data(config): def set_core_data(config):
@ -506,6 +507,7 @@ ESP_IDF_FRAMEWORK_SCHEMA = cv.All(
CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False CONF_IGNORE_EFUSE_CUSTOM_MAC, default=False
): cv.boolean, ): cv.boolean,
cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC): cv.boolean, cv.Optional(CONF_IGNORE_EFUSE_MAC_CRC): cv.boolean,
cv.Optional(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES): cv.boolean,
} }
), ),
cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list( cv.Optional(CONF_COMPONENTS, default=[]): cv.ensure_list(
@ -645,6 +647,11 @@ async def to_code(config):
add_idf_sdkconfig_option( add_idf_sdkconfig_option(
"CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE", False "CONFIG_ESP32_PHY_CALIBRATION_AND_DATA_STORAGE", False
) )
if conf[CONF_ADVANCED].get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES):
_LOGGER.warning(
"Using experimental features in ESP-IDF may result in unexpected failures."
)
add_idf_sdkconfig_option("CONFIG_IDF_EXPERIMENTAL_FEATURES", True)
cg.add_define( cg.add_define(
"USE_ESP_IDF_VERSION_CODE", "USE_ESP_IDF_VERSION_CODE",

View File

@ -1,17 +1,40 @@
import logging
import esphome.codegen as cg import esphome.codegen as cg
from esphome.components.esp32 import add_idf_sdkconfig_option, get_esp32_variant from esphome.components.esp32 import (
CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES,
VARIANT_ESP32,
add_idf_sdkconfig_option,
get_esp32_variant,
only_on_variant,
)
from esphome.components.esp32.const import VARIANT_ESP32S2, VARIANT_ESP32S3
import esphome.config_validation as cv import esphome.config_validation as cv
from esphome.const import CONF_ID, CONF_MODE, CONF_SPEED from esphome.const import (
CONF_ADVANCED,
CONF_FRAMEWORK,
CONF_ID,
CONF_MODE,
CONF_SPEED,
PLATFORM_ESP32,
)
from esphome.core import CORE from esphome.core import CORE
import esphome.final_validate as fv
CODEOWNERS = ["@esphome/core"] CODEOWNERS = ["@esphome/core"]
DEPENDENCIES = [PLATFORM_ESP32]
_LOGGER = logging.getLogger(__name__)
psram_ns = cg.esphome_ns.namespace("psram") psram_ns = cg.esphome_ns.namespace("psram")
PsramComponent = psram_ns.class_("PsramComponent", cg.Component) PsramComponent = psram_ns.class_("PsramComponent", cg.Component)
TYPE_QUAD = "quad" TYPE_QUAD = "quad"
TYPE_OCTAL = "octal" TYPE_OCTAL = "octal"
CONF_ENABLE_ECC = "enable_ecc"
SPIRAM_MODES = { SPIRAM_MODES = {
TYPE_QUAD: "CONFIG_SPIRAM_MODE_QUAD", TYPE_QUAD: "CONFIG_SPIRAM_MODE_QUAD",
TYPE_OCTAL: "CONFIG_SPIRAM_MODE_OCT", TYPE_OCTAL: "CONFIG_SPIRAM_MODE_OCT",
@ -26,7 +49,25 @@ SPIRAM_SPEEDS = {
def validate_psram_mode(config): def validate_psram_mode(config):
if config[CONF_MODE] == TYPE_OCTAL and config[CONF_SPEED] == 120e6: if config[CONF_MODE] == TYPE_OCTAL and config[CONF_SPEED] == 120e6:
raise cv.Invalid("PSRAM 120MHz is not supported in octal mode") esp32_config = fv.full_config.get()[PLATFORM_ESP32]
if (
esp32_config[CONF_FRAMEWORK]
.get(CONF_ADVANCED, {})
.get(CONF_ENABLE_IDF_EXPERIMENTAL_FEATURES)
):
_LOGGER.warning(
"120MHz PSRAM in octal mode is an experimental feature - use at your own risk"
)
else:
raise cv.Invalid("PSRAM 120MHz is not supported in octal mode")
if config[CONF_MODE] != TYPE_OCTAL and config[CONF_ENABLE_ECC]:
raise cv.Invalid("ECC is only available in octal mode.")
if config[CONF_MODE] == TYPE_OCTAL:
variant = get_esp32_variant()
if variant != VARIANT_ESP32S3:
raise cv.Invalid(
f"Octal PSRAM is only supported on ESP32-S3, not {variant}"
)
return config return config
@ -37,19 +78,25 @@ CONFIG_SCHEMA = cv.All(
cv.Optional(CONF_MODE, default=TYPE_QUAD): cv.enum( cv.Optional(CONF_MODE, default=TYPE_QUAD): cv.enum(
SPIRAM_MODES, lower=True SPIRAM_MODES, lower=True
), ),
cv.Optional(CONF_ENABLE_ECC, default=False): cv.boolean,
cv.Optional(CONF_SPEED, default=40e6): cv.All( cv.Optional(CONF_SPEED, default=40e6): cv.All(
cv.frequency, cv.one_of(*SPIRAM_SPEEDS) cv.frequency, cv.one_of(*SPIRAM_SPEEDS)
), ),
} }
), ),
cv.only_on_esp32, only_on_variant(
validate_psram_mode, supported=[VARIANT_ESP32, VARIANT_ESP32S3, VARIANT_ESP32S2],
),
) )
FINAL_VALIDATE_SCHEMA = validate_psram_mode
async def to_code(config): async def to_code(config):
if CORE.using_arduino: if CORE.using_arduino:
cg.add_build_flag("-DBOARD_HAS_PSRAM") cg.add_build_flag("-DBOARD_HAS_PSRAM")
if config[CONF_MODE] == TYPE_OCTAL:
cg.add_platformio_option("board_build.arduino.memory_type", "qio_opi")
if CORE.using_esp_idf: if CORE.using_esp_idf:
add_idf_sdkconfig_option( add_idf_sdkconfig_option(
@ -62,6 +109,14 @@ async def to_code(config):
add_idf_sdkconfig_option(f"{SPIRAM_MODES[config[CONF_MODE]]}", True) add_idf_sdkconfig_option(f"{SPIRAM_MODES[config[CONF_MODE]]}", True)
add_idf_sdkconfig_option(f"{SPIRAM_SPEEDS[config[CONF_SPEED]]}", True) add_idf_sdkconfig_option(f"{SPIRAM_SPEEDS[config[CONF_SPEED]]}", True)
if config[CONF_MODE] == TYPE_OCTAL and config[CONF_SPEED] == 120e6:
add_idf_sdkconfig_option("CONFIG_ESP32S3_DEFAULT_CPU_FREQ_240", True)
# This works only on IDF 5.4.x but does no harm on earlier versions
add_idf_sdkconfig_option(
"CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True
)
if config[CONF_ENABLE_ECC]:
add_idf_sdkconfig_option("CONFIG_SPIRAM_ECC_ENABLE", True)
cg.add_define("USE_PSRAM") cg.add_define("USE_PSRAM")

View File

@ -1,25 +1,36 @@
#include "psram.h"
#ifdef USE_ESP32 #ifdef USE_ESP32
#include "psram.h"
#ifdef USE_ESP_IDF
#include <esp_psram.h>
#endif // USE_ESP_IDF
#include "esphome/core/log.h" #include "esphome/core/log.h"
#include <esp_heap_caps.h> #include <esp_heap_caps.h>
#include <esp_idf_version.h>
namespace esphome { namespace esphome {
namespace psram { namespace psram {
static const char *const TAG = "psram"; static const char *const TAG = "psram";
void PsramComponent::dump_config() { void PsramComponent::dump_config() {
ESP_LOGCONFIG(TAG, "PSRAM:");
#ifdef USE_ESP_IDF
bool available = esp_psram_is_initialized();
ESP_LOGCONFIG(TAG, " Available: %s", YESNO(available));
if (available) {
ESP_LOGCONFIG(TAG, " Size: %zu KB", esp_psram_get_size() / 1024);
#if CONFIG_SPIRAM_ECC_ENABLE
ESP_LOGCONFIG(TAG, " ECC enabled: YES");
#endif
}
#else
// Technically this can be false if the PSRAM is full, but heap_caps_get_total_size() isn't always available, and it's // Technically this can be false if the PSRAM is full, but heap_caps_get_total_size() isn't always available, and it's
// very unlikely for the PSRAM to be full. // very unlikely for the PSRAM to be full.
bool available = heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0; bool available = heap_caps_get_free_size(MALLOC_CAP_SPIRAM) > 0;
ESP_LOGCONFIG(TAG, "PSRAM:");
ESP_LOGCONFIG(TAG, " Available: %s", YESNO(available)); ESP_LOGCONFIG(TAG, " Available: %s", YESNO(available));
#if ESP_IDF_VERSION >= ESP_IDF_VERSION_VAL(4, 1, 0)
if (available) { if (available) {
const size_t psram_total_size_bytes = heap_caps_get_total_size(MALLOC_CAP_SPIRAM); const size_t psram_total_size_bytes = heap_caps_get_total_size(MALLOC_CAP_SPIRAM);
const float psram_total_size_kb = psram_total_size_bytes / 1024.0f; const float psram_total_size_kb = psram_total_size_bytes / 1024.0f;
@ -30,7 +41,7 @@ void PsramComponent::dump_config() {
ESP_LOGCONFIG(TAG, " Size: %zu bytes", psram_total_size_bytes); ESP_LOGCONFIG(TAG, " Size: %zu bytes", psram_total_size_bytes);
} }
} }
#endif #endif // USE_ESP_IDF
} }
} // namespace psram } // namespace psram

View File

@ -1,3 +1,2 @@
psram: psram:
mode: octal
speed: 80MHz speed: 80MHz

View File

@ -1 +0,0 @@
<<: !include common.yaml

View File

@ -1 +0,0 @@
<<: !include common.yaml

View File

@ -1 +1,3 @@
<<: !include common.yaml psram:
mode: octal
speed: 80MHz

View File

@ -1 +1,10 @@
<<: !include common.yaml esp32:
framework:
type: esp-idf
advanced:
enable_idf_experimental_features: yes
psram:
mode: octal
speed: 120MHz
enable_ecc: true