Fix mode-row asset pairing and add RTT external UI flash path.
- Map 0902 rows as 16/19 universal, 17/20 normal, 18/21 expert - Add flash ui0902 RTT writer; avoid LCD dump stealing down bytes - Restore UI_ReturnToModeSelect; shrink flash-trans RAM use - Disable mode-select debug touch crosses Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
parent
f8675e3529
commit
e62c2270af
|
|
@ -14,11 +14,95 @@ static char s_debug_level = 'D';
|
||||||
static char s_cmd_buf[48];
|
static char s_cmd_buf[48];
|
||||||
static uint8_t s_cmd_len;
|
static uint8_t s_cmd_len;
|
||||||
|
|
||||||
|
/* RTT 二进制烧录:将 ui0902_res.bin 写到 W25Q128 @ UI0902_RES_BASE */
|
||||||
|
static uint8_t s_flash_mode;
|
||||||
|
static uint32_t s_flash_addr;
|
||||||
|
static uint32_t s_flash_remain;
|
||||||
|
static uint32_t s_flash_last_sector;
|
||||||
|
static uint16_t s_flash_page_len;
|
||||||
|
static uint8_t s_flash_page[256];
|
||||||
|
|
||||||
|
uint8_t app_log_flash_busy(void)
|
||||||
|
{
|
||||||
|
return s_flash_mode;
|
||||||
|
}
|
||||||
|
|
||||||
static uint32_t app_log_ms(void)
|
static uint32_t app_log_ms(void)
|
||||||
{
|
{
|
||||||
return (uint32_t)(rt_tick_get() * 1000U / RT_TICK_PER_SECOND);
|
return (uint32_t)(rt_tick_get() * 1000U / RT_TICK_PER_SECOND);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void app_log_flash_flush_page(void)
|
||||||
|
{
|
||||||
|
uint32_t sector;
|
||||||
|
char ack[40];
|
||||||
|
|
||||||
|
if (s_flash_page_len == 0U) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
sector = s_flash_addr & ~0xFFFU;
|
||||||
|
if (sector != s_flash_last_sector) {
|
||||||
|
W25Q128_Erase_Sector(sector);
|
||||||
|
s_flash_last_sector = sector;
|
||||||
|
}
|
||||||
|
W25Q128_Write(s_flash_page, s_flash_addr, s_flash_page_len);
|
||||||
|
s_flash_addr += s_flash_page_len;
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void app_log_flash_feed(const uint8_t *data, unsigned len)
|
||||||
|
{
|
||||||
|
unsigned i;
|
||||||
|
|
||||||
|
for (i = 0; i < len && s_flash_remain > 0U; i++) {
|
||||||
|
if (s_flash_page_len == 0U && s_flash_addr == UI0902_RES_BASE && i == 0U) {
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_RX\n");
|
||||||
|
}
|
||||||
|
s_flash_page[s_flash_page_len++] = data[i];
|
||||||
|
if (s_flash_page_len >= sizeof(s_flash_page) ||
|
||||||
|
s_flash_page_len >= s_flash_remain) {
|
||||||
|
app_log_flash_flush_page();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (s_flash_remain == 0U && s_flash_mode) {
|
||||||
|
s_flash_mode = 0U;
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_UI0902_OK\n");
|
||||||
|
UI_DrawModeSelectScreen();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static void app_log_flash_start(uint32_t size)
|
||||||
|
{
|
||||||
|
char msg[64];
|
||||||
|
|
||||||
|
if (size == 0U || size > (2U * 1024U * 1024U)) {
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, "FLASH_UI0902_ERR size\n");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
s_flash_mode = 1U;
|
||||||
|
s_flash_addr = UI0902_RES_BASE;
|
||||||
|
s_flash_remain = size;
|
||||||
|
s_flash_last_sector = 0xFFFFFFFFUL;
|
||||||
|
s_flash_page_len = 0U;
|
||||||
|
s_cmd_len = 0U;
|
||||||
|
s_cmd_buf[0] = '\0';
|
||||||
|
|
||||||
|
snprintf(msg, sizeof(msg),
|
||||||
|
"FLASH_UI0902_GO base=0x%08lX size=%lu\n",
|
||||||
|
(unsigned long)UI0902_RES_BASE, (unsigned long)size);
|
||||||
|
SEGGER_RTT_WriteString(APP_LOG_RTT_CHANNEL, msg);
|
||||||
|
}
|
||||||
|
|
||||||
static void app_log_slot_store(const char *line)
|
static void app_log_slot_store(const char *line)
|
||||||
{
|
{
|
||||||
uint16_t idx = s_head;
|
uint16_t idx = s_head;
|
||||||
|
|
@ -177,6 +261,11 @@ uint8_t app_log_try_command(const char *cmd)
|
||||||
app_log_sys_reset();
|
app_log_sys_reset();
|
||||||
return 1U;
|
return 1U;
|
||||||
}
|
}
|
||||||
|
if (strncmp(cmd, "flash ui0902 ", 13) == 0) {
|
||||||
|
uint32_t size = (uint32_t)strtoul(cmd + 13, NULL, 10);
|
||||||
|
app_log_flash_start(size);
|
||||||
|
return 1U;
|
||||||
|
}
|
||||||
return 0U;
|
return 0U;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -207,7 +296,7 @@ static void app_log_feed_char(char c)
|
||||||
|
|
||||||
void app_log_poll(void)
|
void app_log_poll(void)
|
||||||
{
|
{
|
||||||
char rx[16];
|
uint8_t rx[64];
|
||||||
unsigned read_len;
|
unsigned read_len;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
|
@ -216,8 +305,13 @@ void app_log_poll(void)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (s_flash_mode) {
|
||||||
|
app_log_flash_feed(rx, read_len);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
for (i = 0; i < read_len; i++) {
|
for (i = 0; i < read_len; i++) {
|
||||||
app_log_feed_char(rx[i]);
|
app_log_feed_char((char)rx[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -234,5 +328,6 @@ void app_log_write(char level, const char *cat, const char *fmt, ...) { (void)le
|
||||||
void app_log_poll(void) {}
|
void app_log_poll(void) {}
|
||||||
uint8_t app_log_try_command(const char *cmd) { (void)cmd; return 0U; }
|
uint8_t app_log_try_command(const char *cmd) { (void)cmd; return 0U; }
|
||||||
void app_log_set_ui_page(const char *name) { (void)name; }
|
void app_log_set_ui_page(const char *name) { (void)name; }
|
||||||
|
uint8_t app_log_flash_busy(void) { return 0U; }
|
||||||
|
|
||||||
#endif /* APP_LOG_ENABLE */
|
#endif /* APP_LOG_ENABLE */
|
||||||
|
|
|
||||||
|
|
@ -34,6 +34,7 @@ void app_log_write(char level, const char *cat, const char *fmt, ...);
|
||||||
void app_log_poll(void);
|
void app_log_poll(void);
|
||||||
uint8_t app_log_try_command(const char *cmd);
|
uint8_t app_log_try_command(const char *cmd);
|
||||||
void app_log_set_ui_page(const char *name);
|
void app_log_set_ui_page(const char *name);
|
||||||
|
uint8_t app_log_flash_busy(void);
|
||||||
|
|
||||||
#if APP_LOG_ENABLE
|
#if APP_LOG_ENABLE
|
||||||
|
|
||||||
|
|
|
||||||
15
UI/UI_Idle.c
15
UI/UI_Idle.c
|
|
@ -71,6 +71,16 @@ static void UI_ModeSelect_DrawButtons(void)
|
||||||
UI_ModeSelect_DrawButtonAt(2);
|
UI_ModeSelect_DrawButtonAt(2);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void UI_ReturnToModeSelect(void)
|
||||||
|
{
|
||||||
|
StartFlag = 0;
|
||||||
|
InModeFlag = false;
|
||||||
|
AutoBandTop1_Stop();
|
||||||
|
s_mode_select_focus = 0;
|
||||||
|
CallUI_Idle();
|
||||||
|
UI_DrawModeSelectScreen();
|
||||||
|
}
|
||||||
|
|
||||||
void UI_DrawModeSelectScreen(void)
|
void UI_DrawModeSelectScreen(void)
|
||||||
{
|
{
|
||||||
UI_ClearFocus();
|
UI_ClearFocus();
|
||||||
|
|
@ -80,7 +90,7 @@ void UI_DrawModeSelectScreen(void)
|
||||||
label_top();
|
label_top();
|
||||||
UI_ModeSelect_DrawButtons();
|
UI_ModeSelect_DrawButtons();
|
||||||
Draw_Bottom_Bar(UI0902_NAV_MODE, 0);
|
Draw_Bottom_Bar(UI0902_NAV_MODE, 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
const Touch_AreaTypeDef Touch_ModeSelect_Areas[] = {
|
const Touch_AreaTypeDef Touch_ModeSelect_Areas[] = {
|
||||||
/* Flag=按钮序号(0万能/1普通/2专业);ID=进入 TAB */
|
/* Flag=按钮序号(0万能/1普通/2专业);ID=进入 TAB */
|
||||||
|
|
@ -230,8 +240,6 @@ void IdleProcess(DisplayTaskMessage_Type msg)
|
||||||
LOG_I("UI", "mode_select hit area=%u row=%u focus=%u x=%u y=%u",
|
LOG_I("UI", "mode_select hit area=%u row=%u focus=%u x=%u y=%u",
|
||||||
(unsigned)k, (unsigned)row, (unsigned)s_mode_select_focus,
|
(unsigned)k, (unsigned)row, (unsigned)s_mode_select_focus,
|
||||||
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
|
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
|
||||||
/* 调试十字:确认触点是否落在按钮上 */
|
|
||||||
TP_Drow_Touch_Point(msg.HiByte, msg.LoByte, RED);
|
|
||||||
/* 已聚焦 → 进入;未聚焦 → 切蓝焦点,再点一次进入 */
|
/* 已聚焦 → 进入;未聚焦 → 切蓝焦点,再点一次进入 */
|
||||||
if (row == s_mode_select_focus) {
|
if (row == s_mode_select_focus) {
|
||||||
if (now - s_last_enter_ms < 300U)
|
if (now - s_last_enter_ms < 300U)
|
||||||
|
|
@ -248,7 +256,6 @@ void IdleProcess(DisplayTaskMessage_Type msg)
|
||||||
if (!hit) {
|
if (!hit) {
|
||||||
LOG_I("UI", "mode_select miss x=%u y=%u",
|
LOG_I("UI", "mode_select miss x=%u y=%u",
|
||||||
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
|
(unsigned)msg.HiByte, (unsigned)msg.LoByte);
|
||||||
TP_Drow_Touch_Point(msg.HiByte, msg.LoByte, YELLOW);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
|
|
|
||||||
|
|
@ -236,24 +236,26 @@ void LCD_WR_PIC_ClipX(uint16_t x, uint16_t y, uint16_t full_w, uint16_t h,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* 从W25Q128读小图到RAM后透明显示(跳过近黑像素),仅用于 <=4KB 小图 */
|
/* 从 W25Q128 按行读取并透明显示(跳过近黑像素),复用 pic_batch_buf,无大块静态 RAM */
|
||||||
#define PIC_TRANS_BUF_SIZE 4096
|
|
||||||
void LCD_WR_PIC_FROM_FLASH_Trans(uint16_t x, uint16_t y, uint16_t length, uint16_t width, uint32_t flash_addr)
|
void LCD_WR_PIC_FROM_FLASH_Trans(uint16_t x, uint16_t y, uint16_t length, uint16_t width, uint32_t flash_addr)
|
||||||
{
|
{
|
||||||
static uint8_t s_trans_buf[PIC_TRANS_BUF_SIZE];
|
uint16_t row, col;
|
||||||
uint32_t total_bytes = (uint32_t)length * width * 2;
|
uint32_t row_bytes = (uint32_t)length * 2U;
|
||||||
uint32_t i;
|
if (length == 0 || width == 0 || row_bytes > PIC_BATCH_SIZE) return;
|
||||||
if (total_bytes == 0 || total_bytes > PIC_TRANS_BUF_SIZE) return;
|
|
||||||
W25Q128_Read(s_trans_buf, flash_addr, (uint16_t)total_bytes);
|
for (row = 0; row < width; row++)
|
||||||
for (i = 0; i < total_bytes / 2; i++)
|
|
||||||
{
|
{
|
||||||
uint16_t c = (uint16_t)((s_trans_buf[i * 2] << 8) | s_trans_buf[i * 2 + 1]);
|
W25Q128_Read(pic_batch_buf, flash_addr + row * row_bytes, (uint16_t)row_bytes);
|
||||||
uint8_t r5 = (uint8_t)((c >> 11) & 0x1F);
|
for (col = 0; col < length; col++)
|
||||||
uint8_t g6 = (uint8_t)((c >> 5) & 0x3F);
|
{
|
||||||
uint8_t b5 = (uint8_t)(c & 0x1F);
|
uint16_t c = (uint16_t)((pic_batch_buf[col * 2U] << 8) | pic_batch_buf[col * 2U + 1U]);
|
||||||
if (r5 <= 1 && g6 <= 2 && b5 <= 2)
|
uint8_t r5 = (uint8_t)((c >> 11) & 0x1F);
|
||||||
continue;
|
uint8_t g6 = (uint8_t)((c >> 5) & 0x3F);
|
||||||
LCD_DrawPoint((uint16_t)(x + (i % length)), (uint16_t)(y + (i / length)), c);
|
uint8_t b5 = (uint8_t)(c & 0x1F);
|
||||||
|
if (r5 <= 1 && g6 <= 2 && b5 <= 2)
|
||||||
|
continue;
|
||||||
|
LCD_DrawPoint((uint16_t)(x + col), (uint16_t)(y + row), c);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -190,6 +190,11 @@ static uint8_t LCD_Dump_CommandPending(void)
|
||||||
unsigned read_len;
|
unsigned read_len;
|
||||||
unsigned i;
|
unsigned i;
|
||||||
|
|
||||||
|
/* 烧录外部 UI 资源时占用 RTT0 down,禁止此处吞字节 */
|
||||||
|
if (app_log_flash_busy()) {
|
||||||
|
return 0U;
|
||||||
|
}
|
||||||
|
|
||||||
read_len = SEGGER_RTT_Read(LCD_DUMP_RTT_DOWN_CH, rx, sizeof(rx));
|
read_len = SEGGER_RTT_Read(LCD_DUMP_RTT_DOWN_CH, rx, sizeof(rx));
|
||||||
if (read_len == 0U) {
|
if (read_len == 0U) {
|
||||||
return 0U;
|
return 0U;
|
||||||
|
|
|
||||||
|
|
@ -21,7 +21,7 @@ define region RAM_region = mem:[from __ICFEDIT_region_RAM_start__ to __ICFED
|
||||||
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
define block CSTACK with alignment = 8, size = __ICFEDIT_size_cstack__ { };
|
||||||
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
|
define block HEAP with alignment = 8, size = __ICFEDIT_size_heap__ { };
|
||||||
|
|
||||||
initialize by copy { readwrite };
|
initialize by copy with packing = none { readwrite };
|
||||||
do not initialize { section .noinit };
|
do not initialize { section .noinit };
|
||||||
|
|
||||||
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
place at address mem:__ICFEDIT_intvec_start__ { readonly section .intvec };
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,183 @@
|
||||||
|
#!/usr/bin/env python3
|
||||||
|
"""Flash tools/out/ui0902_res.bin to W25Q128 @ 0x00100000 via RTT."""
|
||||||
|
|
||||||
|
from __future__ import annotations
|
||||||
|
|
||||||
|
import argparse
|
||||||
|
import os
|
||||||
|
import sys
|
||||||
|
import time
|
||||||
|
|
||||||
|
DEFAULT_DEVICES = ("Cortex-M4", "AT32F403AC", "AT32F403A")
|
||||||
|
ROOT = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
|
||||||
|
DEFAULT_BIN = os.path.join(ROOT, "tools", "out", "ui0902_res.bin")
|
||||||
|
|
||||||
|
|
||||||
|
def connect_jlink(device: str):
|
||||||
|
import pylink
|
||||||
|
|
||||||
|
jlink = pylink.JLink()
|
||||||
|
jlink.open()
|
||||||
|
try:
|
||||||
|
jlink.exec_command("HideDeviceSelection = 1")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
jlink.set_tif(pylink.enums.JLinkInterfaces.SWD)
|
||||||
|
|
||||||
|
last_error = None
|
||||||
|
for candidate in (device, *DEFAULT_DEVICES):
|
||||||
|
try:
|
||||||
|
try:
|
||||||
|
jlink.exec_command(f"Device = {candidate}")
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
jlink.connect(candidate)
|
||||||
|
print(f"Connected as {candidate}")
|
||||||
|
return jlink
|
||||||
|
except Exception as exc:
|
||||||
|
last_error = exc
|
||||||
|
jlink.close()
|
||||||
|
raise SystemExit(f"Failed to connect J-Link: {last_error}")
|
||||||
|
|
||||||
|
|
||||||
|
def find_rtt_control_block(jlink, ram_base: int = 0x20000000, ram_size: int = 0x18000):
|
||||||
|
needle = b"SEGGER RTT"
|
||||||
|
chunk = 0x1000
|
||||||
|
was_halted = jlink.halted()
|
||||||
|
if not was_halted:
|
||||||
|
jlink.halt()
|
||||||
|
try:
|
||||||
|
for off in range(0, ram_size, chunk):
|
||||||
|
data = bytes(jlink.memory_read8(ram_base + off, min(chunk, ram_size - off)))
|
||||||
|
idx = data.find(needle)
|
||||||
|
if idx >= 0:
|
||||||
|
return ram_base + off + idx
|
||||||
|
finally:
|
||||||
|
if not was_halted:
|
||||||
|
if hasattr(jlink, "restart"):
|
||||||
|
jlink.restart()
|
||||||
|
else:
|
||||||
|
jlink.go()
|
||||||
|
time.sleep(0.1)
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def rtt_read_text(jlink, timeout_s: float = 0.2) -> str:
|
||||||
|
deadline = time.time() + timeout_s
|
||||||
|
chunks: list[bytes] = []
|
||||||
|
while time.time() < deadline:
|
||||||
|
try:
|
||||||
|
data = bytes(jlink.rtt_read(0, 512) or [])
|
||||||
|
except Exception:
|
||||||
|
data = b""
|
||||||
|
if data:
|
||||||
|
chunks.append(data)
|
||||||
|
deadline = time.time() + timeout_s
|
||||||
|
else:
|
||||||
|
time.sleep(0.02)
|
||||||
|
return b"".join(chunks).decode("ascii", errors="replace")
|
||||||
|
|
||||||
|
|
||||||
|
def wait_for(jlink, marker: str, timeout_s: float = 30.0) -> str:
|
||||||
|
deadline = time.time() + timeout_s
|
||||||
|
buf = ""
|
||||||
|
while time.time() < deadline:
|
||||||
|
buf += rtt_read_text(jlink, 0.15)
|
||||||
|
if marker in buf:
|
||||||
|
return buf
|
||||||
|
raise SystemExit(f"Timeout waiting for {marker!r}\n--- RTT ---\n{buf[-800:]}")
|
||||||
|
|
||||||
|
|
||||||
|
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)
|
||||||
|
continue
|
||||||
|
off += n
|
||||||
|
|
||||||
|
|
||||||
|
def main() -> None:
|
||||||
|
parser = argparse.ArgumentParser()
|
||||||
|
parser.add_argument("--bin", default=DEFAULT_BIN)
|
||||||
|
parser.add_argument("--device", default="Cortex-M4")
|
||||||
|
args = parser.parse_args()
|
||||||
|
|
||||||
|
if not os.path.isfile(args.bin):
|
||||||
|
raise SystemExit(f"missing bin: {args.bin}")
|
||||||
|
|
||||||
|
data = open(args.bin, "rb").read()
|
||||||
|
size = len(data)
|
||||||
|
print(f"bin={args.bin} size={size}")
|
||||||
|
|
||||||
|
jlink = connect_jlink(args.device)
|
||||||
|
try:
|
||||||
|
cb = find_rtt_control_block(jlink)
|
||||||
|
if cb is None:
|
||||||
|
raise SystemExit("RTT control block not found")
|
||||||
|
print(f"RTT CB @ 0x{cb:08X}")
|
||||||
|
jlink.rtt_start(cb)
|
||||||
|
time.sleep(0.3)
|
||||||
|
_ = rtt_read_text(jlink, 0.3)
|
||||||
|
|
||||||
|
# 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:
|
||||||
|
pass
|
||||||
|
cb = find_rtt_control_block(jlink)
|
||||||
|
if cb is None:
|
||||||
|
raise SystemExit("RTT CB missing after reset")
|
||||||
|
print(f"RTT CB @ 0x{cb:08X}")
|
||||||
|
jlink.rtt_start(cb)
|
||||||
|
time.sleep(0.5)
|
||||||
|
_ = rtt_read_text(jlink, 0.5)
|
||||||
|
|
||||||
|
cmd = f"flash ui0902 {size}\n".encode("ascii")
|
||||||
|
send_bytes(jlink, cmd)
|
||||||
|
print("sent flash command, waiting GO...")
|
||||||
|
log = wait_for(jlink, "FLASH_UI0902_GO", 15.0)
|
||||||
|
print(log.strip().splitlines()[-1])
|
||||||
|
time.sleep(0.2)
|
||||||
|
|
||||||
|
# wait for first byte confirmation after starting transfer
|
||||||
|
chunk = 256
|
||||||
|
sent = 0
|
||||||
|
t0 = time.time()
|
||||||
|
# prime first page then expect FLASH_RX
|
||||||
|
send_bytes(jlink, data[0:256])
|
||||||
|
sent = 256
|
||||||
|
wait_for(jlink, "FLASH_RX", 15.0)
|
||||||
|
print("device receiving...")
|
||||||
|
while sent < size:
|
||||||
|
end = min(sent + chunk, size)
|
||||||
|
send_bytes(jlink, data[sent:end])
|
||||||
|
sent = end
|
||||||
|
if sent % 4096 == 0 or sent == size:
|
||||||
|
log = wait_for(jlink, "FLASH_ACK", 30.0)
|
||||||
|
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")
|
||||||
|
|
||||||
|
log = wait_for(jlink, "FLASH_UI0902_OK", 30.0)
|
||||||
|
print(log.strip().splitlines()[-1])
|
||||||
|
print("Done. Mode-select should redraw with new assets.")
|
||||||
|
finally:
|
||||||
|
try:
|
||||||
|
jlink.rtt_stop()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
jlink.close()
|
||||||
|
|
||||||
|
|
||||||
|
if __name__ == "__main__":
|
||||||
|
main()
|
||||||
|
|
@ -103,11 +103,12 @@ INTERNAL = [
|
||||||
|
|
||||||
# ---------------- external flash (big images / text strips) ----------------
|
# ---------------- external flash (big images / text strips) ----------------
|
||||||
EXTERNAL = [
|
EXTERNAL = [
|
||||||
|
# Art numbering: 16/19=universal, 17/20=normal, 18/21=expert (not consecutive pairs)
|
||||||
("ROW_UNIVERSAL_NOT", "04_模式图标/完整版/模式界面栏背景-16.png"),
|
("ROW_UNIVERSAL_NOT", "04_模式图标/完整版/模式界面栏背景-16.png"),
|
||||||
("ROW_UNIVERSAL_SEL", "04_模式图标/完整版/模式界面栏背景-17.png"),
|
("ROW_UNIVERSAL_SEL", "04_模式图标/完整版/模式界面栏背景-19.png"),
|
||||||
("ROW_NORMAL_NOT", "04_模式图标/完整版/模式界面栏背景-18.png"),
|
("ROW_NORMAL_NOT", "04_模式图标/完整版/模式界面栏背景-17.png"),
|
||||||
("ROW_NORMAL_SEL", "04_模式图标/完整版/模式界面栏背景-19.png"),
|
("ROW_NORMAL_SEL", "04_模式图标/完整版/模式界面栏背景-20.png"),
|
||||||
("ROW_EXPERT_NOT", "04_模式图标/完整版/模式界面栏背景-20.png"),
|
("ROW_EXPERT_NOT", "04_模式图标/完整版/模式界面栏背景-18.png"),
|
||||||
("ROW_EXPERT_SEL", "04_模式图标/完整版/模式界面栏背景-21.png"),
|
("ROW_EXPERT_SEL", "04_模式图标/完整版/模式界面栏背景-21.png"),
|
||||||
("ICON_UNIVERSAL_SEL", "04_模式图标/万能模式图标-1.png"),
|
("ICON_UNIVERSAL_SEL", "04_模式图标/万能模式图标-1.png"),
|
||||||
("ICON_UNIVERSAL_NOT", "04_模式图标/万能模式图标-2.png"),
|
("ICON_UNIVERSAL_NOT", "04_模式图标/万能模式图标-2.png"),
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue