jim800121chen 46514d77d7 docs(local-tool): M9 — Kneron Dongle FW 偵測 + 升降版(A+B、翻案 R5-Q9)
L 級新功能、PRD/Design/TDD/ADR 三方協作 + 互審 + M9-6 SDK 雙驗證、總計 ~9000 行文件。

範圍:
- A 階段(MVP、5 人天):KL520 + KL720 自動升級 KDP1 → KDP2
- B 階段(10.5 人天):手動降版面向一般使用者 + KL630 / KL730 擴展
- 合計 15.5 人天、安裝包 +7MB(保守 bundle 策略)

關鍵決策:
- 翻案 R5-Q9(progress.md 第二輪使用者決策「韌體燒錄 flash → B 砍掉」)
- 跨平台用 KneronPLUS Python C API、不用 DFUT.exe
- 多版本目錄結構選 C metadata(firmware/<chip>/{version}/ + CURRENT_VERSION)
- Kneron firmware redistribution 授權與 R5-B4 預置模型同性質、發佈前評估

文件產出:
- PRD v2.2(PRD-v2.md 495 行 + features/feature-firmware-management.md 599 行)
- Design v2.2(firmware-management.md 948 行 + control-panel.md §6a graceful shutdown)
- TDD v2.2(v2/firmware-management.md 823 行 + ADR-001 218 行)
- 8 份 research(含 M9-6 弱驗證 + 強驗證、~3200 行)
- 3 份三方互審報告(PM/Design/Architect cross-review)

M9-6 強驗證重大發現(影響 B 階段):
- KL730 product_id 實際是 0x732(不是 0x0730)
- KL630/KL730 firmware 是 embedded Linux rootfs(不是 .bin、不同代設計)
- KneronPLUS Python 沒 update_kdp_firmware_from_files 公開 API、warrenchen 走 ctypes
- 不影響 A 階段、B 階段 M9-8 需 spike

下一步:派 backend M9-1 起跑(bridge.py handle_firmware_upgrade)

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-05-25 07:40:56 +08:00

13 KiB
Raw Blame History

研究摘要visionA-local Kneron Dongle FW 偵測 + 升降版

作者Architect Agent 日期2026-05-24 範圍:純研究 plan、不出 code、不改任何既有檔案 目標:在 visionA-localWails 桌面 app新增「自動偵測 Kneron Dongle FW 版本 + 升級 / 降版」功能 參考:同事 warrenchen 雲端版實作於 /tmp/web_academy_prototype/


1. Executive Summary

核心發現

  1. R5-Q9 砍 flash 的決策不阻擋本任務——當時砍的是「使用者按按鈕去燒模型到 device flash」這條使用者旅程FW 升降版是不同的事。Q9 砍掉的並不是 firmware 燒錄的技術能力(我們既有的 Flash() driver method 跟 bridge.py 都還有完整的 kp.core.load_firmware_from_file 邏輯只是叫法叫「load_firmware」不叫「flash firmware」
  2. visionA-local 既有 code 已經有 70% 的 FW 偵測 + RAM-load 邏輯
    • kneron_bridge.py:handle_connect() 已會偵測 Loader mode、自動從 firmware/<chip>/fw_scpu.bin + fw_ncpu.bin load firmware 到 RAM
    • kneron_bridge.py:handle_connect() 已處理 KL720 KDP legacy (pid=0x0200) → 強制 load KDP2 firmware 到 RAM 的路徑
    • DeviceInfo.FirmwareVer 已在 driver interface 內、bridge 連線時也已回傳 firmware 欄位
    • bundled firmware 已存在於 server/scripts/firmware/{KL520,KL720}/fw_{scpu,ncpu}.bin(合計約 ~360KB
  3. 缺的核心是「持久化升降版」
    • 既有的 load_firmware_from_fileRAM-load(裝置重新上電就消失)
    • 真正的 FW 升降版需要呼叫 kp_update_kdp_firmware_from_filesC API、會寫 flash
    • warrenchen 雲端版用兩條路徑:(a) kp.core.install_driver_for_windows 風格的 Python 包裝;(b) KneronDFUT.exeWindows-only Qt GUI 工具的 CLI mode
  4. 跨平台選 KneronPLUS C API、不選 DFUT.exe
    • DFUT.exe 是 Windows-only Qt5 binary、~30MB 依賴、不能用
    • libkplus.{dll,so,dylib} 三平台都有、我們既有 bundle 已含、增加成本約 0KB已在 KneronPLUS wheel 內)
    • 對應 Python API 是 kp.core.update_kdp_firmware_from_files、不需要走 ctypes除非舊 KDP1 → KDP2 那條超 legacy 路徑需要 kp_connect_devices_with_magic_pass、那段才必須 ctypes

推薦方案:兩階段

階段 AMVP建議先做「FW 偵測 + 自動升級 KDP1 → KDP2」

範圍KL520 + KL720兩個我們已支援的晶片

做什麼

  1. 被動偵測scan / connect 時已知道 firmware 字串、在前端 UI 顯示 FW 版本(綠/黃/紅 badge
  2. 主動升級(單一動作):使用者按「升級到最新 KDP2」按鈕 → 走 warrenchen 的 legacy-upgrade flow → 進度回報 → 完成後 rescan
  3. 不做手動降版:階段 A 不暴露「給使用者選版本」UI、只有「升級到目前內建的最新版本」一個動作

為什麼先做 A

  • 解決 90% 的真實痛點(拿到一根插上是 KDP1 legacy 的舊 dongle 沒辦法用)
  • 工時 ~3-5 人天、安裝包 +0KBKL520/KL720 firmware 都已內建)
  • 風險低失敗的話舊狀態還在、re-plug 重試
  • 不踩 brick 風險KDP2 是 Kneron 官方 SDK 的標準版本、不是改寫過的 binary

階段 B完整版視 A 驗證結果決定要不要做):「手動降版 + 多裝置支援」

