From 4335fcdb72cddb820b75e6ba20dc41b01739cce2 Mon Sep 17 00:00:00 2001 From: Jonathan Swoboda <154711427+swoboda1337@users.noreply.github.com> Date: Sun, 30 Nov 2025 23:27:10 -0500 Subject: [PATCH 1/5] [psram] Add C5 support (#12215) Co-authored-by: Claude --- esphome/components/psram/__init__.py | 3 +++ tests/component_tests/psram/test_psram.py | 7 ++++--- tests/components/psram/test.esp32-c5-idf.yaml | 8 ++++++++ .../build_components_base.esp32-c5-idf.yaml | 17 +++++++++++++++++ 4 files changed, 32 insertions(+), 3 deletions(-) create mode 100644 tests/components/psram/test.esp32-c5-idf.yaml create mode 100644 tests/test_build_components/build_components_base.esp32-c5-idf.yaml diff --git a/esphome/components/psram/__init__.py b/esphome/components/psram/__init__.py index c50c5998550..4ee4e97696c 100644 --- a/esphome/components/psram/__init__.py +++ b/esphome/components/psram/__init__.py @@ -11,6 +11,7 @@ from esphome.components.esp32 import ( get_esp32_variant, ) from esphome.components.esp32.const import ( + VARIANT_ESP32C5, VARIANT_ESP32P4, VARIANT_ESP32S2, VARIANT_ESP32S3, @@ -55,6 +56,7 @@ SPIRAM_MODES = { VARIANT_ESP32: (TYPE_QUAD,), VARIANT_ESP32S2: (TYPE_QUAD,), VARIANT_ESP32S3: (TYPE_QUAD, TYPE_OCTAL), + VARIANT_ESP32C5: (TYPE_QUAD,), VARIANT_ESP32P4: (TYPE_HEX,), } @@ -63,6 +65,7 @@ SPIRAM_SPEEDS = { VARIANT_ESP32: (40, 80, 120), VARIANT_ESP32S2: (40, 80, 120), VARIANT_ESP32S3: (40, 80, 120), + VARIANT_ESP32C5: (40, 80, 120), VARIANT_ESP32P4: (20, 100, 200), } diff --git a/tests/component_tests/psram/test_psram.py b/tests/component_tests/psram/test_psram.py index f8ad013689b..86bc29cc843 100644 --- a/tests/component_tests/psram/test_psram.py +++ b/tests/component_tests/psram/test_psram.py @@ -23,22 +23,23 @@ from tests.component_tests.types import SetCoreConfigCallable UNSUPPORTED_PSRAM_VARIANTS = [ VARIANT_ESP32C2, VARIANT_ESP32C3, - VARIANT_ESP32C5, VARIANT_ESP32C6, VARIANT_ESP32H2, ] SUPPORTED_PSRAM_VARIANTS = [ VARIANT_ESP32, + VARIANT_ESP32C5, + VARIANT_ESP32P4, VARIANT_ESP32S2, VARIANT_ESP32S3, - VARIANT_ESP32P4, ] SUPPORTED_PSRAM_MODES = { VARIANT_ESP32: ["quad"], + VARIANT_ESP32C5: ["quad"], + VARIANT_ESP32P4: ["hex"], VARIANT_ESP32S2: ["quad"], VARIANT_ESP32S3: ["quad", "octal"], - VARIANT_ESP32P4: ["hex"], } diff --git a/tests/components/psram/test.esp32-c5-idf.yaml b/tests/components/psram/test.esp32-c5-idf.yaml new file mode 100644 index 00000000000..fbd0132e2dd --- /dev/null +++ b/tests/components/psram/test.esp32-c5-idf.yaml @@ -0,0 +1,8 @@ +esp32: + cpu_frequency: 240MHz + framework: + type: esp-idf + +psram: + speed: 120MHz + ignore_not_found: false diff --git a/tests/test_build_components/build_components_base.esp32-c5-idf.yaml b/tests/test_build_components/build_components_base.esp32-c5-idf.yaml new file mode 100644 index 00000000000..6468297e9ad --- /dev/null +++ b/tests/test_build_components/build_components_base.esp32-c5-idf.yaml @@ -0,0 +1,17 @@ +esphome: + name: componenttestesp32c5idf + friendly_name: $component_name + +esp32: + board: esp32-c5-devkitc-1 + framework: + type: esp-idf + +logger: + level: VERY_VERBOSE + +packages: + component_under_test: !include + file: $component_test_file + vars: + component_test_file: $component_test_file From 4dbe0dab51ac3cd6c45ad22885c74a0aad7c4ae0 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 30 Nov 2025 22:42:20 -0600 Subject: [PATCH 2/5] [core] Use StringRef for get_comment and get_compilation_time to avoid allocations --- esphome/components/mqtt/mqtt_component.cpp | 2 +- esphome/components/sen5x/sen5x.cpp | 2 +- esphome/components/sgp30/sgp30.cpp | 2 +- esphome/components/sgp4x/sgp4x.cpp | 2 +- esphome/components/version/version_text_sensor.cpp | 2 +- esphome/components/web_server/web_server.cpp | 2 +- esphome/components/wifi/wifi_component.cpp | 2 +- esphome/core/application.h | 2 ++ esphome/core/helpers.h | 1 + 9 files changed, 10 insertions(+), 7 deletions(-) diff --git a/esphome/components/mqtt/mqtt_component.cpp b/esphome/components/mqtt/mqtt_component.cpp index 1cd818964eb..5d2bedae790 100644 --- a/esphome/components/mqtt/mqtt_component.cpp +++ b/esphome/components/mqtt/mqtt_component.cpp @@ -154,7 +154,7 @@ bool MQTTComponent::send_discovery_() { device_info[MQTT_DEVICE_MANUFACTURER] = model == nullptr ? ESPHOME_PROJECT_NAME : std::string(ESPHOME_PROJECT_NAME, model - ESPHOME_PROJECT_NAME); #else - device_info[MQTT_DEVICE_SW_VERSION] = ESPHOME_VERSION " (" + App.get_compilation_time() + ")"; + device_info[MQTT_DEVICE_SW_VERSION] = ESPHOME_VERSION " (" + App.get_compilation_time_ref() + ")"; device_info[MQTT_DEVICE_MODEL] = ESPHOME_BOARD; #if defined(USE_ESP8266) || defined(USE_ESP32) device_info[MQTT_DEVICE_MANUFACTURER] = "Espressif"; diff --git a/esphome/components/sen5x/sen5x.cpp b/esphome/components/sen5x/sen5x.cpp index 3298a5b8dbb..fc187d68626 100644 --- a/esphome/components/sen5x/sen5x.cpp +++ b/esphome/components/sen5x/sen5x.cpp @@ -157,7 +157,7 @@ void SEN5XComponent::setup() { // Hash with compilation time and serial number // This ensures the baseline storage is cleared after OTA // Serial numbers are unique to each sensor, so mulitple sensors can be used without conflict - uint32_t hash = fnv1_hash(App.get_compilation_time() + std::to_string(combined_serial)); + uint32_t hash = fnv1_hash(App.get_compilation_time_ref() + std::to_string(combined_serial).c_str()); this->pref_ = global_preferences->make_preference(hash, true); if (this->pref_.load(&this->voc_baselines_storage_)) { diff --git a/esphome/components/sgp30/sgp30.cpp b/esphome/components/sgp30/sgp30.cpp index 9e8d6b332c9..2d2b1a151cb 100644 --- a/esphome/components/sgp30/sgp30.cpp +++ b/esphome/components/sgp30/sgp30.cpp @@ -75,7 +75,7 @@ void SGP30Component::setup() { // Hash with compilation time and serial number // This ensures the baseline storage is cleared after OTA // Serial numbers are unique to each sensor, so mulitple sensors can be used without conflict - uint32_t hash = fnv1_hash(App.get_compilation_time() + std::to_string(this->serial_number_)); + uint32_t hash = fnv1_hash(App.get_compilation_time_ref() + std::to_string(this->serial_number_).c_str()); this->pref_ = global_preferences->make_preference(hash, true); if (this->store_baseline_ && this->pref_.load(&this->baselines_storage_)) { diff --git a/esphome/components/sgp4x/sgp4x.cpp b/esphome/components/sgp4x/sgp4x.cpp index 99d88006f78..9099d5780f9 100644 --- a/esphome/components/sgp4x/sgp4x.cpp +++ b/esphome/components/sgp4x/sgp4x.cpp @@ -59,7 +59,7 @@ void SGP4xComponent::setup() { // Hash with compilation time and serial number // This ensures the baseline storage is cleared after OTA // Serial numbers are unique to each sensor, so mulitple sensors can be used without conflict - uint32_t hash = fnv1_hash(App.get_compilation_time() + std::to_string(this->serial_number_)); + uint32_t hash = fnv1_hash(App.get_compilation_time_ref() + std::to_string(this->serial_number_).c_str()); this->pref_ = global_preferences->make_preference(hash, true); if (this->pref_.load(&this->voc_baselines_storage_)) { diff --git a/esphome/components/version/version_text_sensor.cpp b/esphome/components/version/version_text_sensor.cpp index 65dbfd27cfe..78d0fb501ba 100644 --- a/esphome/components/version/version_text_sensor.cpp +++ b/esphome/components/version/version_text_sensor.cpp @@ -13,7 +13,7 @@ void VersionTextSensor::setup() { if (this->hide_timestamp_) { this->publish_state(ESPHOME_VERSION); } else { - this->publish_state(str_sprintf(ESPHOME_VERSION " %s", App.get_compilation_time().c_str())); + this->publish_state(str_sprintf(ESPHOME_VERSION " %s", App.get_compilation_time_ref().c_str())); } } float VersionTextSensor::get_setup_priority() const { return setup_priority::DATA; } diff --git a/esphome/components/web_server/web_server.cpp b/esphome/components/web_server/web_server.cpp index bc48793ba2f..0f5093c8951 100644 --- a/esphome/components/web_server/web_server.cpp +++ b/esphome/components/web_server/web_server.cpp @@ -283,7 +283,7 @@ std::string WebServer::get_config_json() { JsonObject root = builder.root(); root["title"] = App.get_friendly_name().empty() ? App.get_name() : App.get_friendly_name(); - root["comment"] = App.get_comment(); + root["comment"] = App.get_comment_ref(); #if defined(USE_WEBSERVER_OTA_DISABLED) || !defined(USE_WEBSERVER_OTA) root["ota"] = false; // Note: USE_WEBSERVER_OTA_DISABLED only affects web_server, not captive_portal #else diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index e67493aa4d5..2a19ba45f10 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -360,7 +360,7 @@ void WiFiComponent::start() { get_mac_address_pretty_into_buffer(mac_s)); this->last_connected_ = millis(); - uint32_t hash = this->has_sta() ? fnv1_hash(App.get_compilation_time()) : 88491487UL; + uint32_t hash = this->has_sta() ? fnv1_hash(App.get_compilation_time_ref()) : 88491487UL; this->pref_ = global_preferences->make_preference(hash, true); #ifdef USE_WIFI_FAST_CONNECT diff --git a/esphome/core/application.h b/esphome/core/application.h index 14e800342ee..98c979b682b 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -256,6 +256,8 @@ class Application { /// Get the comment of this Application set by pre_setup(). std::string get_comment() const { return this->comment_; } + /// Get the comment as StringRef (avoids allocation) + StringRef get_comment_ref() const { return StringRef::from_maybe_nullptr(this->comment_); } bool is_name_add_mac_suffix_enabled() const { return this->name_add_mac_suffix_; } diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 83a12b9bf00..32e8cc6fa1c 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -380,6 +380,7 @@ uint16_t crc16be(const uint8_t *data, uint16_t len, uint16_t crc = 0, uint16_t p /// Calculate a FNV-1 hash of \p str. uint32_t fnv1_hash(const char *str); inline uint32_t fnv1_hash(const std::string &str) { return fnv1_hash(str.c_str()); } +inline uint32_t fnv1_hash(const StringRef &str) { return fnv1_hash(str.c_str()); } /// Return a random 32-bit unsigned integer. uint32_t random_uint32(); From de6b20d4954ee7cb29bcc4e2479cd273c6acb0dc Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 30 Nov 2025 22:44:30 -0600 Subject: [PATCH 3/5] [core] Use StringRef for get_comment and get_compilation_time to avoid allocations --- esphome/core/application.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/esphome/core/application.h b/esphome/core/application.h index 98c979b682b..8e2035b7c5e 100644 --- a/esphome/core/application.h +++ b/esphome/core/application.h @@ -257,7 +257,7 @@ class Application { /// Get the comment of this Application set by pre_setup(). std::string get_comment() const { return this->comment_; } /// Get the comment as StringRef (avoids allocation) - StringRef get_comment_ref() const { return StringRef::from_maybe_nullptr(this->comment_); } + StringRef get_comment_ref() const { return StringRef(this->comment_); } bool is_name_add_mac_suffix_enabled() const { return this->name_add_mac_suffix_; } From b5a3c0be211c91dc4797655fbb272ed97b0545b2 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 30 Nov 2025 22:47:40 -0600 Subject: [PATCH 4/5] [core] Use StringRef for get_comment and get_compilation_time to avoid allocations --- esphome/core/helpers.h | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 32e8cc6fa1c..9bbc771fb8d 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -15,6 +15,7 @@ #include #include "esphome/core/optional.h" +#include "esphome/core/string_ref.h" #ifdef USE_ESP8266 #include @@ -47,9 +48,6 @@ namespace esphome { -// Forward declaration to avoid circular dependency with string_ref.h -class StringRef; - /// @name STL backports ///@{ From edf19b8dd444b7a678bfcd407b0fab9ce13dc493 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sun, 30 Nov 2025 22:49:23 -0600 Subject: [PATCH 5/5] [core] Use StringRef for get_comment and get_compilation_time to avoid allocations --- esphome/components/wifi/wifi_component.cpp | 2 +- esphome/core/helpers.h | 5 +++-- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/esphome/components/wifi/wifi_component.cpp b/esphome/components/wifi/wifi_component.cpp index 2a19ba45f10..69d7cb489c7 100644 --- a/esphome/components/wifi/wifi_component.cpp +++ b/esphome/components/wifi/wifi_component.cpp @@ -360,7 +360,7 @@ void WiFiComponent::start() { get_mac_address_pretty_into_buffer(mac_s)); this->last_connected_ = millis(); - uint32_t hash = this->has_sta() ? fnv1_hash(App.get_compilation_time_ref()) : 88491487UL; + uint32_t hash = this->has_sta() ? fnv1_hash(App.get_compilation_time_ref().c_str()) : 88491487UL; this->pref_ = global_preferences->make_preference(hash, true); #ifdef USE_WIFI_FAST_CONNECT diff --git a/esphome/core/helpers.h b/esphome/core/helpers.h index 9bbc771fb8d..83a12b9bf00 100644 --- a/esphome/core/helpers.h +++ b/esphome/core/helpers.h @@ -15,7 +15,6 @@ #include #include "esphome/core/optional.h" -#include "esphome/core/string_ref.h" #ifdef USE_ESP8266 #include @@ -48,6 +47,9 @@ namespace esphome { +// Forward declaration to avoid circular dependency with string_ref.h +class StringRef; + /// @name STL backports ///@{ @@ -378,7 +380,6 @@ uint16_t crc16be(const uint8_t *data, uint16_t len, uint16_t crc = 0, uint16_t p /// Calculate a FNV-1 hash of \p str. uint32_t fnv1_hash(const char *str); inline uint32_t fnv1_hash(const std::string &str) { return fnv1_hash(str.c_str()); } -inline uint32_t fnv1_hash(const StringRef &str) { return fnv1_hash(str.c_str()); } /// Return a random 32-bit unsigned integer. uint32_t random_uint32();