firmwareloop 0.6.2__tar.gz → 0.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (37) hide show
  1. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/PKG-INFO +13 -6
  2. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/README.md +12 -5
  3. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/firmwareloop.egg-info/PKG-INFO +13 -6
  4. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/pyproject.toml +1 -1
  5. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/__init__.py +1 -1
  6. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/fw_mcp_server.py +80 -34
  7. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/lib/ndtdbg.py +212 -108
  8. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/lib/serial_assistant.py +128 -16
  9. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/ndtdbg_cli.py +89 -12
  10. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/serial_cli.py +106 -16
  11. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/setup-agent-mcp.ps1 +2 -2
  12. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/LICENSE +0 -0
  13. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/firmwareloop.egg-info/SOURCES.txt +0 -0
  14. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/firmwareloop.egg-info/dependency_links.txt +0 -0
  15. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/firmwareloop.egg-info/entry_points.txt +0 -0
  16. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/firmwareloop.egg-info/requires.txt +0 -0
  17. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/firmwareloop.egg-info/top_level.txt +0 -0
  18. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/setup.cfg +0 -0
  19. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/acceptance-scenario.ps1 +0 -0
  20. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/build.ps1 +0 -0
  21. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/can.ps1 +0 -0
  22. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/check-qoder-mcp.ps1 +0 -0
  23. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/common/build-backends.psm1 +0 -0
  24. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/common/fw.psm1 +0 -0
  25. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/common/uart_probe.py +0 -0
  26. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/doctor.ps1 +0 -0
  27. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/flash.ps1 +0 -0
  28. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/instrument_cli.py +0 -0
  29. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/lib/__init__.py +0 -0
  30. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/lib/instruments.py +0 -0
  31. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/logic_capture.ps1 +0 -0
  32. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/logic_decode.ps1 +0 -0
  33. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/ndtdbg_bridge.ps1 +0 -0
  34. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/reset.ps1 +0 -0
  35. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/sigrok_csv_to_fwloop.py +0 -0
  36. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/test-backends.ps1 +0 -0
  37. {firmwareloop-0.6.2 → firmwareloop-0.7.0}/tools/test.ps1 +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
5
5
  Author-email: WeilinZhang <19523330249@163.com>
6
6
  License: MIT
@@ -148,7 +148,8 @@ fwloop ndtdebugtool "C:/Users/weilin.zhang/Desktop/zwl/NdtDebugTool-v1.0.19"
148
148
  - `fw_ndtdbg_measure` — 数据轮询采集
149
149
  - `fw_ndtdbg_read_reg` / `fw_ndtdbg_write_reg` — 任意寄存器读写(写需 `write_allowed` + `confirm` 双门控)
150
150
  - `fw_ndtdbg_capture_seq` — 寄存器序列 + Saleae 波形同窗口取证
151
- - `fw_ndtdbg_flash` — .bin/.nfw 整片擦写烧录(双门控,默认拒绝)
151
+ - `fw_ndtdbg_flash` — .bin/.nfw 整片擦写烧录(双门控,默认拒绝;擦除后判 boot、校验失败整片重写)
152
+ - `fw_ndtdbg_power_cycle` — 只做目标断电复位(不做 I2C 事务、不需双门控;设备静默时的第一步,也是抓开机日志的触发端)
152
153
 
153
154
  **前置要求:**
154
155
 
@@ -382,7 +383,7 @@ claude mcp remove --scope user agentic-hil
382
383
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
383
384
  ├── demo-make/ 示例固件(Make;构建测试载体)
384
385
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
385
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.6.2)
386
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.7.0)
386
387
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
387
388
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
388
389
  ├── CLAUDE.md Claude Code CLI 指南
@@ -392,7 +393,7 @@ claude mcp remove --scope user agentic-hil
392
393
 
393
394
  ---
394
395
 
395
- ## 能力验证状态(v0.6.2
396
+ ## 能力验证状态(v0.7.0
396
397
 
397
398
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
398
399
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -400,7 +401,7 @@ claude mcp remove --scope user agentic-hil
400
401
  | 能力 | 状态 |
401
402
  |---|---|
402
403
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
403
- | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(48 例单测)-> Real Hardware Validated 待 DUT |
404
+ | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(55 例单测: 含残留 serve 自动清理 / close 进程回收 / UTF-8 线路 / 失败落 JSONL)-> Real Hardware Validated 待 DUT |
404
405
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
405
406
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
406
407
  | 一键终端更新(fwloop update) | Implemented + Auto-updater Validated |
@@ -414,7 +415,9 @@ claude mcp remove --scope user agentic-hil
414
415
  | Safety Policy(limits.yaml) | Implemented(simulator 校验)-> 外置权威配置 |
415
416
  | 自动修复闭环(M6 载体) | Simulator Validated -> Real Hardware Validated 待 DUT |
416
417
  | NdtBox 数据采集/调试(fw_ndtdbg_status / fw_ndtdbg_measure, ChipSea Fxx IIC) | Implemented(无硬件 Fail-Closed 已验证)-> Real Hardware Validated 待 NdtBox |