做什麼

  1. 手動降版 KDP2 → KDP1(測試 / 復現舊 bug 用、僅內部)
  2. 加入 KL630 / KL730 支援(需要 KneronPLUS SDK 對應版本驗證)
  3. 多版本 firmware 並存(讓使用者選擇 firmware 版本)

為什麼分開

  • 手動降版主要是「給開發者測試用」、不是真實使用者場景
  • KL630 / KL730 我們目前 driver 沒驗證過、要先升級 driver code 才能加 FW 支援
  • 安裝包 + 5-10MBKL630/KL730 firmware 是 .tar 約 2-4MB / 套)

工時 / 範圍對照

項目 MVPA 完整版A + B
裝置範圍 KL520 + KL720 + KL630 + KL730
操作範圍 自動升級 KDP1 → KDP2 + 手動降版 + 多版本選擇
新增 API 3 個(/api/devices/:id/firmware, /api/devices/:id/firmware/upgrade, WebSocket progress room + 2 個(/firmware/downgrade, /firmware/versions
新增 UI 1 個 Devices 頁面卡片擴充FW badge + 升級按鈕 + progress modal + Settings 內的「進階FW 版本管理」面板
bridge.py 新增 handler firmware_upgrade + firmware_downgrade + firmware_list_versions
driver 改動 UpgradeFirmware() method + DowngradeFirmware(version)
新文件 TDD 補 §5.4 FW 升級子節 + 1 個新 ADR + 1 個新 ADR
預估工時 3-5 人天 + 5-7 人天 = 8-12 人天合計
安裝包衝擊 +0KB既有 KL520/KL720 已 bundle +5-10MBKL630/KL730 firmware + 可能的舊版 KL520_kdp

R5-Q9 翻案分析

Q9 原文:「韌體燒錄 flash → B 砍掉」progress.md L776

當時為何砍

  • progress.md 沒留下原因只有「B 砍掉」)
  • 推測理由(需使用者確認):
    1. visionA-local 是「local 推論工具」、不是「dongle 管理工具」、燒 flash 不屬核心使用旅程
    2. 燒 flash 有 brick 風險、不想對使用者開放
    3. 早期 MVP 範圍縮小、把非必要功能延後
    4. 既有「load_firmware 到 RAM」夠用KL520 USB Boot 每次都重 load、KL720 已預燒 KDP2

現在為何要翻案

  • 「拿到舊 dongle 完全不能用」是真實痛點progress.md L29 已有 Error 15 SEND_DATA_TOO_LARGE 經驗)
  • 使用者明確要求做(聯合決策已收齊)
  • 同事 warrenchen 雲端版已驗證可做、且安全
  • 階段 A 範圍小、風險可控、工時可估

