Feature/lvgl 9.5 migration#37
Open
eleonel wants to merge 12 commits into
Open
Conversation
Stop the OOM-induced reset loops and harden JS app execution: - Remove both self-inflicted ESP.restart() paths (low-heap check that ran PSRAM-arena GC against internal-DRAM pressure, and the 36000-tick "maintenance reboot" that fired hourly with 100ms timers). - Replace device reboots with an in-place JS app restart: teardown of timers/widgets/styles/media/MQTT state, engine re-created over the same arena, script re-evaluated; safe mode with on-screen error after repeated failures. Boot-eval errors now show on the display. - Elk engine: backport upstream setprop OOM-corruption fix and ++/-- lvalue guard; re-enable auto-GC safely (gated on !F_CALL, 75% threshold); add js_usage/js_total accessors, per-eval statement budget (step limit) and C-stack ceiling so runaway scripts become recoverable JS errors instead of crashes. - Memory: LVGL heap now prefers PSRAM (keeps internal DRAM for TLS/lwip); fix 214KB PSRAM draw-buffer over-allocation; Elk arena size configurable via webscreen.json "js_heap_kb" (64-1024). - Crash fixes: bounded base64 decode in /upload (stack smash); slot-registry handles with validation replace pointer-as-double in chart/meter/span bindings; span text copied instead of pointing into the GC'd arena; GIF reload leak + mem-fs read underflow; SPI panel mutex (loopTask brightness vs JS-task flush race). - Reliability: WiFi/MQTT actually reconnect now; /load restarts the app in place (it never worked before — the reboot discarded the selection); new /restart_app and /gc commands; /stats reports JS arena usage, min free heap and largest free block; serial receive loops time out instead of hanging the loopTask; failed JS start falls back to the notification app; power-button pin gets its pull-up in the live path. - New JS API: mem_info(), gc(), timer_delete(), obj_delete(), gif_free(), ram_image_free(), mqtt_dropped(). - Structure: split the 3.7k-line lvgl_elk.h monolith into 14 ordered ws_*.h fragment headers (token-identical concatenation); remove the dead webscreen_main state machine, duplicate network client globals and runtime simulation stubs.
Review fixes (22 confirmed findings from multi-agent review): - elk.c: block auto-GC during F_NOEXEC function-body parsing (GC fired mid-expression with unrooted arena temporaries); count for(;;) loop iterations against the step budget (empty bodies executed zero statements and dodged it); propagate mkscope OOM instead of storing an error value as the scope chain. - obj_delete now releases chart-series/meter-scale/indicator/span registry slots owned by the deleted widget subtree (was a JS-reachable use-after-free write through stale handles). - Restart state machine: per-timer error streaks (a healthy timer no longer masks a broken one), automatic restarts can't lift safe mode, three streak-triggered restarts without a healthy interval park the app instead of churning forever, leftover timers from partially evaluated scripts are removed before entering safe mode, GC on error rate-limited to the first error of a streak. - /load and /restart_app report an honest error in fallback mode instead of printing success and doing nothing; over-long script paths rejected before teardown. - /stats "Min Free Heap" renamed "Heap Low Watermark" — the substring collided with WebScreen-Admin's 'Free Heap:' parser and corrupted the dashboard memory figure. - Span text no longer truncated at 255 bytes; ble_init returns false on identity mismatch instead of pretending the new UUIDs took effect; WiFi reconnect skipped on never-configured (offline) devices. Clarity refactor (behavior-preserving, JS API list verified byte-identical, flash -4KB): - 36 of 37 style setters collapsed to X-macro table entries (ws_lvgl_styles.h -287 lines, properties still grep-able). - HTTP GET/POST/DELETE share one request scaffold (ws_elk_http.h -200 lines; per-verb quirks like GET's retry loop preserved). - Serial commands dispatch from a single table that also generates /help, so help text can't drift from the implementation. - New shared js_arg_str() helper replaces 10 hand-rolled quote-strip sites. Docs: API.md, SerialCommands.md, CLAUDE.md, RELEASE_NOTES.md (Unreleased section), webscreen.json.example updated for the new APIs, commands, telemetry and js_heap_kb config.
…pin fix Serial console: - /screenshot (/ss): LVGL snapshot streamed as base64 RGB565, captured at the JS task safe point (same handoff pattern as /eval) - /download (/dl): binary-safe base64 file dump with size header/end marker - /mkdir; /rm now also removes empty directories - /factory_reset confirm: delete webscreen.json and reboot to fallback - /ls [path] [json]: machine-readable one-line listing for host tools; text listing gains a "Total: N files, M directories" end marker - /eval REPL error recording feeds /errors; upload ACK lines ([OK] File saved / [ERROR] Upload failed) for host-side verification - /wget alias renamed download -> fetch (frees /download) Critical fixes: - WEBSCREEN_PIN_BUTTON was GPIO 33: on ESP32-S3 with octal PSRAM, GPIOs 33-37 ARE the PSRAM bus, so the new pinMode() in setup() corrupted every PSRAM access and the device died at the next allocation (wedged panic, TG1WDT reset loop, no backtrace over USB-CDC). Button is now GPIO 21, the board's real user button; deep-sleep ext0 wakeup follows the same define. - LVGL allocator back to plain malloc: the PSRAM-first heap_caps_malloc_prefer routing put LVGL's hot small allocations on the slow OPI bus for no measured benefit. - SD mount restored to proven 400kHz probe + 10MHz remount sequence; mounting at high frequency directly wedges the card until power cycle. Version: 2.2.0-dev. The 0.2.3-dev string regressed WebScreen-Admin's capability detection (/upload requires reported major >= 2); back on the 2.x scheme matching git tags and main's 2.0.8. Docs: SerialCommands.md, API.md, README, CLAUDE.md, RELEASE_NOTES updated to match (byte-exact /help block, stream marker formats, /stats label fix).
…-and-pin-fix # Conflicts: # README.md # webscreen/build/esp32.esp32.esp32s3/webscreen.ino.bin # webscreen/build/esp32.esp32.esp32s3/webscreen.ino.elf # webscreen/build/esp32.esp32.esp32s3/webscreen.ino.map # webscreen/build/esp32.esp32.esp32s3/webscreen.ino.merged.bin # webscreen/webscreen_hardware.cpp
No code changes: stripped-comment sources and the compiled binary are byte-identical. Kept one-liners for hardware landmines (GPIO 33-37 = octal-PSRAM bus, SD 400 kHz-first mount), cross-task handoff invariants, and stream format contracts; removed history narration and paragraph rationales.
- New v9-format lv_conf.h (copy to ~/Arduino/libraries/lv_conf.h; the Arduino lvgl library folder must contain LVGL 9.5.0) - Display driver: lv_display_create/set_buffers/set_flush_cb; the panel's byte-swapped RGB565 becomes display color format RGB565_SWAPPED (LV_COLOR_16_SWAP no longer exists) - JS lv_meter_* API reimplemented on lv_scale (lv_meter removed upstream): needle line/image via lv_scale_set_*_needle_value, arcs as styled lv_arc children, scale lines as scale sections; JS signatures unchanged. Tick-gradient color and label_gap have no v9 equivalent (ignored) - lv_chart_set_zoom_x/y and lv_chart_set_axis_tick kept as no-op bindings (removed upstream) so LVGL 8 era scripts keep running - /screenshot: v9 lv_snapshot_take returns lv_draw_buf_t; streams plain RGB565 with matching header marker (host tools accept both) - Assets: boot logo converted to planar RGB565A8 (v9 image header, source shrinks 1.7MB -> 0.4MB); fallback GIF descriptor to LV_COLOR_FORMAT_RAW; RAM-image descriptors likewise - lv_timer_t is opaque in v9: timer bridge includes lvgl_private.h - Misc renames: lv_display_flush_ready, lv_spangroup_delete_span, lv_point_precise_t, lv_color_to_u16 (lv_color_t lost .full), typed style-setter casts (lv_border_side_t, lv_text_decor_t) Flash 3,032,515 bytes (96%, +82KB vs LVGL 8); static DRAM 124KB (37%). Compile-verified only — needs on-device testing (fallback GIF, JS apps, meters, screenshot).
Config (lv_conf.h): - Restore dark default theme: the theme flip made the fallback screen render white text on a white background - Re-enable the image cache (LV_CACHE_DEF_SIZE 512KB; was 0 = re-decode PNG/JPG on every refresh) - Disable ARCLABEL and BAR (nothing creates them) Meter emulation (ws_lvgl_charts.h): - Resolve layout before computing needle length; a meter built and set in the same frame got a 1px needle stub (width read as 0 pre-layout) - Size extra scales in pixels: lv_scale computes needle geometry from the raw style width, so lv_pct(100) placed needles millions of px off-screen - Arc r_mod: size the arc from the resolved scale size +/- r_mod on both signs (positive was dropped, negative shrank the radius twice as much) - Re-apply all indicators when set_scale_range changes the mapping - Align image needles so the pivot sits on the scale center (v9 only rotates; v8 lv_meter also positioned) Display buffers: - Declare draw buffers as bytes (2/px): v9's lv_color_t is 3 bytes, which silently grew the DRAM buffer 42KB->64KB and the fallback PSRAM buffer by 50%. Static DRAM back to 102.7KB (31%), same as before the migration Docs: SJPG is not supported by LVGL 9 at all — say so instead of advertising it (README, API.md, CLAUDE.md, release notes), and fix the contradictory enabled/disabled widget lists.
…tion # Conflicts: # CLAUDE.md # README.md # RELEASE_NOTES.md # docs/API.md # docs/SerialCommands.md # lv_conf.h # webscreen/fallback.cpp # webscreen/webscreen_runtime.cpp # webscreen/ws_elk_core.h # webscreen/ws_elk_media.h # webscreen/ws_lvgl_charts.h # webscreen/ws_lvgl_display.h # webscreen/ws_lvgl_styles.h # webscreen/ws_lvgl_widgets.h
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
No description provided.