fix 3.5 white-screen reboot from LVGL OOM on wifi scan.

Lazy-create keyboard, compact scan rows, skip auto-scan at boot; standalone cyd_35r flags with BL=27.

Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
2026-10-25 19:56:51 +08:00
parent ba09f4f48e
commit 9cbbb296b7
5 changed files with 102 additions and 50 deletions

View File

@@ -1,5 +1,5 @@
name: CYD wifitest (cyd_35r)
git: unknown
git: ba09f4f
date: 2026-10-25
board: ESP32-3248S035 (ST7796)
flash_size: 4MB
@@ -11,5 +11,5 @@ offsets:
sha256:
bootloader.bin 3D234A7471F67B013686DABD4DEE7C1FA915C9928463616A94BC9297ACF1ABF8
boot_app0.bin F94C5D786A7A8FAB06AC5D10E33BF37711A6697636DC037559EA19CC410A17F0
firmware.bin 6E6DBCB9E886AF2FA0A894092CA0C9B8C28BA74D03BB6E7B26F175E943D32F5D
firmware.bin 8632B39F60FF68A0ABD39C49071FF91889F5446D0EC93F7ADF59CDA48AB6D438
partitions.bin 148B959CBFF1C38AA8E1D5C0BA9D612C54997B945E56A63F41223EEF650653A1

Binary file not shown.

View File

@@ -59,22 +59,60 @@ extra_scripts = pre:copy_lv_conf.py
; Build: pio run -e cyd_35r
; Keep TOUCH_CS=-1 — GPIO33 is GT911 SDA, not resistive touch CS.
; TFT_BL=GPIO27 (not 21 — 21 is GT911 INT). See ../CYD_PROJECT_GUIDE.md
; Standalone flags (no extends) so ILI9341 / BL=21 / big MEM cannot linger.
[env:cyd_35r]
extends = env:cyd
build_unflags =
-DILI9341_2_DRIVER=1
-DTFT_WIDTH=240
-DTFT_HEIGHT=320
-DTFT_BL=21
-DLV_MEM_SIZE=49152
platform = espressif32
board = esp32dev
framework = arduino
monitor_speed = 460800
upload_speed = 460800
board_build.partitions = default.csv
lib_deps =
bodmer/TFT_eSPI@^2.5.43
lvgl/lvgl@9.2.2
extra_scripts = pre:copy_lv_conf.py
build_flags =
${env:cyd.build_flags}
-DCORE_DEBUG_LEVEL=0
-DUSER_SETUP_LOADED=1
-DST7796_DRIVER=1
-DTFT_WIDTH=320
-DTFT_HEIGHT=480
-DTFT_MISO=12
-DTFT_MOSI=13
-DTFT_SCLK=14
-DTFT_CS=15
-DTFT_DC=2
-DTFT_RST=-1
-DTFT_BL=27
-DCYD_BOARD_3248S035=1
-DTFT_BACKLIGHT_ON=HIGH
-DTOUCH_CS=-1
-DLOAD_GLCD=1
-DLOAD_FONT2=1
-DLOAD_FONT4=1
-DLOAD_FONT6=1
-DLOAD_FONT7=1
-DLOAD_FONT8=1
-DLOAD_GFXFF=1
-DSMOOTH_FONT=1
-DSPI_FREQUENCY=40000000
-DSPI_READ_FREQUENCY=20000000
-DUSE_HSPI_PORT
-DSUPPORT_TRANSACTIONS
-DTFT_RGB_ORDER=TFT_BGR
-DCYD_BOARD_3248S035=1
-DLV_CONF_SKIP
-DLV_COLOR_DEPTH=16
-DLV_MEM_SIZE=32768
-DLV_FONT_MONTSERRAT_14=1
-DLV_FONT_MONTSERRAT_16=1
-DLV_FONT_MONTSERRAT_18=1
-DLV_FONT_MONTSERRAT_20=1
-DLV_USE_TFT_ESPI=1
-DLV_USE_FLEX=1
-DLV_USE_BUTTON=1
-DLV_USE_LABEL=1
-DLV_USE_LIST=1
-DLV_USE_TEXTAREA=1
-DLV_USE_KEYBOARD=1
-DLV_USE_BTNMATRIX=1
-I${PROJECT_DIR}/include