417
- | NdtBox IIC 固件烧录(fw_ndtdbg_flash, .bin/.nfw 整片擦写, 芯海 Fxx) | Real Hardware Validated(84.87.1.1 / 84.87.1.2 真机整片擦写 verify pass, ~22s;双闸门 Fail-Closed) |
418
+ | NdtBox 目标断电复位(fw_ndtdbg_power_cycle, io10 断电复位, 无写闸门) | Implemented(单测覆盖时序/探针缺失指引)-> Real Hardware Validated NdtBox |
419
+ | NdtBox IIC 固件烧录(fw_ndtdbg_flash, .bin/.nfw 整片擦写, 芯海 Fxx) | Real Hardware Validated(84.87.1.1 / 84.87.1.2 真机整片擦写 verify pass;双闸门 Fail-Closed)+ v0.7.0 boot 判据后移/整片重写(待真机复测首试成功率) |
420
+ | 抓开机日志(fw_serial_capture + power_cycle_off_ms, 窗口内断电复位) | Implemented(simulator 验证窗口与复位串联)-> Real Hardware Validated 待 NdtBox + DUT |
418
421
 
419
422
  ---
420
423
 
@@ -427,6 +430,10 @@ claude mcp remove --scope user agentic-hil
427
430
  | 写操作 `PERMISSION_DENIED` | 全局 `lab.yaml` 的 `ndtdbg.write_allowed` 为 `false` → 临时改 `true` 并重启 Agent(测试完建议改回 `false`) |
428
431
  | sigrok 报 `Failed to receive reply to EP1 command 0x7d` | Saleae 驱动不是 libusb-win32 → 用 Zadig 重装;或设备被 Logic 软件占用(先退出) |
429
432
  | `fw_logic_decode` 空帧 | 抓取窗口内无总线事务 → 改用 `fw_ndtdbg_capture_seq`(抓取与寄存器序列同窗口进行),不要串行先抓后写 |
433
+ | 烧录报 `BOOT_NOT_ENTERED`(擦除后 0x0000 仍读回数据) | 目标没进 boot ROM(应答的是运行态 App)→ 仅对目标板断电重启(勿动 BOX)后重试;反复出现时确认 `off_ms`(默认 500ms,独立看门狗芯片需真 POR)与 io10 供电复位接线 |
434
+ | `fw_ndtdbg_flash` 报 `TARGET_MISMATCH: 烧录校验失败 @0x....` | 响应已带 `stage_timings`/`probe_hex`/`first_mismatch_*`:先看 `probe_hex`(非 FFFFFFFF = 根本没进 boot,属上一条),再看失配偏移是否恒定(恒定=页写未落地);整片重写次数由 `rewrite_times` 控制(默认 3) |
435
+ | 串口 `SERIAL_PORT_ERROR: ... PermissionError(13)` | 端口被 GUI 上位机独占(NDT Debug Tool / STDataCollection.exe、串口助手)→ 关闭占用方后 `fw_serial_open`;残留会话用 `fw_serial_close`(已自动等待/强杀进程,端口释放可验证) |
436
+ | `fw_serial_status` 的 `error_class` 为 `UART_BUSY` | 会话未打开或已被占用 → 先 `fw_serial_open`;残留会话 `fw_serial_close` 清理 |
430
437
 
431
438
  完整速查表与手工部署细节见 [`Fwloop_setup_pack/README.md`](Fwloop_setup_pack/README.md)。
432
439
 
@@ -120,7 +120,8 @@ fwloop ndtdebugtool "C:/Users/weilin.zhang/Desktop/zwl/NdtDebugTool-v1.0.19"
120
120
  - `fw_ndtdbg_measure` — 数据轮询采集
121
121
  - `fw_ndtdbg_read_reg` / `fw_ndtdbg_write_reg` — 任意寄存器读写(写需 `write_allowed` + `confirm` 双门控)
122
122
  - `fw_ndtdbg_capture_seq` — 寄存器序列 + Saleae 波形同窗口取证
123
- - `fw_ndtdbg_flash` — .bin/.nfw 整片擦写烧录(双门控,默认拒绝)
123
+ - `fw_ndtdbg_flash` — .bin/.nfw 整片擦写烧录(双门控,默认拒绝;擦除后判 boot、校验失败整片重写)
124
+ - `fw_ndtdbg_power_cycle` — 只做目标断电复位(不做 I2C 事务、不需双门控;设备静默时的第一步,也是抓开机日志的触发端)
124
125
 
125
126
  **前置要求:**
126
127
 
@@ -354,7 +355,7 @@ claude mcp remove --scope user agentic-hil
354
355
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
355
356
  ├── demo-make/ 示例固件(Make;构建测试载体)
356
357
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
357
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.6.2)
358
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.7.0)
358
359
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
359
360
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
360
361
  ├── CLAUDE.md Claude Code CLI 指南
@@ -364,7 +365,7 @@ claude mcp remove --scope user agentic-hil
364
365
 
365
366
  ---
366
367
 
367
- ## 能力验证状态(v0.6.2
368
+ ## 能力验证状态(v0.7.0
368
369
 
369
370
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
370
371
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -372,7 +373,7 @@ claude mcp remove --scope user agentic-hil
372
373
  | 能力 | 状态 |
