From 5988668026d5f990690252f032692efc3a4c58a1 Mon Sep 17 00:00:00 2001 From: raw-designs Date: Thu, 3 Sep 2026 13:17:06 +0200 Subject: [PATCH] =?UTF-8?q?fix(P4):=20Glyphenpuffer=20ins=20PSRAM=20-=20be?= =?UTF-8?q?hebt=20Stillstand=20bei=20gro=C3=9Fer=20Standby-Uhr=20(1.9.8)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Ursache gefunden. lv_draw_label.c legt pro Glyphe einen A8-Draw-Buf an: box_w * LV_ROUND_UP(box_h, 32) Byte. Größte Ziffer des 360er-Fonts ist 190x247 -> 190*256 = 48 KB. Mit LV_DRAW_SW_DRAW_UNIT_CNT 2 sind zwei davon gleichzeitig offen, also ~97 KB. Der LVGL-Pool (LV_MEM_SIZE 256 KB) hatte laut Herzschlag nur 98068 Byte am Stück frei - es reichte knapp nicht. LV_USE_ASSERT_MALLOC ist 1 und LV_ASSERT_HANDLER war "while(1);". Bei fehlgeschlagener Allokation hält der LVGL-Task also stumm an: kein Panic, kein Backtrace, Log bricht einfach ab. Genau das beobachtete Bild. - font_buf_malloc/-free über lv_draw_buf_get_font_handlers(): Puffer ab 16 KB kommen per heap_caps_malloc aus dem PSRAM, kleinere weiter aus dem LVGL-Pool (schneller; sonst würde jeder Text langsamer). Freigabe unterscheidet über esp_ptr_external_ram(). - LV_ASSERT_HANDLER gibt jetzt eine Meldung aus, bevor er anhält. Der interne RAM bleibt unangetastet - LV_MEM_SIZE zu erhöhen war keine Option, der statische Speicher liegt bereits bei ~98 %. Beide Panel-Varianten mit arduino-cli gegengebaut. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01NeFMr439WcLMdebE3kU7fS --- P4_Display_Firmware/Changelog.txt | 12 +++++++++++ P4_Display_Firmware/lv_conf.h | 6 ++++-- P4_Display_Firmware/ui.cpp | 35 +++++++++++++++++++++++++++++++ 3 files changed, 51 insertions(+), 2 deletions(-) diff --git a/P4_Display_Firmware/Changelog.txt b/P4_Display_Firmware/Changelog.txt index 3f7f158..dcdea60 100644 --- a/P4_Display_Firmware/Changelog.txt +++ b/P4_Display_Firmware/Changelog.txt @@ -1,3 +1,15 @@ +Version 1.9.8: +- Der Stillstand beim Wechsel in den Standby ist gefunden und behoben. LVGL legt für JEDE + Textglyphe einen eigenen Zwischenpuffer an - bei der großen Uhr rund 48 KB pro Ziffer, mit + zwei parallel arbeitenden Zeicheneinheiten fast 100 KB gleichzeitig. Der interne + LVGL-Speicher hatte nur rund 98 KB am Stück frei; es reichte knapp nicht. Schlägt die + Anforderung fehl, hält LVGL per Zusicherung in einer Endlosschleife an - kein Absturz, + keine Meldung, das Display steht einfach. Deshalb brach der Mitschnitt ohne Fehler ab. +- Große Glyphenpuffer liegen jetzt im externen Speicher (PSRAM, 32 MB frei). Kleine bleiben + im internen, der ist schneller - sonst würde jeder Text langsamer. +- Hält LVGL künftig wegen einer verletzten Zusicherung an, sagt es das jetzt, statt stumm + stehen zu bleiben. + Version 1.9.7: - Messpunkte für den Stillstand beim Wechsel in den Standby: Beide Abläufe - der Haupt- und der Zeichenablauf - melden jetzt alle zwei Sekunden einen Herzschlag mit Speicherstand. diff --git a/P4_Display_Firmware/lv_conf.h b/P4_Display_Firmware/lv_conf.h index fae483c..793c519 100644 --- a/P4_Display_Firmware/lv_conf.h +++ b/P4_Display_Firmware/lv_conf.h @@ -374,8 +374,10 @@ #define LV_USE_ASSERT_OBJ 0 /*Check the object's type and existence (e.g. not deleted). (Slow)*/ /*Add a custom handler when assert happens e.g. to restart the MCU*/ -#define LV_ASSERT_HANDLER_INCLUDE -#define LV_ASSERT_HANDLER while(1); /*Halt by default*/ +#define LV_ASSERT_HANDLER_INCLUDE +// Frueher hielt LVGL hier stumm in einer Endlosschleife an - das Display stand, ohne dass +// irgendwo etwas davon zu sehen war. Jetzt sagt es wenigstens, dass es angehalten hat. +#define LV_ASSERT_HANDLER esp_rom_printf("[LVGL] Zusicherung verletzt - Zeichenablauf haelt an\n"); while(1); /*------------- * Debug diff --git a/P4_Display_Firmware/ui.cpp b/P4_Display_Firmware/ui.cpp index d8d52fa..0cb1357 100644 --- a/P4_Display_Firmware/ui.cpp +++ b/P4_Display_Firmware/ui.cpp @@ -18,6 +18,7 @@ #include #include #include // Dashboard-Design P4-lokal merken (NVS) +#include // esp_ptr_external_ram(): welcher Speicher einen Puffer traegt #include // Verlaufs-Historie im PSRAM allozieren (interner RAM ist knapp) #include "ui.h" #include @@ -3571,6 +3572,36 @@ static void ui_heartbeat_cb(lv_timer_t*) { (unsigned)m.free_size, (unsigned)m.total_size, (unsigned)m.free_biggest_size); } +// LVGL legt fuer JEDE Textglyphe einen eigenen Zwischenpuffer an - Breite mal Hoehe, ein +// Byte je Bildpunkt. Bei der grossen Standby-Uhr sind das 190 x 256 = rund 48 KB pro Ziffer, +// und mit zwei parallel arbeitenden Zeicheneinheiten fast 100 KB gleichzeitig. Der interne +// LVGL-Speicher fasst nur 245 KB, wovon rund 98 KB am Stueck frei sind - es reichte knapp +// nicht. Schlaegt die Anforderung fehl, haelt LVGL per Zusicherung in einer Endlosschleife +// an: kein Absturz, keine Meldung, das Display steht einfach. Genau das war der Stillstand +// beim Wechsel in den Standby. +// +// Diese Puffer wandern daher in den externen Speicher (PSRAM, 32 MB frei). Kleine Glyphen +// bleiben im internen Speicher, weil der schneller ist und Text sonst ueberall langsamer +// wuerde; nur die grossen gehen nach aussen. +#define FONT_BUF_EXTERN_AB 16384 // ab dieser Groesse in den externen Speicher + +static void* font_buf_malloc(size_t size, lv_color_format_t cf) { + LV_UNUSED(cf); + size += LV_DRAW_BUF_ALIGN - 1; + if (size >= FONT_BUF_EXTERN_AB) { + void* p = heap_caps_malloc(size, MALLOC_CAP_SPIRAM | MALLOC_CAP_8BIT); + if (p) return p; + } + return lv_malloc(size); +} + +static void font_buf_free(void* buf) { + // Der externe Speicher liegt ausserhalb des LVGL-Bereichs; daran ist zu erkennen, + // welcher der beiden Wege den Puffer vergeben hat. + if (esp_ptr_external_ram(buf)) heap_caps_free(buf); + else lv_free(buf); +} + static void refr_monitor_install() { lv_display_t* d = lv_display_get_default(); if (!d) return; @@ -3981,6 +4012,10 @@ void ui_init(ProtocolClient* client) { show_page(PG_DASH); if (g_client) g_client->sendListProfiles(); + // Glyphenpuffer umlenken, bevor der erste Text gezeichnet wird. + lv_draw_buf_handlers_t* fh = lv_draw_buf_get_font_handlers(); + fh->buf_malloc_cb = font_buf_malloc; + fh->buf_free_cb = font_buf_free; refr_monitor_install(); lv_timer_create(ui_heartbeat_cb, 2000, nullptr); g_uiReady = true; -- 2.54.0