View File

@@ -16,6 +16,10 @@ void setup() {
Serial.println();
Serial.printf("LVGL %d.%d.%d | CYD WiFi Prov\n", lv_version_major(),
lv_version_minor(), lv_version_patch());
Serial.println("BOOT_OK");
Serial.printf("heap=%u BL=%d panel=%dx%d ui=%dx%d\n",
(unsigned)ESP.getFreeHeap(), TFT_BL_PIN, SCREEN_WIDTH,
SCREEN_HEIGHT, UI_HOR_RES, UI_VER_RES);
pinMode(TFT_BL_PIN, OUTPUT);
digitalWrite(TFT_BL_PIN, HIGH);
@@ -34,6 +38,7 @@ void setup() {
wifi_prov_begin();
wifi_ui_create();
Serial.printf("ui_ok heap=%u\n", (unsigned)ESP.getFreeHeap());
}
void loop() {

View File

@@ -87,6 +87,25 @@ static void set_pass_visible(bool visible) {
}
}
static void on_kb(lv_event_t *e); /* defined below — used by ensure_keyboard */
static void ensure_keyboard() {
if (kb || !scr_setup || !ta_pass) {
return;
}
kb = lv_keyboard_create(scr_setup);
if (!kb) {
Serial.println("[ui] OOM: keyboard");
return;
}
lv_obj_set_size(kb, UI_HOR_RES, UH(110));
lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, UX(0), UY(0));
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_TEXT_LOWER);
lv_keyboard_set_textarea(kb, ta_pass);
lv_obj_add_event_cb(kb, on_kb, LV_EVENT_ALL, nullptr);
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
}
static void show_password_dialog(const char *ssid) {
strncpy(g_pick_ssid, ssid, WIFI_PROV_SSID_MAX);
g_pick_ssid[WIFI_PROV_SSID_MAX] = '\0';
@@ -97,6 +116,7 @@ static void show_password_dialog(const char *ssid) {
lv_textarea_set_text(ta_pass, "");
}
set_pass_visible(false);
ensure_keyboard();
if (overlay) {
lv_obj_clear_flag(overlay, LV_OBJ_FLAG_HIDDEN);
lv_obj_move_foreground(overlay);
@@ -134,16 +154,23 @@ static void rebuild_list() {
if (g_item_n <= 0) {
lv_obj_t *lab = lv_label_create(list_wifi);
if (!lab) {
return;
}
lv_label_set_text(lab, "No networks. Tap Scan.");
lv_obj_set_style_text_color(lab, lv_color_hex(COL_MUTED), 0);
return;
}
// 行本身不可点,只有右侧 Join 按钮才会配网,避免滚动误触
/* Compact rows (label + Join) — 3.5 UI + keyboard needs LV_MEM headroom. */
for (int i = 0; i < g_item_n; ++i) {
lv_obj_t *row = lv_obj_create(list_wifi);
if (!row) {
Serial.printf("[ui] OOM at wifi row %d/%d\n", i, g_item_n);
break;
}
lv_obj_set_width(row, lv_pct(100));
lv_obj_set_height(row, UH(36));
lv_obj_set_height(row, UH(34));
lv_obj_set_style_bg_color(row, lv_color_hex(0x121A24), 0);
lv_obj_set_style_bg_opa(row, LV_OPA_COVER, 0);
lv_obj_set_style_border_width(row, 0, 0);
@@ -154,47 +181,36 @@ static void rebuild_list() {
lv_obj_set_flex_flow(row, LV_FLEX_FLOW_ROW);
lv_obj_set_flex_align(row, LV_FLEX_ALIGN_SPACE_BETWEEN, LV_FLEX_ALIGN_CENTER,
LV_FLEX_ALIGN_CENTER);
// 行/信息区不接点击:触摸落到父列表上,整区可拖滚动;只有 Join 可点
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_clear_flag(row, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_flag(row, LV_OBJ_FLAG_EVENT_BUBBLE);
lv_obj_t *info = lv_obj_create(row);
lv_obj_set_flex_grow(info, 1);
lv_obj_set_height(info, lv_pct(100));
lv_obj_set_style_bg_opa(info, LV_OPA_TRANSP, 0);
lv_obj_set_style_border_width(info, 0, 0);
lv_obj_set_style_pad_all(info, 0, 0);
lv_obj_clear_flag(info, LV_OBJ_FLAG_SCROLLABLE);
lv_obj_clear_flag(info, LV_OBJ_FLAG_CLICKABLE);
lv_obj_add_flag(info, LV_OBJ_FLAG_EVENT_BUBBLE);
char line[56];
snprintf(line, sizeof(line), LV_SYMBOL_WIFI " %s", g_items[i].ssid);
lv_obj_t *lab = lv_label_create(info);
char line[64];
snprintf(line, sizeof(line), LV_SYMBOL_WIFI " %s %ddBm", g_items[i].ssid,
(int)g_items[i].rssi);
lv_obj_t *lab = lv_label_create(row);
if (!lab) {
break;
}
lv_label_set_text(lab, line);
lv_label_set_long_mode(lab, LV_LABEL_LONG_DOT);
lv_obj_set_width(lab, lv_pct(100));
lv_obj_set_flex_grow(lab, 1);
lv_obj_set_style_text_color(lab, lv_color_hex(COL_INK), 0);
lv_obj_set_style_text_font(lab, &lv_font_montserrat_14, 0);
lv_obj_align(lab, LV_ALIGN_LEFT_MID, UX(0), UY(-6));
char rssi[16];
snprintf(rssi, sizeof(rssi), "%d dBm", (int)g_items[i].rssi);
lv_obj_t *lab_r = lv_label_create(info);
lv_label_set_text(lab_r, rssi);
lv_obj_set_style_text_color(lab_r, lv_color_hex(COL_MUTED), 0);
lv_obj_set_style_text_font(lab_r, &lv_font_montserrat_14, 0);
lv_obj_align(lab_r, LV_ALIGN_LEFT_MID, UX(0), UY(8));
lv_obj_t *join = lv_button_create(row);
if (!join) {
break;
}
lv_obj_set_size(join, UW(56), UH(28));
style_btn(join, COL_BTN_ACC);
lv_obj_t *jl = lv_label_create(join);
lv_label_set_text(jl, "Join");
lv_obj_set_style_text_color(jl, lv_color_hex(COL_INK), 0);
lv_obj_set_style_text_font(jl, &lv_font_montserrat_14, 0);
lv_obj_center(jl);
if (jl) {
lv_label_set_text(jl, "Join");
lv_obj_set_style_text_color(jl, lv_color_hex(COL_INK), 0);
lv_obj_set_style_text_font(jl, &lv_font_montserrat_14, 0);
lv_obj_center(jl);
}
lv_obj_add_event_cb(join, on_row_join, LV_EVENT_CLICKED,
(void *)(intptr_t)i);
}
@@ -467,14 +483,7 @@ static void build_setup() {
lv_obj_clear_flag(row, LV_OBJ_FLAG_SCROLLABLE);
make_btn(row, "Back", COL_BTN, on_dlg_back, UW(70), UH(26));
make_btn(row, "Join", COL_BTN_ACC, on_join, UW(70), UH(26));
kb = lv_keyboard_create(scr_setup);
lv_obj_set_size(kb, UI_HOR_RES, UH(110));
lv_obj_align(kb, LV_ALIGN_BOTTOM_MID, UX(0), UY(0));
lv_keyboard_set_mode(kb, LV_KEYBOARD_MODE_TEXT_LOWER);
lv_keyboard_set_textarea(kb, ta_pass);
lv_obj_add_event_cb(kb, on_kb, LV_EVENT_ALL, nullptr);
lv_obj_add_flag(kb, LV_OBJ_FLAG_HIDDEN);
/* Keyboard is created lazily in show_password_dialog (saves LV_MEM on 3.5). */
}
void wifi_ui_create() {
@@ -485,7 +494,7 @@ void wifi_ui_create() {
wifi_ui_show_status();
} else {
wifi_ui_show_setup();
do_scan();
set_setup_status("Tap Scan");
}
refresh_status_labels();
}