docs: SUOTA 状态码分层与 0x38000 产品头阻断根因入 DECISIONS

This commit is contained in:
agent committed 2026-07-29 04:56:12 +00:00
1 parent ff9f2f84fd
commit 94fea411a9
2 files changed
+16 -4

No files matched your search

+3
View File
@@ -17,3 +17,6 @@
| 2026-07-28 | 设备睡眠行为适配:广播窗口短(约 30-60s),连接态保持清醒 | 实测:空闲即停广播;单连接 batch 可在窗口内跑完全部命令 | 现场测试统一用 `ppclock batch` 单连接;唤醒守候循环(每 15-20s 重试)跨窗口执行 |
| 2026-07-29 | **SUOTA 状态码 8/16 = 会话信息码而非失败**(仅本固件) | 反汇编 MEM_DEV handler(0x07FCB6F8):type 0x13 命中 bit4 位测试 → 发状态 16 且 SPOTA 状态保持(0x07FCB770-0x07fcb772);type 0x12 → 状态 8 并清会话(0x07FCB780);空镜像探针与正式烧录均先收 16 后流程完好 | bridge ota 对 8/16 记录并继续,块确认只认 2;APK 错误表未覆盖 16,以固件证据为准 |
| 2026-07-29 | bridge OTA 大请求需显式 StreamReader limit | asyncio 默认 64KiB 行限制,OTA 镜像 hex 请求 ~144KB 永不可达(三轮"静默停滞"根因);空镜像探针 0.6s 全通证明管线无恙 | build 9: start_server(limit=4MiB);教训:大载荷 RPC 协议设计必须考虑传输层帧限 |
| 2026-07-29 | **SUOTA 状态码分两类:会话信息码(8/16)与流程错误码**;16=MEM_DEV type 0x13 位测试应答(固件 0x07FCB770),状态保持 | 反汇编 MEM_DEV handler + 三轮烧录对照(16 恒在 MEM_DEV 后 ~1s 到达,块未受影响) | bridge 对 8/16 记录继续、块确认只认 2;APK 表未覆盖 16,固件证据为准 |
| 2026-07-29 | **SUOTA 状态 22/20 根因分层**:22=0x38000 产品头读电气失败(GPIO_MAP 引脚错);20=读成功但非 'pR'(引脚有效、0x38000 疑为空) | GPIO 探针(max_blocks=2 安全模式):A{00,00,06,05}→22、B{40,00,06,05}→22、C{05,06,00,40}→20;C=APK 整数 0x05060040 的 BE 字节,为唯一电气有效候选 | GPIO_MAP 采用 C(BE 序);剩余阻断=0x38000 产品头('pR')缺失/无效,见下条 |
| 2026-07-29 | **0x38000 产品头阻断为 vendor 级问题**:固件在首 0x200 缓冲处理时校验 0x38000 的 'pR' 产品头(0x07FCB4AA),无效则发 20 并中止该缓冲处理;本机疑以裸 'pQ' 直启(无产品头) | 反汇编完整校验链;固件镜像内 0x3A19 处的 70 52 系代码巧合非真产品头;MEM_INFO 读回 00000000 | 强推 END 有变砖风险(END 会写 0xAA 标志+复位,裸启兜底可恢复但需 JTAG 兜底方案);暂缓强推,先与用户决策 |
+13 -4
View File
@@ -26,16 +26,20 @@ class Bridge:
self.next_id = 0
async def open(self):
try:
self.w.close()
except Exception:
pass
self.r, self.w = await asyncio.open_connection(HOST, PORT)
async def rpc(self, op, timeout=120, **kw):
async def rpc(self, op, wait=120, **kw):
self.next_id += 1
rid = self.next_id
self.w.write(json.dumps({"id": rid, "op": op, **kw}).encode() + b"\n")
await self.w.drain()
events = []
while True:
line = await asyncio.wait_for(self.r.readline(), timeout)
line = await asyncio.wait_for(self.r.readline(), wait)
if not line:
raise ConnectionError("bridge EOF")
msg = json.loads(line)
@@ -46,8 +50,13 @@ class Bridge:
async def connect_until_awake(self, tries=12):
for i in range(tries):
resp, _ = await self.rpc("connect", 150, address=DEVICE,
timeout=30, subscribe=False)
try:
resp, _ = await self.rpc("connect", 150, address=DEVICE,
timeout=30, subscribe=False)
except (ConnectionError, asyncio.TimeoutError):
print(" 连接通道中断,重开 TCP...")
await self.open()
continue
if resp.get("ok"):
print(f"连接成功(第 {i + 1} 次)")
return True