diff --git a/AGENTS.md b/AGENTS.md index 9b930f1..dc69f45 100644 --- a/AGENTS.md +++ b/AGENTS.md @@ -790,6 +790,24 @@ Next instrument, and it needs a one-line model change rather than more guessing: 100 ms, which is the same order as the app's whole life. Dropping that interval to a couple of milliseconds turns it into a real trace and would show where in the overlay the app stops. +**The PC probe's interval is now a knob (UVK5_PC_PROBE_MS), and at 2 ms the overlay app's whole life is one tick.** + +100 ms was the same order as the thing being measured: an app that the launcher starts and that is gone again +before the next sample. uvk5_pc_probe_interval_ms() reads UVK5_PC_PROBE_MS and falls back to 100, so every +existing probe run is unchanged. At 2 ms, a launch gives 468 samples in about 0.94 s and **exactly one of them +is inside the 4 KiB overlay** -- the app runs for roughly 2 ms, not 100. + +With a real trace in hand, two things are now settled and one is new. Settled: the loader copies and jumps (the +single overlay sample), and a 16-byte app that calls nothing stays there forever. Settled the other way: the +sector-cache overwrite is dead -- the flash log's **last** transaction for the run is the app's own code load +(addr=103000 len=2408) and **nothing follows it**, no font read included. New: after the app dies the firmware +sits in a loop inside its own flash (PCs around 0x08005118/0x08005122/0x08005248) with **zero flash reads and +no key response at all** -- even F then 7 no longer opens the menu, and an explicit MENU down/up changes +nothing. So the launcher (or the fault path it takes) is wedged, not merely waiting for a release. + +That is where the next round starts: the app dies within about 2 ms, the firmware never reads the flash after +loading it, and what is left running is a tight loop in the firmware with no display or key activity. + ## The keypad: two real bugs, both fixed The old note here said "keys reach the firmware but the UI does not react" and diff --git a/AGENTS.zh-CN.md b/AGENTS.zh-CN.md index 50a1cae..2060bfa 100644 --- a/AGENTS.zh-CN.md +++ b/AGENTS.zh-CN.md @@ -642,6 +642,22 @@ flash 探针是按顺序记录每一笔事务的,而那一次启动的**最后 下一个仪器,只需要改模型一行而不是继续猜:PC 探针每 100 ms 采样一次,而应用整个生命期就是这个量级。把这个 间隔降到几毫秒,它就变成真正的 trace,能看出应用**停在叠加区的哪个位置**。 +**PC 探针的间隔现在是可配置的(UVK5_PC_PROBE_MS);调到 2 ms 之后,叠加应用整个生命期只有一个采样点。** + +100 ms 与被测对象同量级:启动器刚把应用带起来,下一个采样到来之前它就已经没了。uvk5_pc_probe_interval_ms() +读 UVK5_PC_PROBE_MS、缺省仍是 100,所以以往任何一次探针运行都保持原样。调到 2 ms 后,一次启动在约 0.94 秒里 +得到 468 个样本,其中**恰好一个**落在那 4 KiB 叠加区内 —— 应用只活了约 **2 毫秒**,不是 100。 + +有了真正的 trace,两件事就此确定,另有一件是新发现。确定的:加载器会拷贝并跳转(那一个叠加区样本),而且 +那个 16 字节、什么都不调用的应用能一直待在里面。反过来确定的:**扇区缓存覆盖说已经死了** —— 那次运行的 flash +日志里**最后一条**就是应用自己的代码加载(addr=103000 len=2408),**其后什么都没有**,包括字体读取。新发现: +应用死掉之后,固件**停在自身 flash 内的一个循环里**(PC 在 0x08005118/0x08005122/0x08005248 一带),**零次 flash +读取、按键完全无响应** —— 连 F 再 7 都打不开菜单了,显式地 MENU down/up 也毫无变化。也就是说**启动器(或它走的 +故障路径)卡死了**,而不只是在等一次松开。 + +下一轮就从这里开始:应用在约 2 ms 内死亡,固件在加载它之后**再也没有读过 flash**,而剩下的是一个没有显示、 +没有按键活动的紧循环。 + ## 键盘:两个真 bug,都已修复 这里原来的笔记写的是"按键到达了固件但界面不反应",并且归咎于机器模型。结果发现有**两个 diff --git a/qemu/py32f071.c b/qemu/py32f071.c index 3da31c6..f4277ae 100644 --- a/qemu/py32f071.c +++ b/qemu/py32f071.c @@ -3609,6 +3609,19 @@ static uint32_t uvk5_sniff_app_offset(const char *path) * can be located without a debugger (a gdb attach stops the guest, which is the * one thing that must not happen while working out where it stopped). */ +/* + * How often the PC probe samples. 100 ms is fine for finding a hang, but an overlay + * app's whole life can be shorter than that -- the launcher takes the screen and the app + * is gone again before the next tick -- so UVK5_PC_PROBE_MS lets a run ask for a real + * trace instead of a few points. The default keeps every existing probe run identical. + */ +static int uvk5_pc_probe_interval_ms(void) +{ + const char *v = g_getenv("UVK5_PC_PROBE_MS"); + int ms = v ? atoi(v) : 0; + return ms > 0 ? ms : 100; +} + static void uvk5_pc_probe_tick(void *opaque) { UVK5MachineState *s = opaque; @@ -3620,7 +3633,7 @@ static void uvk5_pc_probe_tick(void *opaque) fclose(f); } } - timer_mod(s->pc_probe_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100); + timer_mod(s->pc_probe_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + uvk5_pc_probe_interval_ms()); } static void uvk5_boot_key_release(void *opaque) @@ -3800,7 +3813,7 @@ static void uvk5_machine_init(MachineState *machine) uvk5_arm_boot_key(s); if (g_getenv("UVK5_PC_PROBE")) { s->pc_probe_timer = timer_new_ms(QEMU_CLOCK_VIRTUAL, uvk5_pc_probe_tick, s); - timer_mod(s->pc_probe_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + 100); + timer_mod(s->pc_probe_timer, qemu_clock_get_ms(QEMU_CLOCK_VIRTUAL) + uvk5_pc_probe_interval_ms()); } qdev_connect_gpio_out_named(DEVICE(&s->soc.gpio[0]), "pin-out", 3, qdev_get_gpio_in_named(DEVICE(&s->flash),