From e2a9cced949528fb1eebe1ec2d1d228d38efa6e6 Mon Sep 17 00:00:00 2001 From: Clyde Stubbs <2366188+clydebarrow@users.noreply.github.com> Date: Mon, 9 Jun 2025 11:07:54 +1000 Subject: [PATCH] [psram] Add P4 support (#8545) Co-authored-by: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Co-authored-by: Jesse Hills <3060199+jesserockz@users.noreply.github.com> Co-authored-by: clydeps --- esphome/components/psram/__init__.py | 66 ++++++++++++------- platformio.ini | 12 ++++ tests/components/psram/test.esp32-p4-idf.yaml | 9 +++ .../build_components_base.esp32-p4-idf.yaml | 18 +++++ 4 files changed, 81 insertions(+), 24 deletions(-) create mode 100644 tests/components/psram/test.esp32-p4-idf.yaml create mode 100644 tests/test_build_components/build_components_base.esp32-p4-idf.yaml diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index c00cbb2ba2..9299cdcd0e 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -7,9 +7,12 @@ from esphome.components.esp32 import ( VARIANT_ESP32, add_idf_sdkconfig_option, get_esp32_variant, - only_on_variant, ) -from esphome.components.esp32.const import VARIANT_ESP32S2, VARIANT_ESP32S3 +from esphome.components.esp32.const import ( + VARIANT_ESP32P4, + VARIANT_ESP32S2, + VARIANT_ESP32S3, +) import esphome.config_validation as cv from esphome.const import ( CONF_ADVANCED, @@ -35,24 +38,31 @@ PsramComponent = psram_ns.class_("PsramComponent", cg.Component) TYPE_QUAD = "quad" TYPE_OCTAL = "octal" +TYPE_HEX = "hex" + +SDK_MODES = {TYPE_QUAD: "QUAD", TYPE_OCTAL: "OCT", TYPE_HEX: "HEX"} CONF_ENABLE_ECC = "enable_ecc" SPIRAM_MODES = { - TYPE_QUAD: "CONFIG_SPIRAM_MODE_QUAD", - TYPE_OCTAL: "CONFIG_SPIRAM_MODE_OCT", + VARIANT_ESP32: (TYPE_QUAD,), + VARIANT_ESP32S2: (TYPE_QUAD,), + VARIANT_ESP32S3: (TYPE_QUAD, TYPE_OCTAL), + VARIANT_ESP32P4: (TYPE_HEX,), } + SPIRAM_SPEEDS = { - 40e6: "CONFIG_SPIRAM_SPEED_40M", - 80e6: "CONFIG_SPIRAM_SPEED_80M", - 120e6: "CONFIG_SPIRAM_SPEED_120M", + VARIANT_ESP32: (40, 80, 120), + VARIANT_ESP32S2: (40, 80, 120), + VARIANT_ESP32S3: (40, 80, 120), + VARIANT_ESP32P4: (20, 100, 200), } def validate_psram_mode(config): esp32_config = fv.full_config.get()[PLATFORM_ESP32] - if config[CONF_SPEED] == 120e6: + if config[CONF_SPEED] == "120MHZ": if esp32_config[CONF_CPU_FREQUENCY] != "240MHZ": raise cv.Invalid( "PSRAM 120MHz requires 240MHz CPU frequency (set in esp32 component)" @@ -79,23 +89,23 @@ def validate_psram_mode(config): return config -CONFIG_SCHEMA = cv.All( - cv.Schema( +def get_config_schema(config): + variant = get_esp32_variant() + speeds = [f"{s}MHZ" for s in SPIRAM_SPEEDS.get(variant, [])] + if not speeds: + return cv.Invalid("PSRAM is not supported on this chip") + modes = SPIRAM_MODES[variant] + return cv.Schema( { cv.GenerateID(): cv.declare_id(PsramComponent), - cv.Optional(CONF_MODE, default=TYPE_QUAD): cv.enum( - SPIRAM_MODES, lower=True - ), + cv.Optional(CONF_MODE, default=modes[0]): cv.one_of(*modes, lower=True), cv.Optional(CONF_ENABLE_ECC, default=False): cv.boolean, - cv.Optional(CONF_SPEED, default=40e6): cv.All( - cv.frequency, cv.one_of(*SPIRAM_SPEEDS) - ), + cv.Optional(CONF_SPEED, default=speeds[0]): cv.one_of(*speeds, upper=True), } - ), - only_on_variant( - supported=[VARIANT_ESP32, VARIANT_ESP32S3, VARIANT_ESP32S2], - ), -) + )(config) + + +CONFIG_SCHEMA = get_config_schema FINAL_VALIDATE_SCHEMA = validate_psram_mode @@ -110,15 +120,23 @@ async def to_code(config): add_idf_sdkconfig_option( f"CONFIG_{get_esp32_variant().upper()}_SPIRAM_SUPPORT", True ) + add_idf_sdkconfig_option("CONFIG_SOC_SPIRAM_SUPPORTED", True) add_idf_sdkconfig_option("CONFIG_SPIRAM", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_USE", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_USE_CAPS_ALLOC", True) add_idf_sdkconfig_option("CONFIG_SPIRAM_IGNORE_NOTFOUND", True) - add_idf_sdkconfig_option(f"{SPIRAM_MODES[config[CONF_MODE]]}", 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( + f"CONFIG_SPIRAM_MODE_{SDK_MODES[config[CONF_MODE]]}", True + ) + + # Remove MHz suffix, convert to int + speed = int(config[CONF_SPEED][:-3]) + add_idf_sdkconfig_option(f"CONFIG_SPIRAM_SPEED_{speed}M", True) + add_idf_sdkconfig_option("CONFIG_SPIRAM_SPEED", speed) + if config[CONF_MODE] == TYPE_OCTAL and speed == 120: add_idf_sdkconfig_option("CONFIG_ESPTOOLPY_FLASHFREQ_120M", True) + add_idf_sdkconfig_option("CONFIG_BOOTLOADER_FLASH_DC_AWARE", True) if CORE.data[KEY_CORE][KEY_FRAMEWORK_VERSION] >= cv.Version(5, 4, 0): add_idf_sdkconfig_option( "CONFIG_SPIRAM_TIMING_TUNING_POINT_VIA_TEMPERATURE_SENSOR", True diff --git a/platformio.ini b/platformio.ini index 0e7bd80bc6..27da883ab3 100644 --- a/platformio.ini +++ b/platformio.ini @@ -424,6 +424,18 @@ build_flags = ${flags:clangtidy.build_flags} -DUSE_ESP32_VARIANT_ESP32S3 +;;;;;;;; ESP32-P4 ;;;;;;;; + +[env:esp32p4-idf] +extends = common:esp32-idf +board = esp32-p4-evboard + +board_build.esp-idf.sdkconfig_path = .temp/sdkconfig-esp32p4-idf +build_flags = + ${common:esp32-idf.build_flags} + ${flags:runtime.build_flags} + -DUSE_ESP32_VARIANT_ESP32P4 + ;;;;;;;; RP2040 ;;;;;;;; [env:rp2040-pico-arduino] diff --git a/tests/components/psram/test.esp32-p4-idf.yaml b/tests/components/psram/test.esp32-p4-idf.yaml new file mode 100644 index 0000000000..9ebd80328d --- /dev/null +++ b/tests/components/psram/test.esp32-p4-idf.yaml @@ -0,0 +1,9 @@ +esp32: + cpu_frequency: 360MHz + framework: + type: esp-idf + advanced: + enable_idf_experimental_features: yes + +psram: + speed: 200MHz diff --git a/tests/test_build_components/build_components_base.esp32-p4-idf.yaml b/tests/test_build_components/build_components_base.esp32-p4-idf.yaml new file mode 100644 index 0000000000..e2b975f643 --- /dev/null +++ b/tests/test_build_components/build_components_base.esp32-p4-idf.yaml @@ -0,0 +1,18 @@ +esphome: + name: componenttestesp32p4idf + friendly_name: $component_name + +esp32: + board: esp32-p4-evboard + framework: + type: esp-idf + +logger: + level: VERY_VERBOSE + +packages: + component_under_test: !include + file: $component_test_file + vars: + component_test_file: $component_test_file +