373
374
  |---|---|
374
375
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
375
- | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(48 例单测)-> Real Hardware Validated 待 DUT |
376
+ | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(55 例单测: 含残留 serve 自动清理 / close 进程回收 / UTF-8 线路 / 失败落 JSONL)-> Real Hardware Validated 待 DUT |
376
377
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
377
378
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
378
379
  | 一键终端更新(fwloop update) | Implemented + Auto-updater Validated |
@@ -386,7 +387,9 @@ claude mcp remove --scope user agentic-hil
386
387
  | Safety Policy(limits.yaml) | Implemented(simulator 校验)-> 外置权威配置 |
387
388
  | 自动修复闭环(M6 载体) | Simulator Validated -> Real Hardware Validated 待 DUT |
388
389
  | NdtBox 数据采集/调试(fw_ndtdbg_status / fw_ndtdbg_measure, ChipSea Fxx IIC) | Implemented(无硬件 Fail-Closed 已验证)-> Real Hardware Validated 待 NdtBox |
389
- | NdtBox IIC 固件烧录(fw_ndtdbg_flash, .bin/.nfw 整片擦写, 芯海 Fxx) | Real Hardware Validated(84.87.1.1 / 84.87.1.2 真机整片擦写 verify pass, ~22s;双闸门 Fail-Closed) |
390
+ | NdtBox 目标断电复位(fw_ndtdbg_power_cycle, io10 断电复位, 无写闸门) | Implemented(单测覆盖时序/探针缺失指引)-> Real Hardware Validated NdtBox |
391
+ | NdtBox IIC 固件烧录(fw_ndtdbg_flash, .bin/.nfw 整片擦写, 芯海 Fxx) | Real Hardware Validated(84.87.1.1 / 84.87.1.2 真机整片擦写 verify pass;双闸门 Fail-Closed)+ v0.7.0 boot 判据后移/整片重写(待真机复测首试成功率) |
392
+ | 抓开机日志(fw_serial_capture + power_cycle_off_ms, 窗口内断电复位) | Implemented(simulator 验证窗口与复位串联)-> Real Hardware Validated 待 NdtBox + DUT |
390
393
 
391
394
  ---
392
395
 
@@ -399,6 +402,10 @@ claude mcp remove --scope user agentic-hil
399
402
  | 写操作 `PERMISSION_DENIED` | 全局 `lab.yaml` 的 `ndtdbg.write_allowed` 为 `false` → 临时改 `true` 并重启 Agent(测试完建议改回 `false`) |
400
403
  | sigrok 报 `Failed to receive reply to EP1 command 0x7d` | Saleae 驱动不是 libusb-win32 → 用 Zadig 重装;或设备被 Logic 软件占用(先退出) |
401
404
  | `fw_logic_decode` 空帧 | 抓取窗口内无总线事务 → 改用 `fw_ndtdbg_capture_seq`(抓取与寄存器序列同窗口进行),不要串行先抓后写 |
405
+ | 烧录报 `BOOT_NOT_ENTERED`(擦除后 0x0000 仍读回数据) | 目标没进 boot ROM(应答的是运行态 App)→ 仅对目标板断电重启(勿动 BOX)后重试;反复出现时确认 `off_ms`(默认 500ms,独立看门狗芯片需真 POR)与 io10 供电复位接线 |
406
+ | `fw_ndtdbg_flash` 报 `TARGET_MISMATCH: 烧录校验失败 @0x....` | 响应已带 `stage_timings`/`probe_hex`/`first_mismatch_*`:先看 `probe_hex`(非 FFFFFFFF = 根本没进 boot,属上一条),再看失配偏移是否恒定(恒定=页写未落地);整片重写次数由 `rewrite_times` 控制(默认 3) |
407
+ | 串口 `SERIAL_PORT_ERROR: ... PermissionError(13)` | 端口被 GUI 上位机独占(NDT Debug Tool / STDataCollection.exe、串口助手)→ 关闭占用方后 `fw_serial_open`;残留会话用 `fw_serial_close`(已自动等待/强杀进程,端口释放可验证) |
408
+ | `fw_serial_status` 的 `error_class` 为 `UART_BUSY` | 会话未打开或已被占用 → 先 `fw_serial_open`;残留会话 `fw_serial_close` 清理 |
402
409
 
403
410
  完整速查表与手工部署细节见 [`Fwloop_setup_pack/README.md`](Fwloop_setup_pack/README.md)。
404
411
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: firmwareloop
3
- Version: 0.6.2
3
+ Version: 0.7.0
4
4
  Summary: AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)
5
5
  Author-email: WeilinZhang <19523330249@163.com>
6
6
  License: MIT
@@ -148,7 +148,8 @@ fwloop ndtdebugtool "C:/Users/weilin.zhang/Desktop/zwl/NdtDebugTool-v1.0.19"
148
148
  - `fw_ndtdbg_measure` — 数据轮询采集
149
149
  - `fw_ndtdbg_read_reg` / `fw_ndtdbg_write_reg` — 任意寄存器读写(写需 `write_allowed` + `confirm` 双门控)
150
150
  - `fw_ndtdbg_capture_seq` — 寄存器序列 + Saleae 波形同窗口取证
