-
-
Notifications
You must be signed in to change notification settings - Fork 4k
Fix for cfg exceeding LED limit #4939
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 all commits
db310c6
97f68b3
f8ca0f9
465d816
8e0ab4d
52e443d
ac529e7
70015bf
40039bf
12991d8
9c145dc
70359f9
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 | ||
|---|---|---|---|---|
|
|
@@ -40,8 +40,8 @@ void WLED::reset() | |||
|
|
||||
| void WLED::loop() | ||||
| { | ||||
| static uint32_t lastHeap = UINT32_MAX; | ||||
| static unsigned long heapTime = 0; | ||||
| static uint16_t heapTime = 0; // timestamp for heap check | ||||
| static uint8_t heapDanger = 0; // counter for consecutive low-heap readings | ||||
| #ifdef WLED_DEBUG | ||||
| static unsigned long lastRun = 0; | ||||
| unsigned long loopMillis = millis(); | ||||
|
|
@@ -169,19 +169,47 @@ void WLED::loop() | |||
| correctPIN = false; | ||||
| } | ||||
|
|
||||
| // reconnect WiFi to clear stale allocations if heap gets too low | ||||
| if (millis() - heapTime > 15000) { | ||||
| uint32_t heap = getFreeHeapSize(); | ||||
| if (heap < MIN_HEAP_SIZE && lastHeap < MIN_HEAP_SIZE) { | ||||
| DEBUG_PRINTF_P(PSTR("Heap too low! %u\n"), heap); | ||||
| strip.resetSegments(); // remove all but one segments from memory | ||||
| if (!Update.isRunning()) forceReconnect = true; | ||||
| } else if (heap < MIN_HEAP_SIZE) { | ||||
| DEBUG_PRINTLN(F("Heap low, purging segments.")); | ||||
| strip.purgeSegments(); | ||||
| // free memory and reconnect WiFi to clear stale allocations if heap is too low for too long, check once every 5s | ||||
| if ((uint16_t)(millis() - heapTime) > 5000) { | ||||
| #ifdef ESP8266 | ||||
| uint32_t heap = getFreeHeapSize(); // ESP8266 needs ~8k of free heap for UI to work properly | ||||
| #else | ||||
| #ifdef CONFIG_IDF_TARGET_ESP32C3 | ||||
| // calling getContiguousFreeHeap() during led update causes glitches on C3 | ||||
| // this can (probably) be removed once RMT driver for C3 is fixed | ||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @DedeHai this reminds me of something. I've seen similar behaviour also on other esp32 boards - especially esp32 and -S3, and a few times on -S2 too.
My educated guess here was that something inside ESP.getFreeHeap() uses some kind of "big kernel lock" that suspends everything while counting free heap bytes. Maybe it would also help in upstream to avoid heap size checking while RMT is sending out LEDs. Its definitely not just a -C3 only problem.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Edit: a similar, unguarded call that you might want to protect is here: Line 838 in 4f96886
this is running in webServer context when you refresh the main UI, so there is a possibility that this leads to flickering, too.
Collaborator
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. doh, that is the command I was looking for last week and could not remember. The C3 flickers whenever flash is accessed or other blocking processes run, like the free heap check. Its also an issue in the image FX when running animated gif's, that is where I wanted to add a check to not load a new gif frame while LEDs are being updated.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. maybe my famous "be nice but not too nice" code would help: unsigned t0 = millis();
while (strip.isUpdating() && (millis() - t0 < 15)) delay(1); // be nice, but not too nice. Waits up to 15msyou could also use Don't use yield() on esp32, because yield() does not work like on 8266.
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
Yes, it locks the heap and has to walk the free lists. It's quite expensive. We may someday want to think about some other approach to heap usage monitoring -- the web server has the same problem trying to estimate heap availability. |
||||
| unsigned t0 = millis(); | ||||
| while (strip.isUpdating() && (millis() - t0 < 15)) delay(1); // be nice, but not too nice. Waits up to 15ms | ||||
| #endif | ||||
| uint32_t heap = getContiguousFreeHeap(); // ESP32 family needs ~10k of contiguous free heap for UI to work properly | ||||
| #endif | ||||
| if (heap < MIN_HEAP_SIZE - 1024) heapDanger+=5; // allow 1k of "wiggle room" for things that do not respect min heap limits | ||||
| else heapDanger = 0; | ||||
| switch (heapDanger) { | ||||
| case 15: // 15 consecutive seconds | ||||
| DEBUG_PRINTLN(F("Heap low, purging segments")); | ||||
| strip.purgeSegments(); | ||||
| strip.setTransition(0); // disable transitions | ||||
| for (unsigned i = 0; i < strip.getSegmentsNum(); i++) { | ||||
| strip.getSegments()[i].setMode(FX_MODE_STATIC); // set static mode to free effect memory | ||||
| } | ||||
| errorFlag = ERR_NORAM; // alert UI TODO: make this a distinct error: segment reset | ||||
| break; | ||||
| case 30: // 30 consecutive seconds | ||||
| DEBUG_PRINTLN(F("Heap low, reset segments")); | ||||
| strip.resetSegments(); // remove all but one segments from memory | ||||
| errorFlag = ERR_NORAM; // alert UI TODO: make this a distinct error: segment reset | ||||
| break; | ||||
| case 45: // 45 consecutive seconds | ||||
| DEBUG_PRINTF_P(PSTR("Heap panic! Reset strip, reset connection\n")); | ||||
| strip.~WS2812FX(); // deallocate strip and all its memory | ||||
| new(&strip) WS2812FX(); // re-create strip object, respecting current memory limits | ||||
| if (!Update.isRunning()) forceReconnect = true; // in case wifi is broken, make sure UI comes back, set disableForceReconnect = true to avert | ||||
| errorFlag = ERR_NORAM; // alert UI TODO: make this a distinct error: strip reset | ||||
| break; | ||||
| default: | ||||
| break; | ||||
| } | ||||
| lastHeap = heap; | ||||
| heapTime = millis(); | ||||
| heapTime = (uint16_t)millis(); | ||||
| } | ||||
|
|
||||
| //LED settings have been saved, re-init busses | ||||
|
|
||||
Uh oh!
There was an error while loading. Please reload this page.