翻案是否合理 合理。

  • Q9 的擔憂仍有效brick 風險、不是核心旅程),但範圍縮小到「自動升級到內建 KDP2 標準版本」就能避開大部分風險
  • 不開放使用者「燒任意 binary」、只開放「升級到 Kneron 官方 KDP2 標準版本」
  • 加 progress.md 留下決策痕跡(新 ADR 引用 Q9 + 標註翻案理由)

裝置範圍建議

強烈建議 MVP 階段只做 KL520 + KL720

晶片 現有 driver 支援 warrenchen 提供 firmware 建議
KL520 KL520KDP2+ KL520_kdpKDP1 降版用) MVP 必做
KL720 KL720KDP2 MVP 必做
KL630 driver 沒處理 product_id 0x0630 kp_firmware.tar / kp_loader.tar 延後(要先擴 driver
KL730 driver 沒處理 product_id 0x0730 kp_firmware.tar / kp_loader.tar 延後(要先擴 driver

KL630 / KL730 的 firmware 是 .tar 格式(不是 .bin代表 SDK 的 load_firmware API 對它們的處理流程也不同、需要先讓 Python bridge 能載這兩種、再做 FW 升降版。強行加入 KL630 / KL730 會把 MVP 範圍翻倍

安裝包大小衝擊預估

目前 macOS dmg163MBprogress.md 確認)

階段 新增內容 大小
MVPA 0既有 KL520/KL720 已 bundle +0KB
完整版B KL520_kdp~92KB+ KL630 .tar~2MB+ KL730 .tar~3MB +5MB

→ MVP 階段不衝擊安裝包大小、完整版約 +3%(接受範圍內)。


2. 與既有架構衝突點

2.1 與 TDD v2.1「watchServer Error state」機制的銜接

TDD v2.1 已決定 watchServer 失敗 → 切 ServerStateError、不再 os.Exit

FW 升級失敗該怎麼處理

  • 建議FW 升級是「device 層」失敗、不是「server 層」失敗、不應該讓 server 進 Error state
  • 失敗時device 層回 Error state既有 driver.StatusError)、推 WebSocket 失敗訊息給 UI、server 繼續正常運行
  • 這跟 watchServer 機制是平行的、不衝突

2.2 與 KL520 reset bug2026-04-21的銜接

bridge.py 已加 fresh_firmware_loaded flag、避免雙重 firmware load 浪費 60s。

FW 升級流程要避免踩同樣坑

  • 升級成功後 device 會 re-enumerate裝置脫離 USB → 重新出現)
  • 必須等 USB stable建議 5-8 秒)+ 主動 rescan、不要立刻 reconnect
  • 升級流程內部需要 kp.core.reset_device(KP_RESET_REBOOT)、跟我們既有的 restartBridge() 流程重疊,要小心 race

2.3 與 R5-E 60s 啟動上限的銜接

FW 升級是使用者主動觸發、不在啟動 pipeline 內、跟 60s 上限無關。

:升級可能需要 30-60 秒warrenchen 的 KL520 升級 timeout 設 30 秒、KL720 設 180 秒、UI 必須給 progress bar、不能 block。

2.4 既有 Flash() method 的角色重新定位

flash/service.go:StartFlash() 目前的語意是「load model 到 device RAM」、不是「燒 firmware」。

建議:保持 flash/ 模組原意load model新建 firmware/ 模組(升降版)、不混用。

具體模組劃分:

  • server/internal/flash/ — 既有load model 到 device RAM語意保持
  • server/internal/firmware/(新)— FW 偵測 + 升級 + 降版

2.5 文件命名包袱

server/internal/driver/kneron/kl720_driver.go 檔名其實是 KL520 + KL720 共用 driverprogress.md 已標註)、本任務不改檔名(範圍外)、但新文件不要再用 kl720_* 命名、用 kneron_*device_firmware_*


3. 下一步建議

  1. 給使用者 review 本份 plan這個檔 + 10/20/30 三個附檔)
  2. 使用者確認後:
    • 方案 A 通過 → 啟動 PM 補 PRD「FW 管理」章節(記錄 Q9 翻案 + MVP 範圍)→ Architect 補 TDD v2.1 §5.4 firmware 子節 + 新 ADR-009-firmware-management → Design 補 Devices 頁面 FW badge + 升級 modal 設計
    • 方案 B 通過 → 同上 + 補 KL630/KL730 driver 擴展 plan多一份 research
    • 要求修改 plan → 我修
  3. 文件完成後依 milestone 進入開發(建議拆 M9-1 ~ M9-5

Milestone 建議拆法MVP 階段)

