mirror of
https://github.com/MCKero6423/uv-k5-v3-emulator.git
synced 2026-10-02 03:15:36 +00:00
Record that no overlay app runs: the copy lands, the jump never happens
Measured by polling the PC over QMP every 30 ms, finer than the model's own 100 ms probe. After launching Tetris the overlay at 0x20000280 holds Tetris's code byte for byte, so the loader's copy is correct and aligned; the earlier claim in this session that it was shifted by one byte was my own parsing dropping the first value. But 172 PC samples over 4.5 s and 64 more over 2 s were all inside firmware flash at 0x08013260, a wait loop, and none landed in the overlay. A 16-byte app that calls nothing behaves identically, and Breakout's header is field-for-field the shape of ours, so neither the app's code nor its header is the reason. The failure is upstream of the app, which makes the earlier 'Tetris runs' note stale: per this file's own rule it is treated as unverified until it reproduces. Also carries the CI-fix branch merge and a regression test for _edit_flash creating its working-copy directory (its fixture image has to be a real size: slot 0 sits at 0x102000).
This commit is contained in:
1 parent
c0c2c3230e
commit
fa0f4e7f23
3 files changed
+70
No files matched your search
@@ -688,6 +688,28 @@ and the offset are all accepted. **Whether control then reaches the overlay is s
|
|||||||
probe samples every 100 ms and saw no overlay address, no `APP ERROR` screen appears, and the app does
|
probe samples every 100 ms and saw no overlay address, no `APP ERROR` screen appears, and the app does
|
||||||
not draw. That is where this stands -- the pipeline is verified up to the load, not up to execution.
|
not draw. That is where this stands -- the pipeline is verified up to the load, not up to execution.
|
||||||
|
|
||||||
|
**No overlay app actually runs in this emulator: the code is copied and control is never transferred.**
|
||||||
|
Measured by polling the PC through QMP every 30 ms (finer than the model's own 100 ms probe), with the app
|
||||||
|
installed through the page's own endpoint:
|
||||||
|
|
||||||
|
* after launching Tetris, memory at 0x20000280 holds Tetris's own code byte for byte (f0b56b4c85b0036f...),
|
||||||
|
so the loader's copy is correct and aligned. The earlier claim in this session that it was shifted by a byte
|
||||||
|
was my own parsing dropping the first value, not the model. **172 PC samples over 4.5 s and 64 more over 2 s
|
||||||
|
were all inside firmware flash (0x08013260, a wait loop); not one landed in the 4 KiB overlay.**
|
||||||
|
* a 16-byte app that calls nothing at all -- no display, no keys, no struct member, just a volatile counter in a
|
||||||
|
loop -- behaves the same way, so this is not about what an app does once it starts.
|
||||||
|
* the header is not the reason either: Breakout's header (flags 0x1, capabilities 0x0, entry_off 0, abi 1,
|
||||||
|
api_min 1, hdr 1) is field-for-field the shape of ours, and the firmware still copies its code.
|
||||||
|
|
||||||
|
So the failure is upstream of the app: the firmware validates and copies, and then does not enter the overlay.
|
||||||
|
**This makes the earlier "Tetris runs, DOWN moves the piece" note stale -- per this file's own rule, treat it as
|
||||||
|
unverified until it reproduces.** The screen seen after MENU (the radio's own top line, e.g. "F4 APRS", with the
|
||||||
|
rest blank) is the main screen: the app menu has gone away without the app ever starting.
|
||||||
|
|
||||||
|
Next instruments, in order: whether the firmware waits for a key release before jumping (the PC sits in the same
|
||||||
|
wait loop at 0x08013260 both before and after MENU), and whether the copy of an upstream app is ever entered when
|
||||||
|
it is launched from the radio's own menu path rather than through this page.
|
||||||
|
|
||||||
## The keypad: two real bugs, both fixed
|
## The keypad: two real bugs, both fixed
|
||||||
|
|
||||||
The old note here said "keys reach the firmware but the UI does not react" and
|
The old note here said "keys reach the firmware but the UI does not react" and
|
||||||
|
|||||||
@@ -556,6 +556,26 @@ app 区被读过 —— 而多系统菜单读的是**固件槽**,不是应用
|
|||||||
一次、没采到叠加区地址,也没有出现 `APP ERROR` 屏,应用也没有画出来。现状就是如此 —— **管线验证到了
|
一次、没采到叠加区地址,也没有出现 `APP ERROR` 屏,应用也没有画出来。现状就是如此 —— **管线验证到了
|
||||||
"加载"这一步,还没到"执行"**。
|
"加载"这一步,还没到"执行"**。
|
||||||
|
|
||||||
|
**这个模拟器里现在没有任何叠加应用真的跑起来:代码被拷进了叠加区,控制权却从未交出去。**
|
||||||
|
量法:通过 QMP **每 30 ms 轮询一次 PC**(比模型自带的 100 ms 探针更细),应用是用页面自己的接口装进去的:
|
||||||
|
|
||||||
|
* 启动 Tetris 之后,0x20000280 处的内存**与 Tetris 自己的代码逐字节相同**(f0b56b4c85b0036f...),
|
||||||
|
说明加载器的拷贝是正确且对齐的。本会话里我先前说的"错位一个字节"**是我自己的解析吃掉了第一个数值**,
|
||||||
|
不是模型的问题。**4.5 秒里 172 次采样、外加 2 秒里 64 次采样,全部落在固件 flash 内(0x08013260,一个等待
|
||||||
|
循环),没有一次落进那 4 KiB 叠加区。**
|
||||||
|
* 一个 **16 字节、什么都不调用**的应用(不碰显示、不读按键、不访问结构体成员,只是一个自增的 volatile 循环)
|
||||||
|
表现完全相同 —— 所以这**不是**"应用启动之后做了什么"的问题。
|
||||||
|
* 头也不是原因:Breakout 的头(flags 0x1、capabilities 0x0、entry_off 0、abi 1、api_min 1、hdr 1)与我们的
|
||||||
|
逐字段同形,而固件照样把它的代码拷了进去。
|
||||||
|
|
||||||
|
也就是说,故障在应用**之前**:固件完成校验与拷贝,然后**没有进入叠加区**。
|
||||||
|
**这使得本文件早先那条"Tetris 能跑、按 DOWN 棋子会动"的记录失效 —— 按本文件自己的规矩,在它能复现之前一律
|
||||||
|
当作未验证。** 用户按下 MENU 之后看到的画面(电台自己的顶行,例如 "F4 APRS",其余空白)就是主界面,
|
||||||
|
即应用菜单已经退出、而应用从未启动。
|
||||||
|
|
||||||
|
接下来该用的仪器,按顺序:固件在跳转前是否在等按键释放(按 MENU 前后 PC 都停在 0x08013260 这个等待循环里);
|
||||||
|
以及从**电台自己的菜单路径**启动上游应用时,拷贝进去的代码到底有没有被执行。
|
||||||
|
|
||||||
## 键盘:两个真 bug,都已修复
|
## 键盘:两个真 bug,都已修复
|
||||||
|
|
||||||
这里原来的笔记写的是"按键到达了固件但界面不反应",并且归咎于机器模型。结果发现有**两个
|
这里原来的笔记写的是"按键到达了固件但界面不反应",并且归咎于机器模型。结果发现有**两个
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import subprocess
|
|||||||
import tempfile
|
import tempfile
|
||||||
import time
|
import time
|
||||||
import unittest
|
import unittest
|
||||||
|
from unittest import mock
|
||||||
|
|
||||||
import uvk5_image
|
import uvk5_image
|
||||||
# Flask is the one thing the fast suite needs from pip, so it is not always there.
|
# Flask is the one thing the fast suite needs from pip, so it is not always there.
|
||||||
@@ -1167,3 +1168,30 @@ class TestAppsFrontEnd(unittest.TestCase):
|
|||||||
self.assertNotIn("navigator.serial", self.page)
|
self.assertNotIn("navigator.serial", self.page)
|
||||||
self.assertNotIn("getUserMedia", self.page)
|
self.assertNotIn("getUserMedia", self.page)
|
||||||
self.assertNotIn("AudioContext", self.page)
|
self.assertNotIn("AudioContext", self.page)
|
||||||
|
|
||||||
|
|
||||||
|
class TestWorkingCopyDirectory(unittest.TestCase):
|
||||||
|
"""_edit_flash must create its working-copy directory, not assume it exists.
|
||||||
|
|
||||||
|
On the machine this was written on work/firmware/ already existed, so the missing
|
||||||
|
makedirs() was invisible; a fresh checkout (CI) fails with FileNotFoundError on the
|
||||||
|
first install. Found by the copilot/fix-github-actions-unit-job branch.
|
||||||
|
"""
|
||||||
|
|
||||||
|
def test_the_working_copy_directory_is_created(self):
|
||||||
|
directory = tempfile.mkdtemp()
|
||||||
|
self.addCleanup(shutil.rmtree, directory, True)
|
||||||
|
flash = os.path.join(directory, "flash.img")
|
||||||
|
with open(flash, "wb") as fh:
|
||||||
|
fh.write(b"\xff" * (2 * 1024 * 1024))
|
||||||
|
slot = FlashSlot(flash)
|
||||||
|
missing = os.path.join(directory, "not", "created", "yet")
|
||||||
|
app = webui.create_app(None, frame_addr=0x1000, status_addr=0x2000, flash=slot)
|
||||||
|
with mock.patch.object(webui, "upload_dir", return_value=missing):
|
||||||
|
client = app.test_client()
|
||||||
|
import uvk5_apps
|
||||||
|
blob = uvk5_apps.build(b"\x01" * 32, "Beam", "1.0")
|
||||||
|
r = client.post("/api/apps/0", data=blob)
|
||||||
|
self.assertEqual(r.status_code, 200, r.get_data(as_text=True)[:200])
|
||||||
|
self.assertTrue(os.path.isdir(missing), "the working-copy directory was not created")
|
||||||
|
self.assertTrue(os.path.exists(os.path.join(missing, "flash-current.img")))
|
||||||
Reference in new issue
Block a user