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>
13 KiB
ADR-001: Kneron Dongle FW 偵測 + 升降版(翻案 R5-Q9)
Status
Accepted — 使用者於 2026-05-24 拍板方案 A + B 一次做完、L 級正規流程。
2026-05-25 update:M9-6 弱驗證執行(見 research-kl520-fw-management/55-m9-6-weak-validation-result.md)後追加兩個新事實:
- visionA-local KneronPLUS wheel 三平台版本不一致:macOS/Linux = 2.0.0、Windows = 3.1.2。對 A 階段(KL520/KL720 升級)不阻塞(既有 API 在兩個版本都存在);對 B 階段(KL630/KL730)影響重大、B 階段啟動前必須統一升級到 3.1.2+ 並跑三平台 KL520/KL720 回歸(M9-13)。詳見 TDD
v2/firmware-management.md§1.3。 - PRD AC-FW-3.5(KL630/KL730 升降版)延後至 B 階段 M9-10:弱驗證確認 warrenchen 沒做 KL630/KL730 升降版(reference 實作為零)、且需要實機才能驗
update_kdp_firmware_from_files對 KL630/KL730 是否適用。A 階段 scope 縮限為 KL520+KL720 自動升級。Decision §1 表格的 A 階段範圍不變(本來就只列 KL520+KL720)、Consequences §5 風險敘述強化。
Context
痛點背景
visionA-local 自 2026-04 上線以來、累積以下與 Kneron Dongle FW 相關的痛點:
- 拿到舊 dongle 完全不能用:使用者拿到的 KL520 dongle 若是 KDP1 legacy(pid=0x0200)、插上 visionA-local 後 connect 流程在
kp.core.load_firmware_from_file階段失敗、無法 inference。 - KL520 firmware 殘留導致 Error 15 SEND_DATA_TOO_LARGE(2026-04-21 已修、但 root cause 在 FW 層):commit
ddf0eb8為了解 Windows 60s HTTP timeout 加「KL520 首次 connect 跳過 reset」優化、後來發現 KL520 若 session 間 firmware 殘留(fw=KDP2 Comp/U)、直接 load_model + inference 100% 炸 Error 15。已 revert、但這暴露既有 FW 偵測 + reset 邏輯的脆弱性。 - KL630 / KL730 偵測不到:scan 階段顯示得到名字、但
handle_connectfall-through 到 KL520 路徑、用錯誤的 firmware 檔載入 → 連不上。新世代 dongle 完全不可用。 - 舊 model 與新 FW 相容性:進階使用者反映「我的舊 NEF model 在升版 FW 後跑不出結果」、缺乏降版機制。
R5-Q9 砍 flash 的歷史決策
progress.md 重要決策紀錄 §「第二輪使用者決策 Q9」:
韌體燒錄 flash → B 砍掉
(行號為動態值、本 ADR 不寫具體 L 行號避免日後 progress.md 增刪後失準;以「第二輪使用者決策 Q9」描述位置為準)
當時砍的理由(推測、原 progress.md 沒留下細節):
- visionA-local 是「local 推論工具」、不是「dongle 管理工具」、燒 flash 不屬核心使用旅程
- 燒 flash 有 brick 風險、不想對使用者開放
- 早期 MVP 範圍縮小、把非必要功能延後
- 既有「load_firmware 到 RAM」夠用(KL520 USB Boot 每次都重 load、KL720 已預燒 KDP2)
為何現在要翻案
- 痛點 #1 是真實場景:使用者已陸續遇到舊 KDP1 dongle 完全不能用(Q9 原始假設「既有 load_firmware 到 RAM 夠用」不成立)
- 同事 warrenchen 雲端版已驗證可做、且安全:
/tmp/web_academy_prototype/local_service_win/有完整實作可參考 - 範圍可切割:Q9 砍的是「使用者按按鈕燒任意 model 到 device flash」、本期是「升級到 Kneron 官方 KDP2 標準版本」、避開大部分 brick 與責任風險
- 跨平台技術可行:KneronPLUS Python API(
kp.core.update_kdp_firmware_from_files)+libkplus.{dll,so,dylib}三平台都已在既有 wheel 內、無需引入 Windows-only DFUT.exe
技術現況盤點
visionA-local 既有 code 已有 70% 的 FW 偵測 + RAM-load 邏輯:
kneron_bridge.py:handle_connect()已會偵測 Loader mode、從firmware/<chip>/fw_scpu.bin + fw_ncpu.binload firmware 到 RAMkneron_bridge.py:handle_connect()已處理 KL720 KDP legacy → 強制 load KDP2 firmware 到 RAMDeviceInfo.FirmwareVer已在 driver interface、bridge 連線時也回傳firmware欄位- bundled firmware 已存在
server/scripts/firmware/{KL520,KL720}/(合計 ~360KB)
缺的是「持久化升降版」:
- 既有的
load_firmware_from_file是 RAM-load(裝置重新上電就消失) - 真正的 FW 升降版需要呼叫
kp_update_kdp_firmware_from_files(會寫 flash)
Decision
採以下五項決策:
1. 採方案 A + B、不分階段交付
| 階段 | 範圍 | 工時 |
|---|---|---|
| A | KL520 + KL720 自動升級 KDP1 → KDP2、安裝包 +0KB | 5 人天 |
| B | + KL630 + KL730 driver 擴展 + 手動降版(面向一般使用者)+ 多版本管理、安裝包 +7MB | 10.5 人天 |
| 合計 | — | 15.5 人天 |
不採「先做 A、之後再評估 B」的分階段策略——使用者明確要求一次做完。
2. 翻案 R5-Q9,範圍切割如下
| 「燒 flash」場景 | 本期決策 |
|---|---|
| 使用者按按鈕燒任意 model(NEF)到 device flash | 繼續砍(R5-Q9 原始決策維持) |
| 升級到 Kneron 官方 KDP2 標準版本 | 本期做(範圍切割後翻案) |
| 手動降版到 bundled 舊版(含 KDP1) | 本期做(B2 階段、面向一般使用者) |
| 使用者燒入自編 firmware binary | 不做(brick 風險過高、責任風險過高) |
切割後翻案的核心邏輯:Q9 擔憂的 brick 風險來自「使用者燒任意 binary」、而非「升級到官方標準版本」。本期只暴露「升級到 Kneron 官方 KDP2」+ 「降版到 bundled 已知舊版」、binary 來源已嚴格限制。
3. 跨平台用 KneronPLUS Python C API
| 替代方案 | 否決原因 |
|---|---|
| DFUT.exe(warrenchen 雲端版用) | Windows-only、~30MB Qt5 binary、跨平台不通 |
| ctypes 包 KneronPLUS C API | 既有 Python wheel 已包好、不需重做 |
| 自寫 USB 協議實作 | 範圍過大、需逆向工程 Kneron protocol、Kneron 不認可 |
採 KneronPLUS Python API(kp.core.update_kdp_firmware_from_files)路徑:
- 三平台都有 wheel(既有 bundle 已含、增加成本 ~0KB)
- 對應 C 函式經 SDK 驗證、不踩 brick 風險
- 與既有
kp.core.load_firmware_from_file路徑共用、bridge.py 改動可控
4. 多版本目錄結構採選項 C — CURRENT_VERSION metadata
firmware/<chip>/
├── CURRENT_VERSION ← 單行檔:"v2.2.0"
├── v2.2.0/{...} + VERSION
├── v2.1.0/{...} + VERSION
└── kdp1/{...} + VERSION
| 替代方案 | 否決原因 |
|---|---|
選項 A — symbolic link(current/ 指向版本目錄) |
Windows symlink 需 admin、tar 處理跨 OS 不一致 |
選項 B — 實體副本(current/ 是 v2.2.0/ 的 file copy) |
每 chip 多佔一份(合計 +7-8MB 額外)、跨平台簡單但浪費空間 |
選項 C — CURRENT_VERSION 單行檔 + 版本目錄並列 |
選此:架構乾淨、空間最省、跨平台無 symlink 風險、bridge.py 多一次 file read(trivial 成本) |
5. 保守 bundle 策略 +7MB
| Chip | bundled 版本 | 估算 |
|---|---|---|
| KL520 | current + kdp1 + v2.1.0 | ~290KB |
| KL720 | current + v2.1.0(如有) | ~500KB |
| KL630 | current + 1 個舊版(如有)+ extracted | ~9MB |
| KL730 | current + extracted | ~8MB |
合計 ~18MB(極大值)。實際採保守策略 = 不一定每個 chip 都 bundle 舊版(KL630/KL730 舊版可能 SDK release 取不到)、估算 +7MB。
macOS dmg 從 163MB → ~170MB(+4-5%)、使用者「+5MB 接受」決策對齊。
Consequences
正面影響
- 解決真實痛點:拿到舊 KDP1 dongle 完全不能用的情境消除(A 階段)、新世代 dongle KL630/KL730 變可用(B 階段)、進階使用者可手動切版本(B2 階段)
- 架構乾淨:新
firmware/模組與既有flash/分離、職責清楚、未來擴 KL830 / KL530 有明確 hook 點 - 跨平台一致:三平台同走 KneronPLUS Python API、無 Windows-only 依賴、維護成本均勻
- 回溯可追:本 ADR + 研究檔(research-kl520-fw-management/)+ TDD v2/firmware-management.md 留下完整決策痕跡、未來新人接手不會問「為何 Q9 砍了又做」
負面影響(接受的取捨)
- +7MB 安裝包(B 階段、A 階段 +0KB):macOS dmg 從 163MB → ~170MB、使用者已接受
- Brick 風險未完全消除:KL720 升級會寫 flash、升級中拔 USB 仍有 brick 可能(緩解:UI 警告、不打包 DFUT 但提供內部 SOP)
- 法律 / 簽章授權待釐清:Kneron firmware redistribution(含 KDP1 / 舊版)需發佈前評估、與 R5-B4 同性質、不阻塞開發但是 PRD P0 懸念
- 15.5 人天工時:比原估 11-12 多 ~30%、主因 B2 階段「面向一般使用者」UX safety net + 多版本管理 + M9-6 SDK 驗證
- B 階段對 KL630/KL730 SDK 行為仍有未知:M9-6 驗證後可能需要升級 KneronPLUS wheel、有 KL520/KL720 regression 風險
- CURRENT_VERSION 機制需要 A → B2 migration:A 階段 firmware 檔扁平放、B2 階段才搬進版本目錄、需小心不破壞 A 階段已 commit 路徑
風險
完整風險清單見 v2/firmware-management.md §10(R-FW-1 ~ R-FW-12、R-TAR-1 ~ R-TAR-4 合計 16 條)。最關鍵:
| # | 風險 | 等級 |
|---|---|---|
| R-FW-8 | KneronPLUS SDK 對 KL630/KL730 API 不可預測 | 高 |
| R-FW-11 | 一般使用者誤觸降版 brick 風險 | 高 |
| R-FW-1 | 升級中拔除 device(KL720 寫 flash 階段) | 中 |
Alternatives Considered
替代方案 1:不做 FW 管理
| 維度 | 評估 |
|---|---|
| 工時 | 0 |
| 痛點解決 | 不解 |
| 否決原因 | 痛點 #1(KDP1 dongle 不能用)是真實且高頻場景、使用者明確要求做 |
替代方案 2:用 DFUT.exe(warrenchen 雲端版方案)
| 維度 | 評估 |
|---|---|
| 工時 | 較少(直接呼叫 .exe) |
| 跨平台 | Windows-only、macOS / Linux 完全不通 |
| 安裝包衝擊 | +30MB Qt5 binary |
| 否決原因 | visionA-local 是三平台 desktop app、Windows-only 工具不接受 |
替代方案 3:只做內部 dev mode 降版(非面向一般使用者)
| 維度 | 評估 |
|---|---|
| 工時 | 少(不用做 UX safety net、~12 人天) |
| 痛點解決 | 痛點 #4(舊 model 相容性)不解、仍需技術支援介入 |
| 否決原因 | 使用者明確決策(2026-05-24):手動降版面向一般使用者、不只 dev mode |
替代方案 4:多版本目錄結構選 symlink / 副本
| 維度 | 選 A symlink | 選 B 副本 | 選 C metadata(本期選此) |
|---|---|---|---|
| 跨平台 | Windows symlink 需 admin、Windows zip/tar 處理 symlink 不一致 | 完美跨平台 | 完美跨平台 |
| 空間 | 最省 | 每 chip 多一份(+7-8MB) | 最省(只多一個單行檔) |
| 複雜度 | 高(symlink fall-back 邏輯) | 低 | 低(讀 metadata 一行) |
替代方案 5:等 A 階段驗證後再評估 B
| 維度 | 評估 |
|---|---|
| 工時 | A 階段 5 人天先交付 |
| 風險 | A → B 整合時的 .tar handling / chip 判斷 / multi-version migration 必須重整 A 階段已 commit 程式碼 |
| 否決原因 | 使用者明確要求一次做完、且 ADR / TDD 一次定稿能避免 A 階段做出不利 B 階段擴展的設計 |
Related
| 編號 | 關聯 |
|---|---|
| R5-Q9 | 第二輪「韌體燒錄 flash → B 砍掉」、本 ADR 翻案 |
| R5-B4 | 「Kneron 預置模型 re-distribution 授權」未解決問題、firmware redistribution 同性質、發佈前統一處理 |
| R5-E | 60s 啟動 hard timeout、FW 升降版不在啟動 pipeline、無關 |
| 2026-04-21 commit | KL520 reset bug fix、本 ADR 必須維持「升級成功後 needsReset=true」確保不踩 Error 15 |
| watchServer Error state | v2/server-lifecycle.md、FW 升降版失敗不觸發 server Error state |
TDD v2/firmware-management.md |
本 ADR 對應的 TDD 章節、含完整 API / 流程 / 工時 / 風險 |
PRD 02-prd/features/feature-firmware-management.md v2.2 |
對應 user story(US-FW-1 ~ US-FW-3)與成功指標 |
| research-kl520-fw-management/ | 本 ADR 的研究依據(含 warrenchen 實作分析、SDK API 落差、.tar handling、降版 UX 需求、M9-6 弱驗證結果) |
Compliance
- Architect 與 PM Agent 確認本 ADR 影響業務指標(FW 升級流程是 PRD v2.2 新功能)
- 成本影響已評估:開發 15.5 人天 + 基礎設施 +7MB 安裝包 + 維運 0(無 OTA 通道、無監控 SaaS 需求)
- 與 Kneron 取得 firmware redistribution 授權(發佈前必須完成、不阻塞開發)
- Design Agent 確認 UX 多層 safety net 落地(二次確認 modal + DOWNGRADE 輸入 + persistent banner)
變更記錄
| 日期 | 版本 | 變更 | 作者 |
|---|---|---|---|
| 2026-05-24 | 1.0 | 初版產出、Status: Accepted | Architect Agent |
| 2026-05-25 | 1.1 | 三方互審後修:(1) Status 區塊加 2026-05-25 update 反映 M9-6 弱驗證新事實(wheel 三平台版本不一致 + AC-FW-3.5 延後 B 階段);(2) Context R5-Q9 行號改為描述式引用(不寫具體 L 行號);(3) Related 表補 PRD v2.2 條目;(4) 不改 Decision/Alternatives/Compliance 主體(決策邏輯沒變、仍 Accepted) | Architect Agent |