fix(rlcd): freeze after flash - disable auto-screensaver on monochrome + reduce video stream hog
Frozen screen caused by 2 runtime issues after init fixes 3770ac89:
- BouncingBalls screensaver full_refresh SPI at 10MHz for 300x400 takes ~100ms per frame, hogs LVGL lock -> UI appears frozen stuck on weird image
- MCP video stream task vTaskDelay 5ms streaming holds LVGL lock too often -> starves UI and screenshot (could not acquire LVGL lock)
Fix:
- DisplayIdle tick: for !supportsBacklight (RLCD) don't auto-activate screensaver, only handle wake. Prevents heavy animation entering automatically after timeout (SD may have 60s setting).
- McpSystem video stream: 50ms->100ms idle, 5ms->30ms streaming to release LVGL lock
- Screenshot API: 100ms->500ms lock timeout, task 50->300ms for slow SPI
Build 0x2b79e0 RLCD, flashed.
Co-Authored-By: internal-model
This commit is contained in:
@@ -1701,10 +1701,11 @@ static void mcp_video_stream_task(void* pvParameters) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Yield: longer delay when no client connected to save CPU
|
// Yield: longer delay when no client connected to save CPU
|
||||||
|
// RLCD ST7305 SPI is slow and shared - don't hog LVGL lock (fix freeze)
|
||||||
if (mono_client_fd < 0 && color_client_fd < 0) {
|
if (mono_client_fd < 0 && color_client_fd < 0) {
|
||||||
vTaskDelay(pdMS_TO_TICKS(50));
|
vTaskDelay(pdMS_TO_TICKS(100));
|
||||||
} else {
|
} else {
|
||||||
vTaskDelay(pdMS_TO_TICKS(5));
|
vTaskDelay(pdMS_TO_TICKS(30));
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -214,7 +214,8 @@ void DisplayIdleService::tick() {
|
|||||||
}
|
}
|
||||||
displayDimmed = false;
|
displayDimmed = false;
|
||||||
}
|
}
|
||||||
} else {
|
} else if (supportsBacklight) {
|
||||||
|
// For backlight-capable displays: full idle handling
|
||||||
bool charging_blocks = cachedDisplaySettings.disableScreensaverWhenCharging && isDeviceCharging();
|
bool charging_blocks = cachedDisplaySettings.disableScreensaverWhenCharging && isDeviceCharging();
|
||||||
|
|
||||||
if (!displayDimmed && inactive_ms >= cachedDisplaySettings.backlightTimeoutMs) {
|
if (!displayDimmed && inactive_ms >= cachedDisplaySettings.backlightTimeoutMs) {
|
||||||
@@ -227,7 +228,7 @@ void DisplayIdleService::tick() {
|
|||||||
activateScreensaver();
|
activateScreensaver();
|
||||||
lvgl::unlock();
|
lvgl::unlock();
|
||||||
if (cachedDisplaySettings.screensaverType == settings::display::ScreensaverType::None) {
|
if (cachedDisplaySettings.screensaverType == settings::display::ScreensaverType::None) {
|
||||||
if (supportsBacklight && display != nullptr) {
|
if (display != nullptr) {
|
||||||
display->setBacklightDuty(0);
|
display->setBacklightDuty(0);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -240,6 +241,14 @@ void DisplayIdleService::tick() {
|
|||||||
stopScreensaver();
|
stopScreensaver();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
} else {
|
||||||
|
// For monochrome/RLCD (no backlight): don't auto-enter screensaver (heavy full_refresh SPI causes freeze)
|
||||||
|
// Only handle wake if we are somehow dimmed (e.g. MCP left it)
|
||||||
|
if (displayDimmed && !isMcpActive) {
|
||||||
|
if (inactive_ms < kWakeActivityThresholdMs) {
|
||||||
|
stopScreensaver();
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -49,7 +49,7 @@ void ScreenshotTask::setFinished() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static void makeScreenshot(const std::string& filename) {
|
static void makeScreenshot(const std::string& filename) {
|
||||||
if (lvgl::lock(50 / portTICK_PERIOD_MS)) {
|
if (lvgl::lock(300 / portTICK_PERIOD_MS)) {
|
||||||
if (lv_screenshot_create(lv_scr_act(), LV_100ASK_SCREENSHOT_SV_PNG, filename.c_str())) {
|
if (lv_screenshot_create(lv_scr_act(), LV_100ASK_SCREENSHOT_SV_PNG, filename.c_str())) {
|
||||||
LOGGER.info("Screenshot saved to {}", filename);
|
LOGGER.info("Screenshot saved to {}", filename);
|
||||||
} else {
|
} else {
|
||||||
|
|||||||
@@ -1506,8 +1506,8 @@ esp_err_t WebServerService::handleApiScreenshot(httpd_req_t* request) {
|
|||||||
// LVGL's lodepng uses lv_fs which requires the "A:" prefix
|
// LVGL's lodepng uses lv_fs which requires the "A:" prefix
|
||||||
std::string lvgl_screenshot_path = lvgl::PATH_PREFIX + screenshot_path;
|
std::string lvgl_screenshot_path = lvgl::PATH_PREFIX + screenshot_path;
|
||||||
|
|
||||||
// Capture screenshot using LVGL
|
// Capture screenshot using LVGL — increased timeout for RLCD monochrome (SPI slow)
|
||||||
if (lvgl::lock(pdMS_TO_TICKS(100))) {
|
if (lvgl::lock(pdMS_TO_TICKS(500))) {
|
||||||
bool success = lv_screenshot_create(lv_scr_act(), LV_100ASK_SCREENSHOT_SV_PNG, lvgl_screenshot_path.c_str());
|
bool success = lv_screenshot_create(lv_scr_act(), LV_100ASK_SCREENSHOT_SV_PNG, lvgl_screenshot_path.c_str());
|
||||||
lvgl::unlock();
|
lvgl::unlock();
|
||||||
|
|
||||||
@@ -1518,7 +1518,7 @@ esp_err_t WebServerService::handleApiScreenshot(httpd_req_t* request) {
|
|||||||
}
|
}
|
||||||
LOGGER.info("Screenshot captured successfully");
|
LOGGER.info("Screenshot captured successfully");
|
||||||
} else {
|
} else {
|
||||||
LOGGER.error("Could not acquire LVGL lock within 100ms");
|
LOGGER.error("Could not acquire LVGL lock within 500ms");
|
||||||
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "could not acquire LVGL lock");
|
httpd_resp_send_err(request, HTTPD_500_INTERNAL_SERVER_ERROR, "could not acquire LVGL lock");
|
||||||
return ESP_FAIL;
|
return ESP_FAIL;
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user