151
- - `fw_ndtdbg_flash` — .bin/.nfw 整片擦写烧录(双门控,默认拒绝)
151
+ - `fw_ndtdbg_flash` — .bin/.nfw 整片擦写烧录(双门控,默认拒绝;擦除后判 boot、校验失败整片重写)
152
+ - `fw_ndtdbg_power_cycle` — 只做目标断电复位(不做 I2C 事务、不需双门控;设备静默时的第一步,也是抓开机日志的触发端)
152
153
 
153
154
  **前置要求:**
154
155
 
@@ -382,7 +383,7 @@ claude mcp remove --scope user agentic-hil
382
383
  ├── demo-firmware/ 示例固件(CMake;宿主编译模拟 MCU,闭环验证载体)
383
384
  ├── demo-make/ 示例固件(Make;构建测试载体)
384
385
  ├── docs/ DEPENDENCY_MATRIX / REUSE_PLAN / V0.0.2_GAP_VERIFICATION
385
- ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.6.2)
386
+ ├── pyproject.toml 标准 Python 包配置与 CLI 入口声明 (v0.7.0)
386
387
  ├── .mcp.example.json 双层 MCP 配置模板(firmwareloop + agentic-hil)
387
388
  ├── AGENTS.md 通用智能体规范(Antigravity / Qoder / Cursor 等)
388
389
  ├── CLAUDE.md Claude Code CLI 指南
@@ -392,7 +393,7 @@ claude mcp remove --scope user agentic-hil
392
393
 
393
394
  ---
394
395
 
395
- ## 能力验证状态(v0.6.2
396
+ ## 能力验证状态(v0.7.0
396
397
 
397
398
  > 状态定义:`Implemented`(已实现)/ `Simulator Validated`(模拟验证)/
398
399
  > `Real Hardware Validated`(真机验证)/ `Experimental` / `Not Implemented`
@@ -400,7 +401,7 @@ claude mcp remove --scope user agentic-hil
400
401
  | 能力 | 状态 |
401
402
  |---|---|
402
403
  | 双层 MCP 服务(13 个工作流与硬件工具) | Implemented + Protocol Validated(31/31 测试通过) |
403
- | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(48 例单测)-> Real Hardware Validated 待 DUT |
404
+ | 串口助手工具族(fw_serial_* 七工具, 长驻会话/发送序列/帧解析/窗口采集) | Implemented + Simulator Validated(55 例单测: 含残留 serve 自动清理 / close 进程回收 / UTF-8 线路 / 失败落 JSONL)-> Real Hardware Validated 待 DUT |
404
405
  | 一键多 Agent 脚手架(fwloop init / fw_init_project) | Implemented + Multi-Agent Validated |
405
406
  | 自定义/私有调试工具接入 Skill(fwloop-adapter) | Implemented + Multi-Skill Validated |
406
407
  | 一键终端更新(fwloop update) | Implemented + Auto-updater Validated |
@@ -414,7 +415,9 @@ claude mcp remove --scope user agentic-hil
414
415
  | Safety Policy(limits.yaml) | Implemented(simulator 校验)-> 外置权威配置 |
415
416
  | 自动修复闭环(M6 载体) | Simulator Validated -> Real Hardware Validated 待 DUT |
416
417
  | NdtBox 数据采集/调试(fw_ndtdbg_status / fw_ndtdbg_measure, ChipSea Fxx IIC) | Implemented(无硬件 Fail-Closed 已验证)-> Real Hardware Validated 待 NdtBox |
417
- | NdtBox IIC 固件烧录(fw_ndtdbg_flash, .bin/.nfw 整片擦写, 芯海 Fxx) | Real Hardware Validated(84.87.1.1 / 84.87.1.2 真机整片擦写 verify pass, ~22s;双闸门 Fail-Closed) |
418
+ | NdtBox 目标断电复位(fw_ndtdbg_power_cycle, io10 断电复位, 无写闸门) | Implemented(单测覆盖时序/探针缺失指引)-> Real Hardware Validated NdtBox |
419
+ | NdtBox IIC 固件烧录(fw_ndtdbg_flash, .bin/.nfw 整片擦写, 芯海 Fxx) | Real Hardware Validated(84.87.1.1 / 84.87.1.2 真机整片擦写 verify pass;双闸门 Fail-Closed)+ v0.7.0 boot 判据后移/整片重写(待真机复测首试成功率) |
420
+ | 抓开机日志(fw_serial_capture + power_cycle_off_ms, 窗口内断电复位) | Implemented(simulator 验证窗口与复位串联)-> Real Hardware Validated 待 NdtBox + DUT |
418
421
 
419
422
  ---
420
423
 
@@ -427,6 +430,10 @@ claude mcp remove --scope user agentic-hil
427
430
  | 写操作 `PERMISSION_DENIED` | 全局 `lab.yaml` 的 `ndtdbg.write_allowed` 为 `false` → 临时改 `true` 并重启 Agent(测试完建议改回 `false`) |
428
431
  | sigrok 报 `Failed to receive reply to EP1 command 0x7d` | Saleae 驱动不是 libusb-win32 → 用 Zadig 重装;或设备被 Logic 软件占用(先退出) |
