From f6bf6bd8ee0aff23bbc1961bac67e7d8beb52121 Mon Sep 17 00:00:00 2001 From: "J. Nick Koston" Date: Sat, 8 Nov 2025 21:12:00 -0600 Subject: [PATCH] [uart] Store static data in flash and use function pointers for lambdas --- esphome/components/uart/__init__.py | 7 ++++-- esphome/components/uart/automation.h | 32 +++++++++++++++++----------- 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/esphome/components/uart/__init__.py b/esphome/components/uart/__init__.py index eb911ed007..cbc11d0db0 100644 --- a/esphome/components/uart/__init__.py +++ b/esphome/components/uart/__init__.py @@ -31,7 +31,7 @@ from esphome.const import ( PLATFORM_HOST, PlatformFramework, ) -from esphome.core import CORE +from esphome.core import CORE, ID import esphome.final_validate as fv from esphome.yaml_util import make_data_base @@ -446,7 +446,10 @@ async def uart_write_to_code(config, action_id, template_arg, args): templ = await cg.templatable(data, args, cg.std_vector.template(cg.uint8)) cg.add(var.set_data_template(templ)) else: - cg.add(var.set_data_static(cg.ArrayInitializer(*data))) + # Generate static array in flash to avoid RAM copy + arr_id = ID(f"{action_id}_data", is_declaration=True, type=cg.uint8) + arr = cg.static_const_array(arr_id, cg.ArrayInitializer(*data)) + cg.add(var.set_data_static(arr, len(data))) return var diff --git a/esphome/components/uart/automation.h b/esphome/components/uart/automation.h index ad2c4d2bf1..7a3344c2f1 100644 --- a/esphome/components/uart/automation.h +++ b/esphome/components/uart/automation.h @@ -10,32 +10,38 @@ namespace uart { template class UARTWriteAction : public Action, public Parented { public: - void set_data_template(std::function(Ts...)> func) { - this->data_func_ = func; + void set_data_template(std::vector (*func)(Ts...)) { + // Stateless lambdas (generated by ESPHome) implicitly convert to function pointers + this->data_.func = func; this->static_ = false; } - void set_data_static(std::vector &&data) { - this->data_static_ = std::move(data); - this->static_ = true; - } - void set_data_static(std::initializer_list data) { - this->data_static_ = std::vector(data); + + // Store pointer to static data in flash (no RAM copy) + void set_data_static(const uint8_t *data, size_t len) { + // Simply set pointer and length - no construction needed for POD types + this->data_.static_data.ptr = data; + this->data_.static_data.len = len; this->static_ = true; } void play(const Ts &...x) override { if (this->static_) { - this->parent_->write_array(this->data_static_); + this->parent_->write_array(this->data_.static_data.ptr, this->data_.static_data.len); } else { - auto val = this->data_func_(x...); + auto val = this->data_.func(x...); this->parent_->write_array(val); } } protected: - bool static_{false}; - std::function(Ts...)> data_func_{}; - std::vector data_static_{}; + bool static_{true}; // Default to static mode (most common case) + union Data { + std::vector (*func)(Ts...); // Function pointer (stateless lambdas) + struct { + const uint8_t *ptr; + size_t len; + } static_data; + } data_; }; } // namespace uart