Skip to content

Commit 3ce0cc7

Browse files
committed
added realloc_malloc functions, increased min heap constant
- ESP32 C3 has no PSRAM, it now uses default alloc functions - also added missing UI info for "Error 7"
1 parent 633eb04 commit 3ce0cc7

File tree

6 files changed

+48
-15
lines changed

6 files changed

+48
-15
lines changed

wled00/FX_fcn.cpp

Lines changed: 5 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -160,12 +160,9 @@ bool Segment::allocateData(size_t len) {
160160
}
161161
// prefer DRAM over SPI RAM on ESP32 since it is slow
162162
if (data) {
163-
void* newData = d_realloc(data, len);
164-
if (newData) // realloc returns null if it fails but does not free the original pointer in that case
165-
data = (byte*)newData;
166-
else {
167-
d_free(data); // free old data if realloc failed
168-
data = nullptr; // reset pointer to null
163+
data = (byte*)d_realloc_malloc(data, len); // realloc with malloc fallback
164+
if (!data) {
165+
data = nullptr;
169166
Segment::addUsedSegmentData(-_dataLen); // subtract original buffer size
170167
_dataLen = 0; // reset data length
171168
}
@@ -459,7 +456,7 @@ void Segment::setGeometry(uint16_t i1, uint16_t i2, uint8_t grp, uint8_t spc, ui
459456
}
460457
// re-allocate FX render buffer
461458
if (length() != oldLength) {
462-
if (pixels) d_free(pixels); //pixels = static_cast<uint32_t*>(d_realloc(pixels, sizeof(uint32_t) * length())); // using realloc can cause additional fragmentation instead of reducing it
459+
if (pixels) d_free(pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
463460
pixels = static_cast<uint32_t*>(d_malloc(sizeof(uint32_t) * length()));
464461
if (!pixels) {
465462
DEBUG_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!"));
@@ -1199,7 +1196,7 @@ void WS2812FX::finalizeInit() {
11991196
deserializeMap(); // (re)load default ledmap (will also setUpMatrix() if ledmap does not exist)
12001197

12011198
// allocate frame buffer after matrix has been set up (gaps!)
1202-
if (_pixels) d_free(_pixels);
1199+
if (_pixels) d_free(_pixels); // using realloc on large buffers can cause additional fragmentation instead of reducing it
12031200
_pixels = static_cast<uint32_t*>(d_malloc(getLengthTotal() * sizeof(uint32_t)));
12041201
DEBUG_PRINTF_P(PSTR("strip buffer size: %uB\n"), getLengthTotal() * sizeof(uint32_t));
12051202

wled00/bus_manager.cpp

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -36,25 +36,29 @@ uint8_t realtimeBroadcast(uint8_t type, IPAddress client, uint16_t length, const
3636

3737
//util.cpp
3838
// PSRAM allocation wrappers
39-
#ifndef ESP8266
39+
#if !defined(ESP8266) && !defined(CONFIG_IDF_TARGET_ESP32C3)
4040
extern "C" {
4141
void *p_malloc(size_t); // prefer PSRAM over DRAM
4242
void *p_calloc(size_t, size_t); // prefer PSRAM over DRAM
4343
void *p_realloc(void *, size_t); // prefer PSRAM over DRAM
44+
void *p_realloc_malloc(void *ptr, size_t size); // realloc with malloc fallback, prefer PSRAM over DRAM
4445
inline void p_free(void *ptr) { heap_caps_free(ptr); }
4546
void *d_malloc(size_t); // prefer DRAM over PSRAM
4647
void *d_calloc(size_t, size_t); // prefer DRAM over PSRAM
4748
void *d_realloc(void *, size_t); // prefer DRAM over PSRAM
49+
void *d_realloc_malloc(void *ptr, size_t size); // realloc with malloc fallback, prefer DRAM over PSRAM
4850
inline void d_free(void *ptr) { heap_caps_free(ptr); }
4951
}
5052
#else
5153
#define p_malloc malloc
5254
#define p_calloc calloc
5355
#define p_realloc realloc
56+
#define p_realloc_malloc realloc_malloc
5457
#define p_free free
5558
#define d_malloc malloc
5659
#define d_calloc calloc
5760
#define d_realloc realloc
61+
#define d_realloc_malloc realloc_malloc
5862
#define d_free free
5963
#endif
6064

wled00/const.h

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -546,8 +546,8 @@ static_assert(WLED_MAX_BUSSES <= 32, "WLED_MAX_BUSSES exceeds hard limit");
546546
#endif
547547
#endif
548548

549-
//#define MIN_HEAP_SIZE
550-
#define MIN_HEAP_SIZE 2048
549+
// minimum heap size required to process web requests
550+
#define MIN_HEAP_SIZE 8192
551551

552552
// Web server limits
553553
#ifdef ESP8266

wled00/data/index.js

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1527,6 +1527,9 @@ function readState(s,command=false)
15271527
case 3:
15281528
errstr = "Buffer locked!";
15291529
break;
1530+
case 7:
1531+
errstr = "No RAM for buffer!";
1532+
break;
15301533
case 8:
15311534
errstr = "Effect RAM depleted!";
15321535
break;

wled00/fcn_declare.h

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -551,25 +551,29 @@ inline uint8_t hw_random8(uint32_t upperlimit) { return (hw_random8() * upperlim
551551
inline uint8_t hw_random8(uint32_t lowerlimit, uint32_t upperlimit) { uint32_t range = upperlimit - lowerlimit; return lowerlimit + hw_random8(range); }; // input range 0-255
552552

553553
// PSRAM allocation wrappers
554-
#ifndef ESP8266
554+
#if !defined(ESP8266) && !defined(CONFIG_IDF_TARGET_ESP32C3)
555555
extern "C" {
556556
void *p_malloc(size_t); // prefer PSRAM over DRAM
557557
void *p_calloc(size_t, size_t); // prefer PSRAM over DRAM
558558
void *p_realloc(void *, size_t); // prefer PSRAM over DRAM
559+
void *p_realloc_malloc(void *ptr, size_t size); // realloc with malloc fallback, prefer PSRAM over DRAM
559560
inline void p_free(void *ptr) { heap_caps_free(ptr); }
560561
void *d_malloc(size_t); // prefer DRAM over PSRAM
561562
void *d_calloc(size_t, size_t); // prefer DRAM over PSRAM
562563
void *d_realloc(void *, size_t); // prefer DRAM over PSRAM
564+
void *d_realloc_malloc(void *ptr, size_t size); // realloc with malloc fallback, prefer DRAM over PSRAM
563565
inline void d_free(void *ptr) { heap_caps_free(ptr); }
564566
}
565567
#else
566568
#define p_malloc malloc
567569
#define p_calloc calloc
568570
#define p_realloc realloc
571+
#define p_realloc_malloc realloc_malloc
569572
#define p_free free
570573
#define d_malloc malloc
571574
#define d_calloc calloc
572575
#define d_realloc realloc
576+
#define d_realloc_malloc realloc_malloc
573577
#define d_free free
574578
#endif
575579

wled00/util.cpp

Lines changed: 28 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -619,7 +619,8 @@ int32_t hw_random(int32_t lowerlimit, int32_t upperlimit) {
619619
return hw_random(diff) + lowerlimit;
620620
}
621621

622-
#ifndef ESP8266
622+
#if !defined(ESP8266) && !defined(CONFIG_IDF_TARGET_ESP32C3) // ESP8266 does not support PSRAM, ESP32-C3 does not have PSRAM
623+
// p_x prefer PSRAM, d_x prefer DRAM
623624
void *p_malloc(size_t size) {
624625
int caps1 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
625626
int caps2 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
@@ -640,6 +641,14 @@ void *p_realloc(void *ptr, size_t size) {
640641
return heap_caps_realloc(ptr, size, caps2);
641642
}
642643

644+
// realloc with malloc fallback, original buffer is freed if realloc fails but not copied!
645+
void *p_realloc_malloc(void *ptr, size_t size) {
646+
void *newbuf = p_realloc(ptr, size); // try realloc first
647+
if (newbuf) return newbuf; // realloc successful
648+
p_free(ptr); // free old buffer if realloc failed
649+
return p_malloc(size); // fallback to malloc
650+
}
651+
643652
void *p_calloc(size_t count, size_t size) {
644653
int caps1 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
645654
int caps2 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
@@ -654,7 +663,7 @@ void *d_malloc(size_t size) {
654663
int caps1 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
655664
int caps2 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
656665
if (psramSafe) {
657-
if (size > MIN_HEAP_SIZE) std::swap(caps1, caps2); // prefer PSRAM for large alloactions
666+
if (heap_caps_get_largest_free_block(caps1) < 3*MIN_HEAP_SIZE && size > MIN_HEAP_SIZE) std::swap(caps1, caps2); // prefer PSRAM for large alloactions & when DRAM is low
658667
return heap_caps_malloc_prefer(size, 2, caps1, caps2); // otherwise prefer DRAM
659668
}
660669
return heap_caps_malloc(size, caps1);
@@ -664,12 +673,20 @@ void *d_realloc(void *ptr, size_t size) {
664673
int caps1 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
665674
int caps2 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
666675
if (psramSafe) {
667-
if (size > MIN_HEAP_SIZE) std::swap(caps1, caps2); // prefer PSRAM for large alloactions
676+
if (heap_caps_get_largest_free_block(caps1) < 3*MIN_HEAP_SIZE && size > MIN_HEAP_SIZE) std::swap(caps1, caps2); // prefer PSRAM for large alloactions & when DRAM is low
668677
return heap_caps_realloc_prefer(ptr, size, 2, caps1, caps2); // otherwise prefer DRAM
669678
}
670679
return heap_caps_realloc(ptr, size, caps1);
671680
}
672681

682+
// realloc with malloc fallback, original buffer is freed if realloc fails but not copied!
683+
void *d_realloc_malloc(void *ptr, size_t size) {
684+
void *newbuf = d_realloc(ptr, size); // try realloc first
685+
if (newbuf) return newbuf; // realloc successful
686+
d_free(ptr); // free old buffer if realloc failed
687+
return d_malloc(size); // fallback to malloc
688+
}
689+
673690
void *d_calloc(size_t count, size_t size) {
674691
int caps1 = MALLOC_CAP_DEFAULT | MALLOC_CAP_8BIT;
675692
int caps2 = MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT;
@@ -679,6 +696,14 @@ void *d_calloc(size_t count, size_t size) {
679696
}
680697
return heap_caps_calloc(count, size, caps1);
681698
}
699+
#else // ESP8266 & ESP32-C3
700+
// realloc with malloc fallback, original buffer is freed if realloc fails but not copied!
701+
void *realloc_malloc(void *ptr, size_t size) {
702+
void *newbuf = realloc(ptr, size); // try realloc first
703+
if (newbuf) return newbuf; // realloc successful
704+
free(ptr); // free old buffer if realloc failed
705+
return malloc(size); // fallback to malloc
706+
}
682707
#endif
683708

684709
/*

0 commit comments

Comments
 (0)