docs: add F18 KL520 hardware integration specs to PRD + TDD

PRD v2.5:
- Add F18: Kneron KL520 hardware communication integration
  - USB Boot mode with auto firmware loading
  - JSON-RPC bridge architecture (Go → Python → SDK → USB)
  - Tiny YOLO v3 inference verified (~25ms latency)
  - COCO 80-class detection with NMS post-processing

TDD v1.4:
- Update 5.2: Replace placeholder driver with actual implementation
  - KL720Driver with JSON-RPC over stdin/stdout
  - Python bridge command protocol table
  - KL520 USB Boot connection flow
- Add 8.5.13: KL520 technical mapping with architecture diagram,
  inference pipeline code, YOLO post-processing specs,
  Apple Silicon compatibility notes, and verified detection results
- Update 11.5: Add firmware files, kp module, and scripts directory structure
- Update directory structure to match actual driver files

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
jim800121chen 2026-02-28 04:52:22 +08:00
parent 8c75a6508a
commit 3f02435414
2 changed files with 169 additions and 41 deletions

View File

@ -8,8 +8,8 @@
|------|------|
| 文件名稱 | 邊緣 AI 開發平台 PRD |
| 產品名稱 | (暫未定名,以下稱「本平台」) |
| 版本 | v2.3 |
| 日期 | 2026-02-24 |
| 版本 | v2.5 |
| 日期 | 2026-02-28 |
| 狀態 | 更新中 |
---
@ -1224,6 +1224,23 @@ Kneron Dongle Arduino 開發板 非 Kneron 晶片
| **解除安裝** | macOS: .app 內含解除安裝選項、Windows: 控制台「新增或移除程式」標準流程 |
| **狀態** | 規劃中,待 CLI 安裝穩定後實作 |
#### F18 — Kneron KL520 硬體通訊整合
| 項目 | 規格 |
|------|------|
| **概述** | KL520 USB Dongle 的完整通訊管線已驗證,涵蓋 USB 偵測、韌體載入、模型載入、即時推論與結果後處理 |
| **支援裝置** | Kneron KL520 (VID 0x3231, PID 0x0100)USB 2.0 High-Speed |
| **USB Boot 模式** | KL520 無板載 Flash 韌體,每次連線時 host 自動上傳 fw_scpu.bin + fw_ncpu.bin |
| **SDK** | Kneron PLUS SDK v3.1.2,從 C 原始碼編譯為 macOS dylibApple Silicon 透過 Rosetta 2 執行) |
| **通訊架構** | Go Server → JSON-RPC (stdin/stdout) → Python Bridge (`kneron_bridge.py`) → Kneron PLUS SDK (kp) → USB → KL520 |
| **支援模型** | Kneron NEF 格式,已驗證 Tiny YOLO v3 (model_id=19, 輸入 224×224, COCO 80 類) |
| **推論延遲** | ~25msKL520 NPU 硬體推論,不含圖片前處理與網路傳輸) |
| **後處理** | YOLO v3 雙尺度偵測 (7×7 + 14×14)、Sigmoid 解碼、信心門檻過濾 (≥0.25)、NMS (IoU 0.45) |
| **輸出格式** | 統一 `InferenceResult` JSONtaskType、latencyMs、detections[{label, confidence, bbox{x,y,width,height}}] |
| **Python Bridge 指令** | `scan`(裝置掃描)、`connect`(連線+自動韌體載入)、`load_model`NEF 模型載入)、`inference`base64 圖片推論)、`disconnect` |
| **圖片前處理** | OpenCV 解碼 → BGR565 轉換 → KP_IMAGE_FORMAT_RGB565支援 JPEG/PNG/BMP |
| **驗證結果** | 街道場景圖片偵測到 8 個物件person ×2、car ×5、bicycle ×1結果正確 |
---
## B5. 功能路線圖Post-MVP

View File