429
432
  | `fw_logic_decode` 空帧 | 抓取窗口内无总线事务 → 改用 `fw_ndtdbg_capture_seq`(抓取与寄存器序列同窗口进行),不要串行先抓后写 |
433
+ | 烧录报 `BOOT_NOT_ENTERED`(擦除后 0x0000 仍读回数据) | 目标没进 boot ROM(应答的是运行态 App)→ 仅对目标板断电重启(勿动 BOX)后重试;反复出现时确认 `off_ms`(默认 500ms,独立看门狗芯片需真 POR)与 io10 供电复位接线 |
434
+ | `fw_ndtdbg_flash` 报 `TARGET_MISMATCH: 烧录校验失败 @0x....` | 响应已带 `stage_timings`/`probe_hex`/`first_mismatch_*`:先看 `probe_hex`(非 FFFFFFFF = 根本没进 boot,属上一条),再看失配偏移是否恒定(恒定=页写未落地);整片重写次数由 `rewrite_times` 控制(默认 3) |
435
+ | 串口 `SERIAL_PORT_ERROR: ... PermissionError(13)` | 端口被 GUI 上位机独占(NDT Debug Tool / STDataCollection.exe、串口助手)→ 关闭占用方后 `fw_serial_open`;残留会话用 `fw_serial_close`(已自动等待/强杀进程,端口释放可验证) |
436
+ | `fw_serial_status` 的 `error_class` 为 `UART_BUSY` | 会话未打开或已被占用 → 先 `fw_serial_open`;残留会话 `fw_serial_close` 清理 |
430
437
 
431
438
  完整速查表与手工部署细节见 [`Fwloop_setup_pack/README.md`](Fwloop_setup_pack/README.md)。
432
439
 
@@ -4,7 +4,7 @@ build-backend = "setuptools.build_meta"
4
4
 
5
5
  [project]
6
6
  name = "firmwareloop"
7
- version = "0.6.2"
7
+ version = "0.7.0"
8
8
  description = "AI Agent Firmware Development and Lab Automation Platform (Dual-Tier MCP Server)"
9
9
  readme = "README.md"
10
10
  authors = [
@@ -2,4 +2,4 @@
2
2
  FirmwareLoop - AI Agent Firmware Development and Lab Automation Platform.
3
3
  """
4
4
 
5
- __version__ = "0.6.2"
5
+ __version__ = "0.7.0"
@@ -1,6 +1,6 @@
1
1
  #!/usr/bin/env python3
2
2
  """
3
- fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.6.2).
3
+ fw_mcp_server.py - FirmwareLoop High-Level Workflow & Device MCP Server (v0.7.0).
4
4
 
5
5
  Exposes high-level firmware engineering and hardware management tools to AI Coding
6
6
  Agents (Antigravity CLI, Claude Code CLI, Qoder IDE, CodeBuddy IDE, Cursor) via the Model Context
@@ -21,6 +21,7 @@ Tools provided:
21
21
  - fw_ndtdbg_capture_seq: NdtBox register sequence + concurrent I2C capture for waveform evidence (ndtdbg_cli.py)
22
22
  - fw_ndtdbg_stream_start/status/stop: job mode for long stream captures (immediate job_id, CSV-tail polling, graceful stop)
23
23
  - fw_ndtdbg_flash: NdtBox IIC firmware flash (.bin/.nfw, full-chip erase, double-gated) (ndtdbg_cli.py)
24
+ - fw_ndtdbg_power_cycle: NdtBox target power-cycle only (no I2C transaction, no write gate; boot-log trigger) (ndtdbg_cli.py)
24
25
  - fw_ndtdbg_stream: NdtBox high-rate register stream capture to CSV via one long-lived USB session (read-only) (ndtdbg_cli.py)
25
26
  - fw_serial_status: Serial assistant session probe (serve liveness, port, RX/TX counters, log path) (serial_cli.py)
26
27
  - fw_serial_open: Serial assistant - open (or reuse) the persistent COM session (HEX/ASCII duplex, session log) (serial_cli.py)
@@ -331,35 +332,41 @@ def handle_fw_ndtdbg_write_reg(args: Dict[str, Any]) -> Dict[str, Any]:
331
332
  def handle_fw_ndtdbg_flash(args: Dict[str, Any]) -> Dict[str, Any]:
332
333
  """Erase + flash a .bin/.nfw image onto the NdtBox target chip (ChipSea Fxx) over IIC.
333
334
 
334
- P1-1: retry 参数 (默认 1) —— 命中 "TARGET_MISMATCH @0x0000" (未进 boot 的特征
335
- 签名: 校验读到旧向量表) 自动重试; BOOT_NOT_ENTERED 不重试 (需人工断电, 直接给指引)。
335
+ P1-3 (0.7.0): 去掉按签名重试 —— "TARGET_MISMATCH @0x0000" 正是"根本没进 boot"的
336
+ 特征签名 (旧 boot 判据假阳的同一条错误路径), 盲目重试只会重复同一失败路径。
337
+ 整片重写 (<= rewrite_times) 现由 flash_exec 内部完成, 结果带 rewrite_count;
338
+ BOOT_NOT_ENTERED 直接返回指引 (需断电重启, 重试无意义)。
336
339
  """
