From 3c51793d5cc4388724e32df164e3205f2946fe76 Mon Sep 17 00:00:00 2001 From: Theo Arends <11044339+arendst@users.noreply.github.com> Date: Tue, 10 Dec 2024 11:39:37 +0100 Subject: [PATCH] Reduce stack usage --- CHANGELOG.md | 2 +- tasmota/tasmota_support/support.ino | 6 ++-- .../tasmota_xdrv_driver/xdrv_02_9_mqtt.ino | 29 +++++++++++++++---- .../tasmota_xx2c_global/xdrv_interface.ino | 6 ++-- 4 files changed, 31 insertions(+), 12 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 49c001ddf..f17cbed74 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -18,7 +18,7 @@ All notable changes to this project will be documented in this file. - Command `SetOption162 1` to disable adding export energy to energy today (#22578) - ESP32 support for WPA2/3 Enterprise conditional in core v3.1.0.241206 (#22600) - Support for Sonoff POWCT Energy Export Active (#22596) -- Improved auto-selection of LED hardware support (RMT, SPI) +- Improved auto-selection of LED hardware support (RMT, SPI) (#22618) ### Breaking Changed - ESP32 ArtNet switches from GRB to RGB encoding (#22556) diff --git a/tasmota/tasmota_support/support.ino b/tasmota/tasmota_support/support.ino index 4dc5fdff2..7d34b6c51 100755 --- a/tasmota/tasmota_support/support.ino +++ b/tasmota/tasmota_support/support.ino @@ -1148,6 +1148,8 @@ int GetCommandCode(char* destination, size_t destination_size, const char* needl bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void), const uint8_t *synonyms = nullptr); bool DecodeCommand(const char* haystack, void (* const MyCommand[])(void), const uint8_t *synonyms) { + SHOW_FREE_MEM(PSTR("DecodeCommand")); + GetTextIndexed(XdrvMailbox.command, CMDSZ, 0, haystack); // Get prefix if available int prefix_length = strlen(XdrvMailbox.command); if (prefix_length) { @@ -2680,9 +2682,7 @@ void AddLogData(uint32_t loglevel, const char* log_data, const char* log_data_pa } snprintf_P(TasmotaGlobal.log_buffer, LOG_BUFFER_SIZE, PSTR("%s%c%c%s%s%s%s\1"), TasmotaGlobal.log_buffer, TasmotaGlobal.log_buffer_pointer++, '0'+loglevel, mxtime, log_data, log_data_payload, log_data_retained); - if (too_long) { - free(too_long); - } + if (too_long) { free(too_long); } TasmotaGlobal.log_buffer_pointer &= 0xFF; if (!TasmotaGlobal.log_buffer_pointer) { TasmotaGlobal.log_buffer_pointer++; // Index 0 is not allowed as it is the end of char string diff --git a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino index 0e19c0c0e..3d2d998e8 100644 --- a/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino +++ b/tasmota/tasmota_xdrv_driver/xdrv_02_9_mqtt.ino @@ -702,15 +702,14 @@ void MqttPublishLoggingAsync(bool refresh) { void MqttPublishPayload(const char* topic, const char* payload, uint32_t binary_length, bool retained) { // Publish payload string or binary when binary_length set with optional retained - - SHOW_FREE_MEM(PSTR("MqttPublish")); + SHOW_FREE_MEM(PSTR("MqttPublishPayload")); bool binary_data = (binary_length > 0); if (!binary_data) { binary_length = strlen(payload); } - if (Settings->flag4.mqtt_no_retain) { // SetOption104 - Disable all MQTT retained messages, some brokers don't support it: AWS IoT, Losant + if (Settings->flag4.mqtt_no_retain) { // SetOption104 - Disable all MQTT retained messages, some brokers don't support it: AWS IoT, Losant retained = false; // Some brokers don't support retained, they will disconnect if received } @@ -794,14 +793,30 @@ void MqttPublishPayloadPrefixTopic_P(uint32_t prefix, const char* subtopic, cons prefix 5 = stat using subtopic or RESULT prefix 6 = tele using subtopic or RESULT */ - char romram[64]; + SHOW_FREE_MEM(PSTR("MqttPublishPayloadPrefixTopic_P")); +/* + char romram[64]; // Claim 64 bytes from 4k stack snprintf_P(romram, sizeof(romram), ((prefix > 3) && !Settings->flag.mqtt_response) ? S_RSLT_RESULT : subtopic); // SetOption4 - Switch between MQTT RESULT or COMMAND UpperCase(romram, romram); prefix &= 3; - char stopic[TOPSZ]; + char stopic[TOPSZ]; // Claim TOPSZ bytes from 4k stack GetTopic_P(stopic, prefix, TasmotaGlobal.mqtt_topic, romram); MqttPublishPayload(stopic, payload, binary_length, retained); +*/ + // Reduce important stack usage by 200 bytes but adding 52 bytes code + char *romram = (char*)malloc(64); // Claim 64 bytes from 20k heap + strcpy_P(romram, ((prefix > 3) && !Settings->flag.mqtt_response) ? S_RSLT_RESULT : subtopic); + UpperCase(romram, romram); + + prefix &= 3; + char *htopic = (char*)malloc(TOPSZ); // Claim TOPSZ bytes from 16k heap + GetTopic_P(htopic, prefix, TasmotaGlobal.mqtt_topic, romram); + char stopic[strlen_P(htopic) +1]; // Claim only strlen_P bytes from 4k stack + strcpy_P(stopic, htopic); + free(htopic); // Free 16k heap from TOPSZ bytes + free(romram); // Free 16k heap from 64 bytes + MqttPublishPayload(stopic, payload, binary_length, retained); #if defined(USE_MQTT_AWS_IOT) || defined(USE_MQTT_AWS_IOT_LIGHT) if ((prefix > 0) && (Settings->flag4.awsiot_shadow) && (Mqtt.connected)) { // placeholder for SetOptionXX @@ -857,6 +872,8 @@ void MqttPublishPayloadPrefixTopicRulesProcess_P(uint32_t prefix, const char* su void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic, bool retained) { // Publish //> default ResponseData string with optional retained + SHOW_FREE_MEM(PSTR("MqttPublishPrefixTopic_P")); + MqttPublishPayloadPrefixTopic_P(prefix, subtopic, ResponseData(), 0, retained); } @@ -868,6 +885,8 @@ void MqttPublishPrefixTopic_P(uint32_t prefix, const char* subtopic) { void MqttPublishPrefixTopicRulesProcess_P(uint32_t prefix, const char* subtopic, bool retained) { // Publish //> default ResponseData string with optional retained // then process rules + SHOW_FREE_MEM(PSTR("MqttPublishPrefixTopicRulesProcess_P")); + MqttPublishPrefixTopic_P(prefix, subtopic, retained); XdrvRulesProcess(0); } diff --git a/tasmota/tasmota_xx2c_global/xdrv_interface.ino b/tasmota/tasmota_xx2c_global/xdrv_interface.ino index b68c53c8e..78810c253 100644 --- a/tasmota/tasmota_xx2c_global/xdrv_interface.ino +++ b/tasmota/tasmota_xx2c_global/xdrv_interface.ino @@ -1105,10 +1105,10 @@ bool XdrvRulesProcess(bool teleperiod) { #ifdef USE_DEBUG_DRIVER void ShowFreeMem(const char *where) { - char stemp[30]; - snprintf_P(stemp, sizeof(stemp), where); - XdrvMailbox.data = stemp; + char *XdrvMailboxData = XdrvMailbox.data; + XdrvMailbox.data = (char*)where; XdrvCall(FUNC_FREE_MEM); + XdrvMailbox.data = XdrvMailboxData; } #endif