diff --git a/src/src/DataStructs/EventQueue.cpp b/src/src/DataStructs/EventQueue.cpp index 0b975046f5..06a0b4e546 100644 --- a/src/src/DataStructs/EventQueue.cpp +++ b/src/src/DataStructs/EventQueue.cpp @@ -11,18 +11,21 @@ void EventQueueStruct::add(const String& event, bool deduplicate) { if (!deduplicate || !isDuplicate(event)) { - #ifdef USE_SECOND_HEAP +#if defined(USE_SECOND_HEAP) || defined(ESP32) String tmp; reserve_special(tmp, event.length()); tmp = event; +#ifdef USE_SECOND_HEAP // Do not add to the list while on 2nd heap HeapSelectDram ephemeral; +#endif + _eventQueue.emplace_back(std::move(tmp)); - #else +#else _eventQueue.push_back(event); - #endif // ifdef USE_SECOND_HEAP +#endif } } @@ -38,12 +41,14 @@ void EventQueueStruct::addMove(String&& event, bool deduplicate) if (!event.length()) { return; } if (!deduplicate || !isDuplicate(event)) { - #ifdef USE_SECOND_HEAP + #if defined(USE_SECOND_HEAP) || defined(ESP32) String tmp; move_special(tmp, std::move(event)); + #ifdef USE_SECOND_HEAP // Do not add to the list while on 2nd heap HeapSelectDram ephemeral; + #endif _eventQueue.emplace_back(std::move(tmp)); #else _eventQueue.emplace_back(std::move(event)); diff --git a/src/src/DataStructs/LogEntry.cpp b/src/src/DataStructs/LogEntry.cpp index 90cb825dcc..99348ce80c 100644 --- a/src/src/DataStructs/LogEntry.cpp +++ b/src/src/DataStructs/LogEntry.cpp @@ -48,7 +48,7 @@ bool LogEntry_t::add(const uint8_t loglevel, String&& line) // Need to make a substring, which is a new allocation, on the 2nd heap HeapSelectIram ephemeral; #endif // ifdef USE_SECOND_HEAP - _message = std::move(line.substring(0, LOG_STRUCT_MESSAGE_SIZE - 1)); + _message = move_special(line.substring(0, LOG_STRUCT_MESSAGE_SIZE - 1)); } else { move_special(_message, std::move(line)); } diff --git a/src/src/Helpers/Memory.cpp b/src/src/Helpers/Memory.cpp index b4749f11cc..173e49e947 100644 --- a/src/src/Helpers/Memory.cpp +++ b/src/src/Helpers/Memory.cpp @@ -197,3 +197,73 @@ void* special_calloc(size_t num, size_t size) { return res; } + + +#ifdef ESP8266 +bool String_reserve_special(String& str, size_t size) { + if (str.length() >= size) { + // Nothing needs to be done + return true; + } + #ifdef USE_SECOND_HEAP + if (size >= 32) { + // Only try to store larger strings here as those tend to be kept for a longer period. + HeapSelectIram ephemeral; + // String does round up to nearest multiple of 16 bytes, so no need to round up to multiples of 32 bit here + if (str.reserve(size)) { + return true; + } + } + #endif + return str.reserve(size); +} +#endif + +#ifdef ESP32 + +// Special class to get access to the protected String functions +// This class only has a constructor which will perform +// the requested allocation in PSRAM when possible +class PSRAM_String : public String { + public: + PSRAM_String(size_t size) : String() { + if (size > capacity() && UsePSRAM()) { + size_t newSize = (size + 16) & (~0xf); + void *ptr = special_calloc(1, newSize); + if (ptr != nullptr) { + setSSO(false); + setBuffer((char *)ptr); + setCapacity(newSize - 1); + setLen(newSize - 1); // TD-er: Not sure if needed? + } + } + } +}; + + +bool String_reserve_special(String& str, size_t size) { + if (str.length() < size) { + // As we like to move this to PSRAM, it also makes sense + // to do this when the length equals size + PSRAM_String psram_str(size); + + if (psram_str.length() == 0) { + return str.reserve(size); + } + + // Copy any existing content + String tmp(std::move(str)); + + // Move the newly allocated buffer to a tmp String object. + // Needs to be empty, so the buffer is moved. + // N.B. String::clear() = String::setlen(0)) + str = std::move(psram_str); + str.clear(); + + if (tmp.length()) { + str = tmp; + } + } + return true; +} +#endif diff --git a/src/src/Helpers/Memory.h b/src/src/Helpers/Memory.h index e09ce027d4..06d1a30459 100644 --- a/src/src/Helpers/Memory.h +++ b/src/src/Helpers/Memory.h @@ -55,4 +55,7 @@ unsigned long getMaxFreeBlock(); void *special_malloc(uint32_t size); void *special_realloc(void *ptr, size_t size); -void *special_calloc(size_t num, size_t size); \ No newline at end of file +void *special_calloc(size_t num, size_t size); + + +bool String_reserve_special(String& str, size_t size); \ No newline at end of file diff --git a/src/src/Helpers/StringConverter.cpp b/src/src/Helpers/StringConverter.cpp index 7f312beaf9..6fb63f4456 100644 --- a/src/src/Helpers/StringConverter.cpp +++ b/src/src/Helpers/StringConverter.cpp @@ -90,6 +90,9 @@ void move_special(String& dest, String&& source) { } #endif // ifdef USE_SECOND_HEAP dest = std::move(source); + #ifdef ESP32 + reserve_special(dest, dest.length()); + #endif } String move_special(String&& source) { @@ -100,23 +103,7 @@ String move_special(String&& source) { bool reserve_special(String& str, size_t size) { - if (str.length() >= size) { - // Nothing needs to be done - return true; - } - // FIXME TD-er: Should also use this for ESP32 with PSRAM to allocate on PSRAM - #ifdef USE_SECOND_HEAP - if (size >= 32) { - // Only try to store larger strings here as those tend to be kept for a longer period. - HeapSelectIram ephemeral; - // String does round up to nearest multiple of 16 bytes, so no need to round up to multiples of 32 bit here - if (str.reserve(size)) { - return true; - } - } - #endif - return str.reserve(size); - // TD-er: should we also log here? + return String_reserve_special(str, size); }