337
340
  cli_script = os.path.join(REPO_ROOT, "tools", "ndtdbg_cli.py")
338
341
  cmd = [PYTHON_EXE, cli_script, "flash-bin", "--file", str(args.get("file_path")),
339
342
  "--erase-ms", str(int(args.get("erase_ms", 2000)))]
343
+ if args.get("off_ms") is not None:
344
+ cmd.extend(["--off-ms", str(int(args["off_ms"]))])
345
+ if args.get("rewrite_times") is not None:
346
+ cmd.extend(["--rewrite-times", str(max(0, int(args["rewrite_times"])))])
340
347
  if args.get("confirm"):
341
348
  cmd.append("--confirm")
342
349
  _ndtdbg_reg_args(args, cmd)
343
350
  timeout_s = min(max(int(args.get("timeout_seconds", 300)), 30), 900)
344
- retry = max(0, int(args.get("retry", 1)))
345
- result: Dict[str, Any] = {}
346
- for attempt in range(retry + 1):
347
- result = _ndtdbg_run(cmd, timeout_s)
348
- data = result.get("data") if isinstance(result.get("data"), dict) else None
349
- if not data:
350
- return result # CLI JSON body: 原样返回 (兼容 mock/异常输出)
351
- if data.get("ok"):
352
- if attempt:
353
- data["retry_count"] = attempt
354
- return data
355
- err_text = f"{data.get('error', '')} {data.get('detail', '')}"
356
- err_cls = data.get("error_class")
357
- if err_cls == "BOOT_NOT_ENTERED":
358
- return data # 需人工断电重启, 重试无意义
359
- if err_cls == "TARGET_MISMATCH" and "@0x0000" in err_text and attempt < retry:
360
- continue # 未进 boot 特征签名: 自动重试
361
- return data
362
- return result
351
+ result = _ndtdbg_run(cmd, timeout_s)
352
+ data = result.get("data") if isinstance(result.get("data"), dict) else None
353
+ return data if data else result # 无 CLI JSON body: 原样返回 (兼容 mock/异常输出)
354
+
355
+
356
+ def handle_fw_ndtdbg_power_cycle(args: Dict[str, Any]) -> Dict[str, Any]:
357
+ """P0-2: 只做一次断电复位 (usb2io IO10 off -> on), 不做任何 I2C 事务。
358
+
359
+ 设备静默时最安全的第一步 (读风险等级: 不需要 lab.yaml write_allowed), 也是
360
+ "复位 + 抓开机日志" 的触发端 —— 与 fw_serial_open/capture 配合使用。
361
+ 返回 {off_ms, powered_on, io_ms}。
362
+ """
363
+ cli_script = os.path.join(REPO_ROOT, "tools", "ndtdbg_cli.py")
364
+ cmd = [PYTHON_EXE, cli_script, "power-cycle"]
365
+ if args.get("off_ms") is not None:
366
+ cmd.extend(["--off-ms", str(int(args["off_ms"]))])
367
+ _ndtdbg_reg_args(args, cmd)
368
+ res = _ndtdbg_run(cmd, 60)
369
+ return res.get("data") or res
363
370
 
364
371
 
365
372
  def _stream_cli_cmd(args: Dict[str, Any], out_path: str, duration_cap: float) -> Optional[list]:
@@ -1378,13 +1385,22 @@ def handle_fw_serial_parse(args: Dict[str, Any]) -> Dict[str, Any]:
1378
1385
 
1379
1386
 
1380
1387
  def handle_fw_serial_capture(args: Dict[str, Any]) -> Dict[str, Any]:
1388
+ """P2-4: 可选 power_cycle_off_ms —— 开机打印只在复位瞬间出现, 必须先开端口再复位。
1389
+
1390
+ 实现: capture 窗口在后台线程先行打开 (~200ms), 窗口内触发一次断电复位
1391
+ (ndtdbg power-cycle), 于是复位瞬间及其后的启动日志都落在 CSV 里。
1392
+ """
1381
1393
  duration_ms = int(args.get("duration_ms", 3000))
1394
+ power_cycle = args.get("power_cycle_off_ms")
1382
1395
  cmd = [PYTHON_EXE, SERIAL_CLI, "capture", "--duration-ms", str(duration_ms)]
1383
1396
  if args.get("out"):
1384
1397
  cmd.extend(["--out", str(args["out"])])
1398
+ if power_cycle is not None:
1399
+ cmd.extend(["--power-cycle-off-ms", str(int(power_cycle))])
1385
1400
  if args.get("lab_config"):
1386
1401
  cmd.extend(["--lab-config", str(args["lab_config"])])