@ -7,9 +7,9 @@
| 項目 | 內容 |
|------|------|
| 文件名稱 | 邊緣 AI 開發平台 TDD |
| 對應 PRD | PRD-Integrated.md v2.2 |
| 版本 | v1.2 |
| 日期 | 2026-02-24 |
| 對應 PRD | PRD-Integrated.md v2.5 |
| 版本 | v1.4 |
| 日期 | 2026-02-28 |
| 狀態 | 更新中 |
---
@ -496,9 +496,8 @@ server/
│ ├── driver/ # 裝置驅動層
│ │ ├── interface.go # DeviceDriver 介面定義
│ │ ├── kneron/
│ │ │ ├── kl720_driver.go # KL720 Dongle 驅動 (MVP)
│ │ │ ├── kl730_driver.go # KL730 / KNEO Pi 驅動 (Phase 1)
│ │ │ └── kneron_sdk.go # Kneron PLUS SDK 封裝
│ │ │ ├── kl720_driver.go # Kneron Driver (KL520/KL720, JSON-RPC → Python bridge)
│ │ │ └── detector.go # USB 裝置偵測 (透過 Python bridge scan)
│ │ └── mock/
│ │ └── mock_driver.go # 模擬驅動 (開發/測試用)
│ │
@ -1201,48 +1200,65 @@ type BBox struct {
}
```
### 5.2 Kneron KL720 Driver 實作策略
### 5.2 Kneron Driver 實作策略(已實作)
Go Driver 透過 Python subprocess`kneron_bridge.py`)與 Kneron PLUS SDK 通訊,採用 JSON-RPC over stdin/stdout 模式。
```
Go Server ──stdin/stdout──► kneron_bridge.py ──ctypes──► libkplus.dylib ──USB──► KL520
JSON-RPC kp module BULK EP
```
```go
// internal/driver/kneron/kl720_driver.go
type KL720Driver struct {
info DeviceInfo
sdk *KneronSDK // Kneron PLUS SDK 封裝
connected bool
inferring bool
mu sync.Mutex
info driver.DeviceInfo
connected bool
inferring bool
modelLoaded string
mu sync.Mutex
scriptPath string // kneron_bridge.py 路徑
pythonCmd *exec.Cmd // Python 子進程
stdin io.WriteCloser // JSON 指令輸入
stdout *bufio.Scanner // JSON 回應輸出
pythonReady bool
}
// USB 裝置識別
var KL720USBFilter = USBFilter{
VendorID: 0x3231, // Kneron VID (需確認實際值)
ProductID: 0x0200, // KL720 PID (需確認實際值)
}
// USB 裝置識別(已確認實際值)
const KneronVendorID uint16 = 0x3231
// KL520 PID = 0x0100, KL720 PID = 0x0200
func (d *KL720Driver) Connect() error {
d.mu.Lock()
defer d.mu.Unlock()
// Python venv 自動偵測scripts/venv/bin/python3 → 系統 python3
func (d *KL720Driver) resolvePython() string { ... }
// 1. 透過 Kneron PLUS SDK 初始化裝置
// 2. 取得裝置資訊 (kp_get_system_info)
// 3. 設定連線狀態
return d.sdk.Connect(d.info.Port)
}
// 啟動 Python bridge設定 DYLD_LIBRARY_PATH等待 {"status":"ready"}
func (d *KL720Driver) startPython() error { ... }
func (d *KL720Driver) Flash(modelPath string, progressCh chan<- FlashProgress) error {
// 1. 驗證 NEF 檔案
// 2. 進入 bootloader / DFU 模式
// 3. 透過 kp_load_model_from_file() 上傳 NEF
// 4. 回報進度
// 5. 驗證 CRC
// 6. 重啟裝置
}
// JSON-RPC 通訊Marshal → stdin → stdout → Unmarshal
func (d *KL720Driver) sendCommand(cmd map[string]interface{}) (map[string]interface{}, error) { ... }
```
func (d *KL720Driver) ReadInference() (*InferenceResult, error) {
// 透過 Kneron PLUS SDK 讀取推論結果
// 解析 Kneron 格式 → 統一 InferenceResult
}
**Python Bridge 指令協定:**
| 指令 | 參數 | 回應 | 說明 |
|------|------|------|------|
| `scan` | — | `{devices: [{port, firmware, kn_number, product_id}]}` | USB 裝置掃描 |
| `connect` | `port`, `index` | `{status, firmware, kn_number}` | 連線 + 自動韌體載入 |
| `load_model` | `path` | `{status, model_id, target_chip}` | NEF 模型載入 |
| `inference` | `image_base64` | `{taskType, latencyMs, detections[...]}` | 圖片推論 |
| `disconnect` | — | `{status}` | 斷線 |
**KL520 連線流程USB Boot 模式):**
```
connect_devices(port_id)
→ set_timeout(10000ms)
→ 偵測 firmware 狀態
→ if "Loader": load_firmware_from_file(scpu, ncpu)
→ sleep(5s) 等待 reboot
→ 重新 scan + connect
→ 回傳 firmware 版本
```
### 5.3 Driver 註冊流程
@ -1642,7 +1658,87 @@ Server 啟動 → deps.PrintStartupReport(logger)
| macOS Apple Silicon | tar.gz | `edge-ai-platform_v0.1.0_darwin_arm64.tar.gz` |
| Windows x64 | zip | `edge-ai-platform_v0.1.0_windows_amd64.zip` |
每個 archive 含:`edge-ai-server` binary + `data/models.json` + `scripts/kneron_bridge.py` + `scripts/requirements.txt`
每個 archive 含:`edge-ai-server` binary + `data/models.json` + `scripts/kneron_bridge.py` + `scripts/requirements.txt` + `scripts/firmware/KL520/`
#### 8.5.13 Kneron KL520 硬體通訊整合F18
| 前端元件 | 後端模組 | 腳本/資源 |
|---------|---------|----------|
| 既有 inference panel | `internal/driver/kneron/kl720_driver.go` | `scripts/kneron_bridge.py` |
| 既有 device panel | `internal/driver/kneron/detector.go` | `scripts/firmware/KL520/fw_scpu.bin` |
| — | `internal/driver/interface.go` | `scripts/firmware/KL520/fw_ncpu.bin` |
**通訊架構:**
```
┌──────────┐ JSON-RPC ┌──────────────────┐ ctypes ┌──────────────┐ USB BULK ┌───────┐
│ Go Server│──stdin/out──►│ kneron_bridge.py │──────────►│libkplus.dylib│──────────►│ KL520 │
│ (Gin) │◄────────────│ (Python 3.9) │◄──────────│(Kneron PLUS) │◄──────────│ (NPU) │
└──────────┘ └──────────────────┘ └──────────────┘ └───────┘
```
**kneron_bridge.py 推論流程:**
```python
# 1. 接收 base64 圖片
img_bytes = base64.b64decode(image_base64)
# 2. OpenCV 解碼 + 色彩空間轉換
img = cv2.imdecode(np.frombuffer(img_bytes, np.uint8), cv2.IMREAD_COLOR)
img_bgr565 = cv2.cvtColor(img, cv2.COLOR_BGR2BGR565)
# 3. 建立推論描述符
inf_config = kp.GenericImageInferenceDescriptor(
model_id=model_id,
input_node_image_list=[kp.GenericInputNodeImage(
image=img_bgr565,
image_format=kp.ImageFormat.KP_IMAGE_FORMAT_RGB565,
)]
)
# 4. 送出推論 + 接收結果
kp.inference.generic_image_inference_send(device_group, inf_config)
result = kp.inference.generic_image_inference_receive(device_group)
# 5. YOLO v3 後處理decode → sigmoid → NMS → detections[]
```
**YOLO v3 後處理細節:**
| 項目 | 規格 |
|------|------|
| 偵測頭 | 雙尺度7×7大物件+ 14×14小物件 |
| Anchor boxes | 7×7: (81,82), (135,169), (344,319)14×14: (10,14), (23,27), (37,58) |
| 輸出通道 | 255 = 3 anchors × (5 + 80 classes) |
| 信心門檻 | ≥ 0.25 |
| NMS IoU 門檻 | 0.45 |
| 類別 | COCO 80 類person, bicycle, car, ... toothbrush |
**macOS Apple Silicon 相容性:**
```
Kneron PLUS SDK (C source) ──編譯──► libkplus.dylib (x86_64)
Python 3.9 (x86_64 via Rosetta 2) ──ctypes.cdll.LoadLibrary──► libkplus.dylib
pendian.h 修正:#if defined(__APPLE__) #include <machine/endian.h>
CMakeLists.txt 修正:移除 -Werror改用 -Wno-unused-but-set-variable
```
**驗證結果bike_cars_street_224x224.bmp**
| 物件 | 信心值 | BBox (x, y, w, h) |
|------|--------|-------------------|
| car | 0.998 | (0.66, 0.38, 0.20, 0.37) |
| car | 0.971 | (0.53, 0.34, 0.43, 0.43) |
| person | 0.965 | (0.26, 0.34, 0.10, 0.44) |
| person | 0.754 | (0.18, 0.34, 0.26, 0.43) |
| car | 0.499 | (0.42, 0.41, 0.12, 0.07) |
| bicycle | 0.465 | (0.26, 0.50, 0.12, 0.37) |
| car | 0.368 | (0.16, 0.37, 0.05, 0.05) |
| car | 0.294 | (0.45, 0.43, 0.06, 0.09) |
推論延遲:~25msNPU 硬體推論)
---
@ -1870,9 +1966,24 @@ clean:
**安裝內容:**
1. Edge AI Server binary + data 檔案
2. Python venv`$INSTALL_DIR/venv`+ pyusb
2. Python venv`$INSTALL_DIR/venv`+ pyusb + numpy + opencv-python-headless
3. libusb 系統驅動macOS: Homebrew / Linux: apt / Windows: Zadig 提示)
4. `/usr/local/bin/edge-ai-server` symlinkmacOS或 PATH 設定Windows
5. KL520 韌體檔案:`scripts/firmware/KL520/fw_scpu.bin`, `fw_ncpu.bin`
6. Kneron PLUS SDK`kp` Python module + `libkplus.dylib`macOS/ `libkplus.so`Linux
**scripts 目錄結構:**
```
scripts/
├── kneron_bridge.py # Go↔Kneron JSON-RPC bridge
├── requirements.txt # numpy, opencv-python-headless, pyusb
├── firmware/
│ └── KL520/
│ ├── fw_scpu.bin # SCPU 韌體 (52KB)
│ └── fw_ncpu.bin # NCPU 韌體 (40KB)
└── venv/ # Python venv安裝時建立
└── lib/.../site-packages/kp/ # Kneron PLUS SDK module
```
**解除安裝:**
- macOS: `rm -rf ~/.edge-ai-platform && sudo rm -f /usr/local/bin/edge-ai-server`