-
-
Notifications
You must be signed in to change notification settings - Fork 3.9k
Improvements to heap-memory and PSRAM handling #4791
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from 2 commits
b96a950
516aa62
48fbb1d
9bd9d32
ec29161
32743ab
f9d0c19
39870f8
0328f5c
2c7ac77
b8bd2a7
477b13a
190262f
c665d59
1560ce4
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -88,18 +88,17 @@ extern byte realtimeMode; // used in getMappedPixelIndex() | |
| #endif | ||
| #define FPS_CALC_SHIFT 7 // bit shift for fixed point math | ||
|
|
||
| /* each segment uses 82 bytes of SRAM memory, so if you're application fails because of | ||
| insufficient memory, decreasing MAX_NUM_SEGMENTS may help */ | ||
| // heap memory limit for effects data, pixel buffers try to reserve it if PSRAM is available | ||
| #ifdef ESP8266 | ||
| #define MAX_NUM_SEGMENTS 16 | ||
| /* How much data bytes all segments combined may allocate */ | ||
| #define MAX_SEGMENT_DATA 5120 | ||
| #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*640) // 10k by default | ||
| #elif defined(CONFIG_IDF_TARGET_ESP32S2) | ||
| #define MAX_NUM_SEGMENTS 20 | ||
| #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*512) // 10k by default (S2 is short on free RAM) | ||
| #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1024) // 20k by default (S2 is short on free RAM) | ||
|
||
| #else | ||
| #define MAX_NUM_SEGMENTS 32 // warning: going beyond 32 may consume too much RAM for stable operation | ||
| #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1280) // 40k by default | ||
| #define MAX_SEGMENT_DATA (MAX_NUM_SEGMENTS*1920) // 60k by default | ||
| #endif | ||
|
|
||
| /* How much data bytes each segment should max allocate to leave enough space for other segments, | ||
|
|
@@ -600,8 +599,8 @@ class Segment { | |
| , _t(nullptr) | ||
| { | ||
| DEBUGFX_PRINTF_P(PSTR("-- Creating segment: %p [%d,%d:%d,%d]\n"), this, (int)start, (int)stop, (int)startY, (int)stopY); | ||
| // allocate render buffer (always entire segment) | ||
| pixels = static_cast<uint32_t*>(d_calloc(sizeof(uint32_t), length())); // error handling is also done in isActive() | ||
| // allocate render buffer (always entire segment), prefer PSRAM if DRAM is running low. Note: impact on FPS with PSRAM buffer is low (<2% with QSPI PSRAM) | ||
| pixels = static_cast<uint32_t*>(allocate_buffer(length() * sizeof(uint32_t), BFRALLOC_PREFER_PSRAM | BFRALLOC_NOBYTEACCESS | BFRALLOC_CLEAR)); | ||
| if (!pixels) { | ||
| DEBUGFX_PRINTLN(F("!!! Not enough RAM for pixel buffer !!!")); | ||
| extern byte errorFlag; | ||
|
|
||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -550,7 +550,10 @@ inline uint8_t hw_random8() { return HW_RND_REGISTER; }; | |
| inline uint8_t hw_random8(uint32_t upperlimit) { return (hw_random8() * upperlimit) >> 8; }; // input range 0-255 | ||
| 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 | ||
|
|
||
| // PSRAM allocation wrappers | ||
| // memory allocation wrappers | ||
| #ifdef CONFIG_IDF_TARGET_ESP32 | ||
| void *pixelbuffer_malloc(size_t size, bool enforcePSRAM = false); // prefer IRAM for pixel buffers if possible | ||
| #endif | ||
|
||
| #if !defined(ESP8266) && !defined(CONFIG_IDF_TARGET_ESP32C3) | ||
| extern "C" { | ||
| void *p_malloc(size_t); // prefer PSRAM over DRAM | ||
|
|
@@ -579,6 +582,20 @@ extern "C" { | |
| #define d_realloc_malloc realloc_malloc | ||
| #define d_free free | ||
| #endif | ||
| #ifndef ESP8266 | ||
| inline size_t getFreeHeapSize() { return heap_caps_get_free_size(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); } // returns free heap (ESP.getFreeHeap() can include other memory types) | ||
| inline size_t getContiguousFreeHeap() { return heap_caps_get_largest_free_block(MALLOC_CAP_INTERNAL | MALLOC_CAP_8BIT); } // returns largest contiguous free block | ||
| #else | ||
| inline size_t getFreeHeapSize() { return ESP.getFreeHeap(); } // returns free heap | ||
| inline size_t getContiguousFreeHeap() { return ESP.getMaxFreeBlockSize(); } // returns largest contiguous free block | ||
| #endif | ||
| #define BFRALLOC_NOBYTEACCESS (1 << 0) // ESP32 has 32bit accessible DRAM (usually ~50kB free) that must not be byte-accessed | ||
| #define BFRALLOC_PREFER_DRAM (1 << 1) // prefer DRAM over PSRAM | ||
| #define BFRALLOC_ENFORCE_DRAM (1 << 2) // use DRAM only, no PSRAM | ||
| #define BFRALLOC_PREFER_PSRAM (1 << 3) // prefer PSRAM over DRAM | ||
| #define BFRALLOC_ENFORCE_PSRAM (1 << 4) // use PSRAM if available, otherwise fall back to DRAM | ||
| #define BFRALLOC_CLEAR (1 << 5) // clear allocated buffer after allocation | ||
| void *allocate_buffer(size_t size, uint32_t type); | ||
|
|
||
| // RAII guard class for the JSON Buffer lock | ||
| // Modeled after std::lock_guard | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
That's a lot (and I mean a lot) for ESP8266.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if you can give me a scenario that is critical in ram usage, I can test.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
4 usermods (PIR, temperature, 4LD, AR) and 16x16 matrix
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
works fine:
Free heap: 16384, Contiguous: 11344
Main:
Free heap: 15720, Contiguous: 7272
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Did you enable MQTT and use GPIO3?
Uh oh!
There was an error while loading. Please reload this page.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
no, I dont have the hardware to do that, you'd need to check with your setup.
edit:
since this is all about free heap : if it works in main, I see no reason it should not work with this PR
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
maybe the condition to delete and reallocate of the segmentdata should not be
FAIR_DATA_PER_SEGbut something a bit larger, might help with fragmentation on ESP8266