diff --git a/APP/app_log.c b/APP/app_log.c index 9ac8080..348715d 100644 --- a/APP/app_log.c +++ b/APP/app_log.c @@ -51,11 +51,9 @@ static void app_log_flash_flush_page(void) s_flash_remain -= s_flash_page_len; s_flash_page_len = 0U; - /* 扇区边界或结束时 ACK,主机据此节流 */ - if ((s_flash_addr & 0xFFFU) == 0U || s_flash_remain == 0U) { - snprintf(ack, sizeof(ack), "FLASH_ACK %lu\n", (unsigned long)s_flash_addr); - SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, ack); - } + /* 每页 ACK,避免主机打爆 RTT 下行缓冲 */ + snprintf(ack, sizeof(ack), "FLASH_ACK %lu\n", (unsigned long)s_flash_addr); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, ack); } static void app_log_flash_feed(const uint8_t *data, unsigned len) @@ -266,6 +264,13 @@ uint8_t app_log_try_command(const char *cmd) app_log_flash_start(size); return 1U; } + if (strncmp(cmd, "ui boot", 7) == 0) { + LCD_BLK_Set(); + LCD_WR_PIC_FROM_FLASH(0, 0, UI0902_BOOT_LOGO_W, UI0902_BOOT_LOGO_H, + UI0902_BOOT_LOGO_ADDR); + SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "UI_BOOT_OK\n"); + return 1U; + } return 0U; } diff --git a/UI/UI_Idle.c b/UI/UI_Idle.c index cd05f8d..fbd3a97 100644 --- a/UI/UI_Idle.c +++ b/UI/UI_Idle.c @@ -181,8 +181,8 @@ void IdleProcess(DisplayTaskMessage_Type msg) { case MSG_ID_POWER_ON : LCD_BLK_Set(); - LCD_FillByColor(0, 0, 240, 320, WHITE); - LCD_WR_PIC_FROM_FLASH(40, 80, 168, 155, 0x00000000); + LCD_WR_PIC_FROM_FLASH(0, 0, UI0902_BOOT_LOGO_W, UI0902_BOOT_LOGO_H, + UI0902_BOOT_LOGO_ADDR); BSP_SelectAdcChannel(6); /* 让出 CPU,避免忙等卡住触摸/主循环线程 */ rt_thread_mdelay(1000); diff --git a/project/inc/UI0902_Res_Addr.h b/project/inc/UI0902_Res_Addr.h index 61bd7da..3029131 100644 --- a/project/inc/UI0902_Res_Addr.h +++ b/project/inc/UI0902_Res_Addr.h @@ -276,7 +276,11 @@ #define UI0902_TXT_RESTORE_CONFIRM_W 71 #define UI0902_TXT_RESTORE_CONFIRM_H 14 -#define UI0902_BTN_CANCEL_BIG_ADDR (UI0902_RES_BASE + 0x086000UL) /* 11872 bytes */ +#define UI0902_BOOT_LOGO_ADDR (UI0902_RES_BASE + 0x086000UL) /* 153600 bytes */ +#define UI0902_BOOT_LOGO_W 240 +#define UI0902_BOOT_LOGO_H 320 + +#define UI0902_BTN_CANCEL_BIG_ADDR (UI0902_RES_BASE + 0x0AC000UL) /* 11872 bytes */ #define UI0902_BTN_CANCEL_BIG_W 106 #define UI0902_BTN_CANCEL_BIG_H 56 diff --git a/tools/assets_0902/07_开机/开机界面-20.png b/tools/assets_0902/07_开机/开机界面-20.png new file mode 100644 index 0000000..a7dd0ac Binary files /dev/null and b/tools/assets_0902/07_开机/开机界面-20.png differ diff --git a/tools/flash_ui0902_res.py b/tools/flash_ui0902_res.py index d8294f7..0d88d16 100644 --- a/tools/flash_ui0902_res.py +++ b/tools/flash_ui0902_res.py @@ -91,9 +91,13 @@ def wait_for(jlink, marker: str, timeout_s: float = 30.0) -> str: def send_bytes(jlink, payload: bytes) -> None: off = 0 while off < len(payload): - n = jlink.rtt_write(0, list(payload[off : off + 128])) - if n <= 0: - time.sleep(0.01) + try: + n = jlink.rtt_write(0, list(payload[off : off + 64])) + except Exception: + time.sleep(0.05) + continue + if n is None or n <= 0: + time.sleep(0.02) continue off += n @@ -124,11 +128,9 @@ def main() -> None: _ = rtt_read_text(jlink, 0.3) if not args.no_reset: - # Hardware reset clears any stuck flash_mode from a previous attempt print("hardware reset...") jlink.reset(halt=False) time.sleep(3.5) - # RTT CB may move after reboot — re-find try: jlink.rtt_stop() except Exception: @@ -148,26 +150,23 @@ def main() -> None: print(log.strip().splitlines()[-1]) time.sleep(0.2) - # Smaller chunks + brief pause so erase/write can keep up with RTT down-buffer - chunk = 128 + chunk = 256 sent = 0 t0 = time.time() - send_bytes(jlink, data[0:256]) - sent = 256 - wait_for(jlink, "FLASH_RX", 20.0) - print("device receiving...") + receiving = False while sent < size: end = min(sent + chunk, size) send_bytes(jlink, data[sent:end]) sent = end - if sent % 256 == 0: - time.sleep(0.002) - if sent % 4096 == 0 or sent == size: - log = wait_for(jlink, "FLASH_ACK", 60.0) - if "FLASH_UI0902_OK" in log: - print(log.strip().splitlines()[-1]) - print("Done. Mode-select should redraw with new assets.") - return + # 一页对应一次 ACK;FLASH_RX 可能夹在同一次读缓冲里,勿分两次 wait + log = wait_for(jlink, "FLASH_ACK", 60.0) + if (not receiving) and ("FLASH_RX" in log or "FLASH_ACK" in log): + receiving = True + print("device receiving...") + if "FLASH_UI0902_OK" in log: + print(log.strip().splitlines()[-1]) + print("Done. Mode-select should redraw with new assets.") + return if sent % (64 * 1024) == 0 or sent == size: elapsed = time.time() - t0 print(f" {sent}/{size} ({100.0 * sent / size:.1f}%) {elapsed:.1f}s") diff --git a/tools/gen_ui0902_assets.py b/tools/gen_ui0902_assets.py index 21ecaee..544d63b 100644 --- a/tools/gen_ui0902_assets.py +++ b/tools/gen_ui0902_assets.py @@ -48,9 +48,26 @@ def rgba_to_rgb565(im): r = (r * a) // 255 g = (g * a) // 255 b = (b * a) // 255 - c = ((r >> 3) << 11) | ((g >> 2) << 5) | (b >> 3) - out[i] = (c >> 8) & 0xFF - out[i + 1] = c & 0xFF + v = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3) + out[i] = (v >> 8) & 0xFF + out[i + 1] = v & 0xFF + i += 2 + return bytes(out), w, h + + +def rgba_to_rgb565_opaque(im): + """Full-screen boot/charge: keep dark background pixels (no near-black punch-through).""" + im = im.convert("RGB") + px = im.load() + w, h = im.size + out = bytearray(w * h * 2) + i = 0 + for y in range(h): + for x in range(w): + r, g, b = px[x, y] + v = ((r & 0xF8) << 8) | ((g & 0xFC) << 3) | (b >> 3) + out[i] = (v >> 8) & 0xFF + out[i + 1] = v & 0xFF i += 2 return bytes(out), w, h @@ -172,6 +189,8 @@ EXTERNAL = [ ("TXT_RESTORE_V2", "06_控件/文字/文字-25.png"), ("TXT_RESTORE_H", "06_控件/文字/文字-26.png"), ("TXT_RESTORE_CONFIRM", "06_控件/文字/文字-27.png"), + # 整屏开机 Logo(避开旧 0x0 / 充电 0xCB70 区,挂在 ui0902 资源包末尾) + ("BOOT_LOGO", "07_开机/开机界面-20.png"), ] @@ -209,7 +228,15 @@ def main(): im = Image.open(SRC / rel) if name in ("ROW_UNIVERSAL_NOT", "ROW_UNIVERSAL_SEL", "ROW_NORMAL_NOT", "ROW_NORMAL_SEL", "ROW_EXPERT_NOT", "ROW_EXPERT_SEL"): im = im.resize(ROW_RESIZE, Image.LANCZOS) - data, w, h = rgba_to_rgb565(im) + data, w, h = rgba_to_rgb565(im) + elif name == "BOOT_LOGO": + if im.size[0] >= 241 and im.size[1] >= 321: + im = im.crop((0, 0, 240, 320)) + elif im.size != (240, 320): + im = im.resize((240, 320), Image.LANCZOS) + data, w, h = rgba_to_rgb565_opaque(im) + else: + data, w, h = rgba_to_rgb565(im) entries[name] = (offset, w, h, len(data)) blob += data pad = (-len(blob)) % ALIGN