# Milestone 預估 平行性
M9-1 bridge.py 新增 firmware_upgrade handlerKneronPLUS C API 1 人天 獨立
M9-2 Go driver + serviceUpgradeFirmware() + firmware/service.go 1 人天 依賴 M9-1
M9-3 API handler + WebSocket progress room 0.5 人天 依賴 M9-2
M9-4 前端 Devices 頁 FW badge + 升級按鈕 + progress modal 1.5 人天 依賴 M9-3
M9-5 三平台實機驗證macOS / Windows / Linux 1 人天 全部後
合計 5 人天

每個 milestone 都走 Reviewer 審查、最後 Testing E2E 驗收。


附錄B 階段研究索引2026-05-24 追加)

使用者最新決策2026-05-24

使用者拍板採方案 A + B 一次做完。新決策:

  1. 手動降版面向一般使用者(不只 dev mode、Settings 一般面板就要看得到)
  2. FW 全部內嵌進安裝包、+5MB 接受、不做線上更新通道

本附錄涵蓋的新研究檔

檔案 主題
40-b-phase-kl630-kl730-extension.md KL630/KL730 driver 擴展研究主檔warrenchen 實作分析、既有 driver 擴點、SDK 落差、milestone M9-6 ~ M9-13
41-tar-firmware-handling.md .tar firmware 處理細節(為什麼是 .tar、SDK API、解壓策略 X/Y/Z、大小估算
42-manual-downgrade-for-end-users.md 手動降版面向一般使用者driver/bridge/API 細節、多版本儲存結構、Design Agent 需求清單)

與主檔00 ~ 30的關係

主檔內容 B 階段研究檔位置
§1 範圍對照表「階段 B 工時」5-7 人天 更新為 ~10.5 人天B 階段拆三層 + 手動降版面向一般使用者 + SDK 驗證)詳見 40 §10
§1 安裝包衝擊「+5-10MB」 更新為 +6-8MB(保守 bundle 策略)詳見 42 §4
§1 「KL630/KL730 延後」 變更A 階段做完後啟動 M9-6 SDK 驗證 → 決定 B 階段是否全做、見 40 §11
§3 「手動降版主要是給開發者測試用」 翻案:使用者決策面向一般使用者、見 42 §1.1

B 階段風險清單擴增

承前 R-FW-1 ~ R-FW-7、本研究新增

  • R-FW-8KneronPLUS SDK 對 KL630/KL730 API 不可預測(高度)
  • R-FW-9.tar 解包對安裝包大小衝擊(低度)
  • R-FW-10KL630/KL730 沒有 Loader mode 概念(中度)
  • R-FW-11:一般使用者誤觸降版 brick 風險高度B2
  • R-FW-12:多版本管理 UX 複雜度中度B2
  • R-TAR-1 ~ R-TAR-4.tar 解壓特定風險41 檔 §8

B 階段啟動前必確認

  1. KneronPLUS wheel 版本與升級可能性M9-6 第一件事)
  2. KL630/KL730 是否有實機可測(沒有則 M9-6 降級為純文件研究)
  3. Kneron 對 firmware re-distribution 的書面授權範圍是否含舊版 / KDP142 §7
  4. 使用者對多版本 bundle 策略的選擇(保守 / 完整 / 極簡42 §4.3
  5. 多版本目錄結構選項(建議 C、42 §3.2

下一步建議(更新版)

  1. 給使用者 review 本份完整 plan00 + 10/20/30 + 40/41/42 七個檔)
  2. 使用者最終 confirm 整體範圍後:
    • A 階段啟動M9-1 ~ M9-55 人天)
    • B 階段預備M9-6 SDK 驗證1 人天、可與 A 階段平行做 research
  3. A 階段 release / 驗證後評估 M9-6 結論、決定 B 階段全做或調整 scope
  4. B 階段執行M9-7 ~ M9-13合計 ~9.5 人天)
  5. 整體合計:~15.5 人天A 5 + B 10.5