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:
parent
8c75a6508a
commit
3f02435414
@ -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 dylib(Apple 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 類) |
|
||||
| **推論延遲** | ~25ms(KL520 NPU 硬體推論,不含圖片前處理與網路傳輸) |
|
||||
| **後處理** | YOLO v3 雙尺度偵測 (7×7 + 14×14)、Sigmoid 解碼、信心門檻過濾 (≥0.25)、NMS (IoU 0.45) |
|
||||
| **輸出格式** | 統一 `InferenceResult` JSON:taskType、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)
|
||||
|
||||
189
docs/TDD.md
189
docs/TDD.md
@ -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) |
|
||||
|
||||
推論延遲:~25ms(NPU 硬體推論)
|
||||
|
||||
---
|
||||
|
||||
@ -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` symlink(macOS)或 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`
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user