From c2a8b21917fbedbe5c087f83da868704fa7eea3a Mon Sep 17 00:00:00 2001 From: raw-designs Date: Wed, 2 Sep 2026 02:26:24 +0200 Subject: [PATCH] fix(P4): DSI-Strecke beim Hochlauf einmal neu aufbauen (1.6.21) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Der Hochlauf lief zuletzt vollständig fehlerfrei durch - Bridge zweimal eingestellt, Panel zweimal geweckt, alle I2C-Bausteine erreichbar - und trotzdem kam beim ersten Einschalten kein Bild. Erst ein Reset half, und der zuverlässig. Es fehlte also kein Befehl mehr, sondern der Vorgang selbst: Ein Reset unterscheidet sich an dieser Stelle in genau einem Punkt von unserem Ablauf - die DSI-Verbindung geht einmal weg und neu auf, während Bridge und Panel bereits versorgt und eingestellt sind. Die Wiederholungen aus 1.6.19/1.6.20 liefen dagegen über eine durchgehend bestehende Verbindung. - Der DSI-Aufbau (Bus, Kommandokanal, Bildausgabe, Weckbefehle) steckt jetzt in ws7_dsi_bringup() und ist damit wiederholbar. - Nach dem ersten Durchlauf werden esp_lcd_panel_del(), esp_lcd_panel_io_del() und esp_lcd_del_dsi_bus() aufgerufen und die Strecke neu angelegt. Schalter WS7_DSI_RESTART, Pause WS7_DSI_RESTART_MS. Beide Panel-Varianten mit arduino-cli gegengebaut. Co-Authored-By: Claude Opus 5 Claude-Session: https://claude.ai/code/session_01P7JsiDJ1QbNFLDz5chf8Jt --- P4_Display_Firmware/Changelog.txt | 16 +++ P4_Display_Firmware/board_bringup.c | 155 ++++++++++++++++++---------- P4_Display_Firmware/pins_config.h | 8 ++ 3 files changed, 125 insertions(+), 54 deletions(-) diff --git a/P4_Display_Firmware/Changelog.txt b/P4_Display_Firmware/Changelog.txt index c704819..0b8ef53 100644 --- a/P4_Display_Firmware/Changelog.txt +++ b/P4_Display_Firmware/Changelog.txt @@ -1,3 +1,19 @@ +Version 1.6.21: +- Der Hochlauf lief zuletzt vollstaendig fehlerfrei durch - Bridge zweimal eingestellt, + Panel zweimal geweckt, alle I2C-Bausteine erreichbar - und trotzdem kam beim ersten + Einschalten kein Bild. Erst ein Reset half, und der zuverlaessig. Es fehlte also kein + Befehl mehr; es fehlte der Vorgang selbst. +- Ein Reset unterscheidet sich an dieser Stelle in genau einem Punkt: Die DSI-Verbindung + geht einmal weg und neu auf, waehrend Bridge und Panel bereits versorgt und eingestellt + sind. Weder die wiederholte Grundeinstellung noch die wiederholten Weckbefehle ersetzen + das - beide laufen ueber eine Verbindung, die durchgehend bestand. +- Der Hochlauf baut die DSI-Strecke jetzt einmal komplett ab und wieder auf: Bildausgabe, + Kommandokanal und Bus werden freigegeben und neu angelegt. Damit passiert ohne Reset, + was vorher erst der zweite Start brachte. Schalter WS7_DSI_RESTART in pins_config.h, + Pause dazwischen WS7_DSI_RESTART_MS (Vorgabe 200 ms). +- Der DSI-Aufbau steckt dafuer in einer eigenen Funktion, damit der Vorgang wiederholbar + ist statt zweimal im Quelltext zu stehen. + Version 1.6.20: - Nach 1.6.19 lief es reproduzierbar so ab: Beim Einschalten ging nach zwei bis drei Sekunden die Hintergrundbeleuchtung an, dann kam nichts mehr; nach einem Reset ging die diff --git a/P4_Display_Firmware/board_bringup.c b/P4_Display_Firmware/board_bringup.c index d69e8ef..5f7d61c 100644 --- a/P4_Display_Firmware/board_bringup.c +++ b/P4_Display_Firmware/board_bringup.c @@ -422,6 +422,84 @@ static void ws7_panel_wake(esp_lcd_panel_io_handle_t io, const char *wann) } #endif +#if JC_PANEL_TYPE == WS_PANEL_7H +// Baut die komplette DSI-Strecke auf: Bus, Kommandokanal, Bildausgabe, und weckt das +// Panel. Bewusst als eigene Funktion, damit der ganze Vorgang wiederholbar ist. +static bool ws7_dsi_bringup(esp_lcd_dsi_bus_handle_t *out_bus, + esp_lcd_panel_io_handle_t *out_io, + esp_lcd_panel_handle_t *out_panel, + esp_lcd_dpi_panel_config_t *out_dpi_config) +{ + esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; + esp_lcd_panel_io_handle_t io = NULL; + esp_lcd_panel_handle_t disp_panel = NULL; + + esp_lcd_dsi_bus_config_t bus_config = { + .bus_id = 0, + .num_data_lanes = WS7_DSI_LANES, + .phy_clk_src = MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F20M, + .lane_bit_rate_mbps = WS7_DSI_LANE_MBPS, + }; + BSP_STEP(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus), "MIPI-DSI-Bus"); + + esp_lcd_dbi_io_config_t dbi_config = { + .virtual_channel = 0, + .lcd_cmd_bits = 8, + .lcd_param_bits = 8, + }; + BSP_STEP(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io), "DBI-Kommandokanal"); + + esp_lcd_dpi_panel_config_t dpi_config = { + .virtual_channel = 0, + .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, + .dpi_clock_freq_mhz = WS7_DPI_CLOCK_MHZ, +#if WS7_COLOR_BITS == 24 + .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888, +#else + .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, +#endif + .num_fbs = LVGL_PORT_LCD_BUFFER_NUMS, + .video_timing = { + .h_size = BSP_LCD_H_RES, + .v_size = BSP_LCD_V_RES, + .hsync_back_porch = WS7_HSYNC_BACK, + .hsync_pulse_width = WS7_HSYNC_PULSE, + .hsync_front_porch = WS7_HSYNC_FRONT, + .vsync_back_porch = WS7_VSYNC_BACK, + .vsync_pulse_width = WS7_VSYNC_PULSE, + .vsync_front_porch = WS7_VSYNC_FRONT, + }, + .flags = { + .use_dma2d = true, + }, + }; + BSP_STEP(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &disp_panel), + "DPI-Panel (Framebuffer im PSRAM)"); + if (disp_panel == NULL) { + esp_rom_printf("[Panel] Abbruch: Panel wurde nicht angelegt. Haeufigste Ursache ist zu " + "wenig PSRAM - PSRAM in den Board-Einstellungen aktivieren oder in " + "pins_config.h weniger Framebuffer waehlen.\n"); + return false; + } + + ws7_panel_wake(io, "vor dem Start der Videoausgabe"); + + BSP_STEP(esp_lcd_panel_init(disp_panel), "DPI-Videoausgabe starten"); + + // Zweiter Anlauf, jetzt bei laufender Videoausgabe: faengt den Fall ab, dass das + // Panel beim ersten Mal noch nicht aufnahmebereit war. + vTaskDelay(pdMS_TO_TICKS(WS7_PANEL_SETTLE_MS)); + ws7_bridge_core_init("nach dem Start der Videoausgabe"); + ws7_panel_wake(io, "nach dem Start der Videoausgabe"); + + *out_bus = mipi_dsi_bus; + *out_io = io; + *out_panel = disp_panel; + *out_dpi_config = dpi_config; + return true; +} +#endif + // Bringt Panel + Touch + LVGL-Port hoch (LVGL laeuft danach in eigenem Task). // Rueckgabe false: Panel kam nicht hoch - der Aufrufer darf dann KEINE LVGL-Funktion // benutzen, sonst folgt ein zweiter Absturz, der die eigentliche Ursache ueberdeckt. @@ -483,9 +561,12 @@ bool jc_board_bringup(void) }; BSP_STEP(esp_ldo_acquire_channel(&ldo_cfg, &phy_pwr_chan), "Stromversorgung MIPI-D-PHY"); - esp_lcd_dsi_bus_handle_t mipi_dsi_bus; + esp_lcd_dsi_bus_handle_t mipi_dsi_bus = NULL; esp_lcd_panel_io_handle_t io = NULL; esp_lcd_panel_handle_t disp_panel = NULL; +#if JC_PANEL_TYPE == WS_PANEL_7H + esp_lcd_dpi_panel_config_t dpi_config; +#endif #if JC_PANEL_TYPE == WS_PANEL_7H // ---------------- Waveshare 7inch DSI LCD (H) (1280x720) ---------------- @@ -495,63 +576,29 @@ bool jc_board_bringup(void) bsp_report_psram((size_t)BSP_LCD_H_RES * BSP_LCD_V_RES * BSP_LCD_FB_BYTES_PER_PX * LVGL_PORT_LCD_BUFFER_NUMS); - esp_lcd_dsi_bus_config_t bus_config = { - .bus_id = 0, - .num_data_lanes = WS7_DSI_LANES, - .phy_clk_src = MIPI_DSI_PHY_PLLREF_CLK_SRC_PLL_F20M, - .lane_bit_rate_mbps = WS7_DSI_LANE_MBPS, - }; - BSP_STEP(esp_lcd_new_dsi_bus(&bus_config, &mipi_dsi_bus), "MIPI-DSI-Bus"); - - esp_lcd_dbi_io_config_t dbi_config = { - .virtual_channel = 0, - .lcd_cmd_bits = 8, - .lcd_param_bits = 8, - }; - BSP_STEP(esp_lcd_new_panel_io_dbi(mipi_dsi_bus, &dbi_config, &io), "DBI-Kommandokanal"); - - esp_lcd_dpi_panel_config_t dpi_config = { - .virtual_channel = 0, - .dpi_clk_src = MIPI_DSI_DPI_CLK_SRC_DEFAULT, - .dpi_clock_freq_mhz = WS7_DPI_CLOCK_MHZ, -#if WS7_COLOR_BITS == 24 - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB888, -#else - .pixel_format = LCD_COLOR_PIXEL_FORMAT_RGB565, -#endif - .num_fbs = LVGL_PORT_LCD_BUFFER_NUMS, - .video_timing = { - .h_size = BSP_LCD_H_RES, - .v_size = BSP_LCD_V_RES, - .hsync_back_porch = WS7_HSYNC_BACK, - .hsync_pulse_width = WS7_HSYNC_PULSE, - .hsync_front_porch = WS7_HSYNC_FRONT, - .vsync_back_porch = WS7_VSYNC_BACK, - .vsync_pulse_width = WS7_VSYNC_PULSE, - .vsync_front_porch = WS7_VSYNC_FRONT, - }, - .flags = { - .use_dma2d = true, - }, - }; - BSP_STEP(esp_lcd_new_panel_dpi(mipi_dsi_bus, &dpi_config, &disp_panel), - "DPI-Panel (Framebuffer im PSRAM)"); - if (disp_panel == NULL) { - esp_rom_printf("[Panel] Abbruch: Panel wurde nicht angelegt. Haeufigste Ursache ist zu " - "wenig PSRAM - PSRAM in den Board-Einstellungen aktivieren oder in " - "pins_config.h weniger Framebuffer waehlen.\n"); + if (!ws7_dsi_bringup(&mipi_dsi_bus, &io, &disp_panel, &dpi_config)) { return false; } - ws7_panel_wake(io, "vor dem Start der Videoausgabe"); +#if WS7_DSI_RESTART + // Die Strecke einmal komplett ab- und wieder aufbauen. + // + // Beim ersten Einschalten kam trotz fehlerfreiem Hochlauf kein Bild; erst ein Reset + // half, und zwar zuverlaessig. Ein Reset unterscheidet sich an dieser Stelle nur in + // einem Punkt von unserem Ablauf: Die DSI-Verbindung geht einmal weg und neu auf, + // waehrend Bridge und Panel bereits versorgt und eingestellt sind. Weder die + // wiederholte Grundeinstellung der Bridge noch die wiederholten Weckbefehle ersetzen + // das. Genau dieser Ab- und Wiederaufbau wird hier nachgeholt - ohne Reset. + esp_rom_printf("[Panel] DSI-Strecke wird neu aufgebaut\n"); + esp_lcd_panel_del(disp_panel); + esp_lcd_panel_io_del(io); + esp_lcd_del_dsi_bus(mipi_dsi_bus); + vTaskDelay(pdMS_TO_TICKS(WS7_DSI_RESTART_MS)); - BSP_STEP(esp_lcd_panel_init(disp_panel), "DPI-Videoausgabe starten"); - - // Zweiter Anlauf, jetzt bei laufender Videoausgabe: faengt den Fall ab, dass das - // Panel beim ersten Mal noch nicht aufnahmebereit war. - vTaskDelay(pdMS_TO_TICKS(WS7_PANEL_SETTLE_MS)); - ws7_bridge_core_init("nach dem Start der Videoausgabe"); - ws7_panel_wake(io, "nach dem Start der Videoausgabe"); + if (!ws7_dsi_bringup(&mipi_dsi_bus, &io, &disp_panel, &dpi_config)) { + return false; + } +#endif #if WS7_TEST_PATTERN // Prueffarbbalken: Sie entstehen im DSI-Baustein selbst und benutzen weder den // Bildspeicher noch LVGL. Erscheinen sie, arbeitet die Anzeigekette bis zum Panel und diff --git a/P4_Display_Firmware/pins_config.h b/P4_Display_Firmware/pins_config.h index 6fce2e5..f9a31e3 100644 --- a/P4_Display_Firmware/pins_config.h +++ b/P4_Display_Firmware/pins_config.h @@ -159,6 +159,14 @@ // Beleuchtung brennt - sie haengt an der Bridge, nicht am Panel. #define WS7_PANEL_SETTLE_MS 200 +// Die DSI-Strecke beim Hochlauf einmal ab- und wieder aufbauen. Beim ersten Einschalten +// kam sonst trotz fehlerfreiem Ablauf kein Bild; erst ein Reset half. Der einzige +// Unterschied dabei: Die DSI-Verbindung geht einmal weg und neu auf, waehrend Bridge und +// Panel schon versorgt und eingestellt sind. Genau das holt der zweite Aufbau nach. +// Kostet WS7_DSI_RESTART_MS zusaetzliche Startzeit. +#define WS7_DSI_RESTART 1 +#define WS7_DSI_RESTART_MS 200 + #define WS7_TEST_PATTERN 0 #elif JC_PANEL_TYPE == JC_PANEL_70 -- 2.54.0