# 01 — NPU 硬件架构与驱动基础 ## 一、RK3568 NPU 硬件架构 ### 1.1 整体结构 ``` RK3568 SoC 内部 ┌──────────────────────────────────────────────────────┐ │ CPU 子系统 (4×Cortex-A55) │ │ ┌──────────────────────────────────────────────┐ │ │ │ Linux 应用层 (你的保护程序) │ │ │ │ │ │ │ │ │ ▼ rknn_api.h (librknnrt.so) │ │ │ │ ┌─────────────────────────────────────┐ │ │ │ │ │ RKNN Runtime (用户态驱动) │ │ │ │ │ │ - 模型加载/解析 │ │ │ │ │ │ - 内存管理 (DMA buffer 分配) │ │ │ │ │ │ - 任务提交/同步 │ │ │ │ │ └──────────────┬──────────────────────┘ │ │ │ └─────────────────┼────────────────────────────┘ │ │ │ ioctl() │ │ ┌─────────────────▼─────────────────────────────┐ │ │ │ NPU 内核驱动 (drivers/rknpu/) │ │ │ │ - 电源/时钟管理 │ │ │ │ - 中断处理 (推理完成通知) │ │ │ │ - MMU (NPU 有自己的 IOMMU) │ │ │ └──────────────────┬───────────────────────────┘ │ │ │ AXI 总线 │ │ ┌──────────────────▼───────────────────────────┐ │ │ │ NPU 硬件 (3 个 NPU 核心) │ │ │ │ │ │ │ │ ┌──────────┐ ┌──────────┐ ┌──────────┐ │ │ │ │ │ NPU Core0│ │ NPU Core1│ │ NPU Core2│ │ │ │ │ │ • MAC阵列│ │ • MAC阵列│ │ • MAC阵列│ │ │ │ │ │ • 卷积加速│ │ • 卷积加速│ │ • 卷积加速│ │ │ │ │ │ • 本地SRAM│ │ • 本地SRAM│ │ • 本地SRAM│ │ │ │ │ └──────────┘ └──────────┘ └──────────┘ │ │ │ │ │ │ │ │ 合计: 1 TOPS (INT8), 192 INT8 MAC/cycle │ │ │ └───────────────────────────────────────────────┘ │ │ │ │ DDR (共享内存, NPU 通过 IOMMU 访问) │ └──────────────────────────────────────────────────────┘ ``` ### 1.2 关键硬件特性 | 特性 | 说明 | 对波形识别的影响 | |------|------|------| | 3 个独立 NPU 核心 | 可并行执行 3 个不同任务 | 可以同时跑故障识别 + 谐波分析 | | 每核本地 SRAM | 减少 DDR 访问延迟 | 小模型可能完全放在 SRAM 里 | | 专用卷积加速器 | 卷积+激活+池化 硬件流水线 | 1D-CNN 推理极快 | | 支持非对称量化 | INT8 输入/输出,INT32 累加 | 模型压缩 4×,精度损失 < 0.5% | | IOMMU | NPU 看到连续地址,物理上可以不连续 | 不需要预留大块连续内存 | ### 1.3 NPU 适合的算子 ``` ✅ 完全支持 (NPU 硬件原生): Conv2D, DepthwiseConv2D, FullyConnected AveragePool, MaxPool, GlobalAveragePool ReLU, ReLU6, Sigmoid, Tanh BatchNorm (可融合到 Conv 中) Concat, Reshape, Transpose, Slice ⚠️ 有限支持 (可能回退到 CPU): LeakyReLU (仅部分版本), Softmax (仅末层) LSTM/GRU (支持不完善,量化损失大) ❌ 不支持 (无法在 NPU 上运行): 动态 shape 算子, 自定义算子 RNN 复杂变体, Attention (Transformer 需要 RKNN 2.0+) ``` > **对你的波形识别模型的影响**:选择 1D-CNN 而非 LSTM/Transformer,就是因为 CNN 的算子 NPU 原生支持最优。 --- ## 二、驱动环境搭建 ### 2.1 确认 NPU 驱动已加载 ```bash # 1. 检查 NPU 设备节点 ls -la /dev/rknpu # 预期输出: crw-rw---- 1 root root 10, 58 Jan 1 00:00 /dev/rknpu # 2. 检查内核模块 lsmod | grep rknpu # 预期输出: rknpu xxxxxx 0 # 3. 检查 NPU 使用情况 cat /sys/kernel/debug/rknpu/load # 预期输出: NPU load: 0% ``` 如果设备节点不存在,说明内核没有开启 NPU 驱动。检查内核配置: ```bash # 确认内核编译了 NPU 驱动 zcat /proc/config.gz | grep RKNPU # 应有: CONFIG_RKNPU=y ``` ### 2.2 安装 RKNN Runtime 板端推理只需要 **librknnrt.so**,不需要完整的 RKNN-Toolkit2(那个只在 PC 端做模型转换用)。 ```bash # 方式1: 从 Rockchip SDK 提取 # SDK 路径: external/rknn-toolkit2/rknpu2/runtime/Linux/librknn_api/aarch64/ cp librknnrt.so /usr/lib/ cp rknn_server /usr/bin/ # 可选,用于代理模式 ldconfig ldconfig -p | grep rknnrt # 预期输出: librknnrt.so => /usr/lib/librknnrt.so # 方式2: 从 buildroot 镜像中确认是否已包含 # 创龙 TL3568-EVM 默认 Buildroot 已包含 NPU 驱动 ``` ### 2.3 npu_transfer_proxy(重要) RK3568 推荐使用 **npu_transfer_proxy** 机制:NPU 推理请求从一个代理进程转发,避免每个应用都打开 `/dev/rknpu`。 ```bash # 启动 proxy(通常在 init 脚本中自动启动) npu_transfer_proxy & # 监听 /tmp/rknpu.sock # 应用程序通过 proxy 与 NPU 通信 # librknnrt.so 内部自动通过 proxy,应用层无感知 ``` ### 2.4 快速验证:跑通 YOLOv5 Demo 创龙已提供 YOLOv5 推理 Demo,用来验证 NPU 环境: ```bash # Demo 路径 (在仓库中) # TL3568-EVM.../4-软件资料/Demo/platform-demos/yolov5_object_detect/ # 运行验证 cd /path/to/yolov5_demo ./rknn_yolov5_demo ./model/yolov5s.rknn ./test.jpg # 预期输出: # NPU init success # model load success # inference time: 15.2 ms # detected: person (0.95), car (0.87) ``` 如果这一步跑通了,NPU 环境就是正常的。 --- ## 三、NPU 内存管理要点 ### 3.1 两种内存模式 ``` 模式 A: 拷贝模式 (简单,适合开发阶段) 应用层 buffer → rknn_inputs_set() → 内部拷贝到 NPU DMA buffer + 简单,不需要关心物理内存 - 每次推理多一次 memcpy (~几十 μs) 模式 B: 零拷贝模式 (高效,适合生产环境) 应用层分配 DMA buffer → rknn_set_io_mem() → NPU 直接访问 + 无 CPU 拷贝开销 - 需要通过 DMA API 分配内存 (dma_alloc_coherent 或 ion) ``` ### 3.2 建议 开发阶段先用拷贝模式(代码简单),稳定后改为零拷贝(性能最优)。对于你的波形推理(1~3ms),单次 memcpy 的几十 μs 影响不大。 --- ## 四、NPU 驱动调试命令速查 ```bash # 查看 NPU 负载 cat /sys/kernel/debug/rknpu/load # 查看 NPU 频率 cat /sys/class/devfreq/ffbc0000.npu/cur_freq # 查看 NPU 电源状态 cat /sys/kernel/debug/rknpu/power # 查看最近一次推理耗时 cat /sys/kernel/debug/rknpu/profile # dmesg 中查看 NPU 错误 dmesg | grep -i rknpu dmesg | grep -i "npu.*error" ```