1387
- res = _serial_run(cmd, duration_ms // 1000 + 60)
1402
+ # 断电复位 = 额外一次 32 位桥进程往返 (秒级), 计入超时预算
1403
+ res = _serial_run(cmd, duration_ms // 1000 + 60 + (30 if power_cycle is not None else 0))
1388
1404
  return res.get("data") or res
1389
1405
 
1390
1406
 
@@ -1754,7 +1770,7 @@ TOOLS_REGISTRY = {
1754
1770
  "handler": handle_fw_ndtdbg_write_reg,
1755
1771
  },
1756
1772
  "fw_ndtdbg_flash": {
1757
- "description": "Erase and flash a .bin/.nfw firmware image onto the NdtBox target chip (ChipSea Fxx) over IIC via NdtDebugTool (power-cycle reset into boot -> erase magic AA 55 A5 5A -> 128B page writes -> 256B read-back verify -> finish 'PASs'). DESTRUCTIVE full-chip erase: requires lab.yaml ndtdbg.write_allowed: true AND confirm: true, otherwise PERMISSION_DENIED.",
1773
+ "description": "Erase and flash a .bin/.nfw firmware image onto the NdtBox target chip (ChipSea Fxx) over IIC via NdtDebugTool (power-cycle reset into boot -> erase magic AA 55 A5 5A -> BOOT JUDGEMENT: 0x0000 must read all-0xFF, a running App answers its own static registers and is rejected with BOOT_NOT_ENTERED -> 128B page writes -> 256B read-back verify, whole-chip rewrite on mismatch -> finish 'PASs'). DESTRUCTIVE full-chip erase: requires lab.yaml ndtdbg.write_allowed: true AND confirm: true, otherwise PERMISSION_DENIED.",
1758
1774
  "inputSchema": {
1759
1775
  "type": "object",
1760
1776
  "properties": {
@@ -1777,10 +1793,13 @@ TOOLS_REGISTRY = {
1777
1793
  "description": "CLI process timeout; budget ~30s per 64KB image (page writes paced at 30ms)",
1778
1794
  "default": 300,
1779
1795
  },
1780
- "retry": {
1796
+ "off_ms": {
1781
1797
  "type": "integer",
1782
- "description": "Auto-retries on TARGET_MISMATCH @0x0000 signature (target did not enter boot; verify read old vector table). BOOT_NOT_ENTERED never retries (manual power-cycle required). Result carries retry_count when a retry succeeded",
1783
- "default": 1,
1798
+ "description": "Power-off duration of the reset-into-boot power cycle, in ms. Default from lab.yaml ndtdbg.flash.off_ms, else 500 (200ms may only sag the rail - independent-watchdog chips such as CSA37F72 IWDG_S need a real POR)",
1799
+ },
1800
+ "rewrite_times": {
1801
+ "type": "integer",
1802
+ "description": "Whole-chip rewrite budget when read-back verify mismatches (aligned with ChipSea.cs REWRITE_TIMES). Default 3; 0 disables rewriting. The result carries rewrite_count/attempts, and a failed flash reports stage_timings/probe_hex/first_mismatch_* for post-mortem",
1784
1803
  },
1785
1804
  "dll_dir": {
1786
1805
  "type": "string",
@@ -1799,6 +1818,29 @@ TOOLS_REGISTRY = {
1799
1818
  },
1800
1819
  "handler": handle_fw_ndtdbg_flash,
1801
1820
  },
1821
+ "fw_ndtdbg_power_cycle": {
1822
+ "description": "Power-cycle the NdtBox target through the reset rail (usb2io IO10 off -> on, default 500ms) WITHOUT any I2C transaction. Read-risk level: lab.yaml ndtdbg.write_allowed is NOT required. Use it as the first step when the target is silent, and as the trigger for capturing boot-time UART logs (fw_serial_open + fw_serial_capture). Returns {off_ms, powered_on, io_ms}.",
1823
+ "inputSchema": {
1824
+ "type": "object",
1825
+ "properties": {
1826
+ "off_ms": {
1827
+ "type": "integer",
1828
+ "description": "Power-off duration in ms; default from lab.yaml ndtdbg.flash.off_ms, else 500. Independent-watchdog chips (e.g. CSA37F72 IWDG_S) only clear on a real POR/BOR/pin reset",
1829
+ "default": 500,
1830
+ },
1831
+ "dll_dir": {
1832
+ "type": "string",
1833
+ "description": "NdtDebugTool lib directory containing USBIOX.DLL and usb2io.dll; default from lab.yaml ndtdbg.dll_dir",
1834
+ },
1835
+ "slave_addr": {
1836
+ "type": "string",
1837
+ "description": "IIC slave address (unused by power-cycle; accepted for tool-family symmetry)",
1838
+ },
1839
+ },
1840
+ "additionalProperties": False,
1841
+ },
1842
+ "handler": handle_fw_ndtdbg_power_cycle,
1843
+ },
1802
1844
  "fw_ndtdbg_stream": {
1803
1845
  "description": "Stream-read a set of IIC registers from the NdtBox target chip (ChipSea Fxx) at a fixed interval via one long-lived USB session. Writes CSV with timestamps; returns JSON summary (frames, FF_GAP/IO_FAIL/HANG counts, interval stats, io_overhead, write stats). Protocol profiles: continuous (pure-read), request-response (pre_write), stress (interleave_writes, needs confirm). NOTE: server-side timeout = duration_s + 120s; for durations beyond ~90s the MCP client may time out first - use shorter windows or the job pattern.",
1804
1846
  "inputSchema": {
@@ -2193,7 +2235,7 @@ TOOLS_REGISTRY = {
2193
2235
  "handler": handle_fw_serial_parse,
2194
2236
  },
2195
2237
  "fw_serial_capture": {
2196
- "description": "Serial assistant: synchronous window capture - record the RX stream for duration_ms into a timestamped CSV (t_rel_ms, dir, hex, printable) for offline analysis/plotting (real-time-curve equivalent; plotting happens in your tools/Agent from the CSV). duration_ms <= 90000; long background captures (job mode) are a planned follow-up.",
2238
+ "description": "Serial assistant: synchronous window capture - record the RX stream for duration_ms into a timestamped CSV (t_rel_ms, dir, hex, printable) for offline analysis/plotting (real-time-curve equivalent; plotting happens in your tools/Agent from the CSV). Pass power_cycle_off_ms to fire an NdtBox power-cycle inside the window and capture boot-time prints (port is opened first). duration_ms <= 90000; long background captures (job mode) are a planned follow-up.",
2197
2239
  "inputSchema": {
2198
2240
  "type": "object",
2199
2241
  "properties": {
@@ -2202,6 +2244,10 @@ TOOLS_REGISTRY = {
2202
2244
  "description": "Capture window length in ms (1..90000)",
2203
2245
  "default": 3000,
2204
2246
  },
2247
+ "power_cycle_off_ms": {
2248
+ "type": "integer",
2249
+ "description": "When set, power-cycle the NdtBox target inside the capture window (off for N ms, default 500 behaviour when the value is omitted) so boot-time prints land in the CSV. The COM port is opened first, then the reset fires ~200ms into the window. Requires the NdtBox reset rail (usb2io IO10); no write_allowed needed",
2250
+ },
2205
2251
  "out": {"type": "string", "description": "CSV output path (defaults to a temp-dir file)"},
2206
2252
  "lab_config": {"type": "string", "description": "Explicit lab.yaml path override"},
2207
2253
  },
@@ -2254,7 +2300,7 @@ def process_request(req: Dict[str, Any]) -> Optional[Dict[str, Any]]:
2254
2300
  },
2255
2301
  "serverInfo": {
2256
2302
  "name": "firmwareloop",
2257
- "version": "0.6.2"
2303
+ "version": "0.7.0"
2258
2304
  }
2259
2305
  }
2260
2306
  }
@@ -2389,7 +2435,7 @@ def _settle_stashed_entrypoints(stashed) -> None:
2389
2435
  def handle_cli_update() -> int:
2390
2436
  """Handle `firmwareloop update` command."""
2391
2437
  print("============================================================")
2392
- print(" FirmwareLoop Auto-Updater (v0.6.2)")
2438
+ print(" FirmwareLoop Auto-Updater (v0.7.0)")
2393
2439
  print("============================================================")
2394
2440
 
2395
2441
  is_git_repo = os.path.exists(os.path.join(REPO_ROOT, ".git"))
@@ -2820,7 +2866,7 @@ def set_ndtdbg_dlldir(dll_path: str) -> str:
2820
2866
  def handle_cli_setup() -> int:
2821
2867
  """Handle `firmwareloop setup` command: simultaneously configure Antigravity CLI, Claude Code CLI, Qoder IDE, and CodeBuddy IDE."""
2822
2868
  print("============================================================")
2823
- print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.6.2)")
2869
+ print(" FirmwareLoop Multi-Agent Global Setup Helper (v0.7.0)")
2824
2870
  print("============================================================")
2825
2871
  print("")
2826
2872
 
@@ -2945,7 +2991,7 @@ def handle_cli_setup() -> int:
2945
2991
  def handle_cli_init(chip: Optional[str] = None, upgrade: bool = False) -> int:
2946
2992
  """Handle `firmwareloop init [target_chip]` command."""
2947
2993
  print("============================================================")
2948
- print(" FirmwareLoop Multi-Agent Project Initializer (v0.6.2)")
2994
+ print(" FirmwareLoop Multi-Agent Project Initializer (v0.7.0)")
2949
2995
  print("============================================================")
2950
2996
  cwd = os.getcwd()
2951
2997
  print(f"[*] Initializing multi-agent guidelines & bench config in:\n {cwd}\n")
@@ -2978,7 +3024,7 @@ def handle_cli_init(chip: Optional[str] = None, upgrade: bool = False) -> int:
2978
3024
 
2979
3025
 
2980
3026
  def print_cli_help() -> None:
2981
- print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.6.2)
3027
+ print("""FirmwareLoop (fwloop) — AI Agent Firmware Engineering & Lab Automation Platform (v0.7.0)
2982
3028
 
2983
3029
  Usage:
2984
3030
  fwloop [command] (or: firmwareloop [command])
@@ -3024,7 +3070,7 @@ def main() -> None:
3024
3070
  sys.exit(2)
3025
3071
  sys.exit(handle_cli_ndtdebugtool(args[1]))
3026
3072
  elif cmd in ["version", "-v", "--version"]:
3027
- print("FirmwareLoop v0.6.2")
3073
+ print("FirmwareLoop v0.7.0")
3028
3074
  sys.exit(0)
3029
3075
  elif cmd in ["help", "-h", "--help"]:
3030
3076
  print_cli_help()