# 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`)後追加兩個新事實: 1. **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。 2. **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 相關的痛點: 1. **拿到舊 dongle 完全不能用**:使用者拿到的 KL520 dongle 若是 KDP1 legacy(pid=0x0200)、插上 visionA-local 後 connect 流程在 `kp.core.load_firmware_from_file` 階段失敗、無法 inference。 2. **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 邏輯的脆弱性。 3. **KL630 / KL730 偵測不到**:scan 階段顯示得到名字、但 `handle_connect` fall-through 到 KL520 路徑、用錯誤的 firmware 檔載入 → 連不上。新世代 dongle 完全不可用。 4. **舊 model 與新 FW 相容性**:進階使用者反映「我的舊 NEF model 在升版 FW 後跑不出結果」、缺乏降版機制。 ### R5-Q9 砍 flash 的歷史決策 `progress.md` 重要決策紀錄 §「第二輪使用者決策 Q9」: > 韌體燒錄 flash → B 砍掉 (行號為動態值、本 ADR 不寫具體 L 行號避免日後 progress.md 增刪後失準;以「第二輪使用者決策 Q9」描述位置為準) 當時砍的理由(推測、原 progress.md 沒留下細節): 1. visionA-local 是「local 推論工具」、不是「dongle 管理工具」、燒 flash 不屬核心使用旅程 2. 燒 flash 有 brick 風險、不想對使用者開放 3. 早期 MVP 範圍縮小、把非必要功能延後 4. 既有「load_firmware 到 RAM」夠用(KL520 USB Boot 每次都重 load、KL720 已預燒 KDP2) ### 為何現在要翻案 1. **痛點 #1 是真實場景**:使用者已陸續遇到舊 KDP1 dongle 完全不能用(Q9 原始假設「既有 load_firmware 到 RAM 夠用」不成立) 2. **同事 warrenchen 雲端版已驗證可做、且安全**:`/tmp/web_academy_prototype/local_service_win/` 有完整實作可參考 3. **範圍可切割**:Q9 砍的是「使用者按按鈕燒任意 model 到 device flash」、本期是「升級到 Kneron 官方 KDP2 標準版本」、避開大部分 brick 與責任風險 4. **跨平台技術可行**: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//fw_scpu.bin + fw_ncpu.bin` load firmware 到 RAM - `kneron_bridge.py:handle_connect()` 已處理 KL720 KDP legacy → 強制 load KDP2 firmware 到 RAM - `DeviceInfo.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// ├── 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 ### 正面影響 1. **解決真實痛點**:拿到舊 KDP1 dongle 完全不能用的情境消除(A 階段)、新世代 dongle KL630/KL730 變可用(B 階段)、進階使用者可手動切版本(B2 階段) 2. **架構乾淨**:新 `firmware/` 模組與既有 `flash/` 分離、職責清楚、未來擴 KL830 / KL530 有明確 hook 點 3. **跨平台一致**:三平台同走 KneronPLUS Python API、無 Windows-only 依賴、維護成本均勻 4. **回溯可追**:本 ADR + 研究檔(research-kl520-fw-management/)+ TDD v2/firmware-management.md 留下完整決策痕跡、未來新人接手不會問「為何 Q9 砍了又做」 ### 負面影響(接受的取捨) 1. **+7MB 安裝包**(B 階段、A 階段 +0KB):macOS dmg 從 163MB → ~170MB、使用者已接受 2. **Brick 風險未完全消除**:KL720 升級會寫 flash、升級中拔 USB 仍有 brick 可能(緩解:UI 警告、不打包 DFUT 但提供內部 SOP) 3. **法律 / 簽章授權待釐清**:Kneron firmware redistribution(含 KDP1 / 舊版)需發佈前評估、與 R5-B4 同性質、不阻塞開發但是 PRD P0 懸念 4. **15.5 人天工時**:比原估 11-12 多 ~30%、主因 B2 階段「面向一般使用者」UX safety net + 多版本管理 + M9-6 SDK 驗證 5. **B 階段對 KL630/KL730 SDK 行為仍有未知**:M9-6 驗證後可能需要升級 KneronPLUS wheel、有 KL520/KL720 regression 風險 6. **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 - [x] Architect 與 PM Agent 確認本 ADR 影響業務指標(FW 升級流程是 PRD v2.2 新功能) - [x] 成本影響已評估:開發 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 |