- Every doc (README, AGENT, docs/*) now ships as English under the default filename and Chinese as *.zh-cn.md; both versions cross-link in their first line, in-document links stay within the same language - AGENT.md §7 records the keep-both-languages-in-sync rule (same commit, no translating later); CHANGELOG kept in both languages - Docs-only change; version 0.5.1 synced in the usual three places
7.4 KiB
7.4 KiB
English | 简体中文
esp-emu-peris 系统架构
1. 分层总览
┌───────────────────────────────── 页面(page)─────────────────────────────────┐
│ esp-emu-peris.html 上游样式原块(便于升级 diff)+ <link peris/peris.css> │
│ 三栏同屏:UART0 控制台 │ 外设面板 │ Debug(0.3.0 起不再标签切换) │
│ build/ui/* (TypeScript 编译产物) │
│ app.ts 编排器:机器状态、Run/Pause/固件/网络控件、消息路由 │
│ worker-client Worker 唯一入口(其它模块一律经由它收发消息) │
│ terminal / chart / debug-panels UART 控制台 / 性能图 / Debug 只读面板 │
│ peris-panel + config-editor 行式外设列表(图标/名称/GPIO/V·G 徽章 │
│ + 展开/删除/拖动)与详情配置编辑器 │
└───────────────▲───────────────────────────────────────────────▲────────────┘
postMessage(协议见 core/protocol.ts) │ DOM
┌───────────────┴───────────────────────────────────────────────▼────────────┐
│ 页面侧设备 View(peris/devices/*.js 的 View 类,由 peris-panel 实例化) │
├─────────────────────────────────────────────────────────────────────────────┤
│ ← peris_state / peris_command → │
├─────────────────────────────────────────────────────────────────────────────┤
│ build/core/worker.ts 上游 worker 复刻 + 6 处 peris: 钩子(唯一可碰上游逻辑) │
│ build/core/runtime.ts 设备宿主:配置校验/实例化/命令/状态节流推送 │
│ build/core/sigbus.ts 引脚信号总线:每批 gpio_state() 差分分发 │
│ build/core/registry.ts 插件注册表(manifest 驱动 + 元数据校验) │
│ build/core/{version,types,protocol,chips,mmio}.ts 版本/契约/消息/芯片表/寄存器表 │
│ worker 侧设备 Device(peris/devices/*.js 的 Device 类) │
└───────────────────────────────────────────────────┬─────────────────────────┘
│ WasmEmulator(闭源 wasm,
│ 只此一处触碰)
esp_emu_bg.wasm v0.51.0
2. 关键决策与理由
| 决策 | 理由 |
|---|---|
| 模拟器只存在于 worker | 页面永不触碰 wasm;所有交互走 postMessage,线程模型不可能被破坏 |
| 框架层 TypeScript、设备插件原生 JS | 类型检查覆盖 bug 高发区(本次重构即修掉状态丢弃缺陷);插件保持"丢文件即用",不引入构建依赖 |
| tsc 逐文件编译、不打包 | 产物仍是标准 ESM 目录,部署模型不变(www 只增不改);上游同构,升级 diff 容易 |
| 样式拆 peris.css,上游样式原块留 HTML | 升级时直接 diff HTML 里的上游段 |
| 数据在 TS 常量(chips/mmio)而非 JSON | tsc 原生携带、类型检查、无运行时拷贝问题 |
| registry 运行时校验插件元数据 | 插件作者没有编译期检查,缺 pins()/typeId 在加载时即报错(真实 bug 类) |
3. 数据流与状态归属
- 固件 → 设备:worker 每批
run_batch()后runtime.onBatchEnd()→sigbus.sample()读gpio_state()(4 个 32 位字),按联合变化掩码(out|oe)对每个变化引脚分发一次onPinState。无变化时成本 = 1 次 wasm 调用 + 4 次 XOR。 - 设备 → 页面:设备
markDirty()→flushStates节流 ~30fps;节流窗口内挂尾随 定时器,保证最后一次 dirty 必达(否则静止在窗口内的最终状态会被丢弃)。 - 页面 → 设备:View
sendCmd()→peris_command→runtime.command()→onCommand。 - 输入引脚电平:唯一写者是
ctx.setPinInput(设备)与 Debug 网格的gpio_input。 页面侧gpioInputLevels[]只是 Debug 网格自己的镜像,不是权威状态;权威状态在设备里 (onEmuReady时重驱动)。 - 配置:页面
PerisPanel.config是唯一事实源;每次变更全量peris_config下发 (worker 销毁重建实例)并写 localStorage。引脚冲突由 worker 校验后回报peris_ready.errors,页面黄条展示。
4. 目录职责
src/core/ worker 侧框架(TS 源) → 编译到 build/core/
src/ui/ 页面侧模块(TS 源) → 编译到 build/ui/
build/ tsc 产物(未入 git;HTML/worker/测试都引用这里)
peris/devices/ 设备插件(JS 源,不编译;manifest.json 注册;各自版本号)
peris/vendor/ xterm 本地化
peris/peris.css peris 专属样式
tests/unit/ 单元测试(node:test,零依赖)
tests/m1_smoke.mjs 集成冒烟(真实 wasm+固件+runtime+设备)
tests/m0_probe.mjs 模拟器能力探针(升级上游时先跑它)
tests/firmware/ IDF 测试固件
5. 构建与测试
npm install # 一次性(typescript 走 npmmirror 源)
npm run build # tsc → peris/core + peris/ui(改 src 后必须)
npm run check # 仅类型检查
npm test # 单测 + 集成冒烟
npm run serve # python serve.py(合并服务仓库与 www/pkg)
npm run sync # 发布进官方 www(先 build)
测试分层:单元(纯逻辑:位运算/电平语义/校验/行式徽章推导——快、定位准)→ 集成(真实
wasm+固件全链路)→ GUI(手动清单:页面加载、三栏同屏可见、加设备
后行式渲染、行内改名/改 GPIO/翻 V·G、行内图标交互(点灯换色/按压/开关)、展开详情
与配置编辑、拖动排序、载固件、Run 后 LED 翻转、配置导入导出往返;浏览器自动化待
网络环境允许时引入 Playwright,
PLAYWRIGHT_DOWNLOAD_HOST=https://cdn.npmmirror.com/binaries/playwright)。
6. 升级流程(摘要,详见 UPGRADE.zh-cn.md)
- 新 wasm 包就位后先跑
npm run test:m0,对比 FEASIBILITY.zh-cn.md 结论; - diff 上游 worker.js ↔
src/core/worker.ts(改动均标peris:); - diff 上游 app.js/index.html ↔
src/ui/*.ts与 HTML 的上游样式段; npm run build && npm test,GUI 冒测。
7. 扩展点
- 新外设:
peris/devices/放模块 + manifest 一行(见 docs/DEVICE-API.zh-cn.md);Worker/页面 自动加载,元数据即时校验。 - 新芯片:
src/core/mmio/<chip>.ts加地址表 + 注册到mmio.ts;chips.ts补引脚数。 - 新页面面板:ui/ 加模块,在 app.ts 的消息路由注册——worker 协议不动。