RV1106嵌入式AI开发全攻略:从环境搭建到NPU部署实战

📅 2026/6/16 11:41:57
RV1106嵌入式AI开发全攻略:从环境搭建到NPU部署实战
1. 项目概述为什么RV1106值得你投入时间如果你正在寻找一款既能跑轻量级Linux又内置了MCU和0.5T NPU的嵌入式芯片并且对成本、功耗和图像处理有综合要求那么瑞芯微的RV1106很可能就是你的“梦中情U”。我最近刚用它完成了一个智能门铃的项目从选型、画板、烧写到应用开发算是把这条路上的坑都踩了一遍。今天就来聊聊基于RV1106做开发到底是怎么一回事以及有哪些你绕不开的关键点。RV1106这颗芯片的定位非常清晰它不是追求极致性能的RK3588而是瞄准了智能视觉IoT终端市场。它把一颗Cortex-A7应用处理器、一个实时MCU、一个0.5TOPS的NPU、以及一套不错的ISP图像信号处理器打包在一起。这意味着你可以用一颗芯片同时搞定视频流的采集、AI分析、逻辑控制和网络通信省去了外挂MCU或NPU的麻烦和成本。对于像人脸识别门锁、低功耗摄像头、工业视觉检测盒子这类产品RV1106提供了一个相当优雅的“单芯片解决方案”。2. 开发环境搭建与SDK获取上手RV1106第一步不是急着写代码而是把“战场”布置好。官方的开发环境基于Linux强烈建议你使用Ubuntu 18.04或20.04 LTS版本这是经过官方验证最稳定的。别用太新的发行版各种依赖库的版本冲突能让你怀疑人生。2.1 获取官方SDK瑞芯微的SDK主要通过其官方的“瑞芯微驱动助手”工具进行下载和管理。你需要先在瑞芯微的开发者网站注册账号并通过审核。这个过程可能需要一点时间建议提前准备。登录后在“下载中心”找到RV1106的SDK包。通常它会被命名为类似rv1106_linux_sdk_release_YYYYMMDD.tgz这样的格式。这个SDK包体积不小包含了U-Boot、Kernel、Buildroot/Yocto根文件系统、交叉编译工具链、以及各种外设的驱动和示例代码。注意官方SDK更新可能不那么频繁但遇到问题首先检查SDK版本。有时一个已知的Bug在最新版本中已被修复。下载后务必校验MD5或SHA256文件损坏会导致后续编译出现各种诡异错误。2.2 搭建交叉编译环境SDK里一般会自带交叉编译工具链通常在prebuilts/gcc/linux-x86/arm目录下。你需要做的是将其路径加入到系统的PATH环境变量中。# 假设你的SDK解压目录为 /home/yourname/rv1106_sdk export RK_TOOLCHAIN/home/yourname/rv1106_sdk/prebuilts/gcc/linux-x86/arm/gcc-arm-8.3-2019.03-x86_64-arm-linux-gnueabihf/bin export PATH$RK_TOOLCHAIN:$PATH然后通过arm-linux-gnueabihf-gcc -v命令验证工具链是否生效。接下来安装一些必要的编译依赖包sudo apt-get update sudo apt-get install git-core gitk git-gui gcc-arm-linux-gnueabihf \ u-boot-tools device-tree-compiler mtools \ libssl-dev ncurses-dev libncurses5-dev \ parted libudev-dev libusb-1.0-0-dev python-linaro-image-tools \ linaro-image-tools gcc-aarch64-linux-gnu g-aarch64-linux-gnu \ autoconf autotools-dev libsigsegv2 m4 intltool libdrm-dev \ curl sed make binutils build-essential gcc g bash \ patch gzip bzip2 perl tar cpio python unzip rsync file bc wget \ libncurses5 libqt4-dev libglib2.0-dev libgtk2.0-dev \ libglade2-dev cvs git mercurial rsync openssh-client subversion \ asciidoc w3m dblatex graphviz python-matplotlib libc6-i386 \ lib32stdc6 lib32z1这个列表看起来很长但很多是构建完整Linux系统所必需的。一次性装好能避免后续编译时频繁中断。2.3 编译基础固件SDK目录下通常有一个顶层的build.sh脚本这是编译的入口。但在第一次编译前你需要选择板级配置。RV1106有不同的内存配置如RV1106G2内置内存标准版外接DDR对应的配置文件也不同。cd /home/yourname/rv1106_sdk # 查看可用的板级配置通常类似 rv1106-emmc-tb.config, rv1106-nand-tb.config 等 ls rockdev/ | grep .config # 加载配置例如选择EMMC版本的测试板配置 ./build.sh rv1106-emmc-tb.config # 开始全自动编译这会依次编译U-Boot, Kernel, Rootfs并打包成固件 ./build.sh第一次编译耗时较长可能需要一两个小时取决于你的电脑性能。编译成功后生成的固件通常是rockdev/目录下的update.img就是可以烧录到板子上的完整系统镜像。3. 系统启动流程与固件烧录理解RV1106的启动顺序对于调试和故障排查至关重要。它的启动流程是典型的Rockchip芯片流程BootROM - SPL (U-Boot Minimal) - U-Boot Proper - Kernel - RootfsBootROM芯片内部掩膜ROM出厂即固化。它负责检测启动介质如eMMC、SPI NAND、SD卡并加载位于特定位置的SPL。SPL这是一个极其精简的U-Boot主要作用是初始化DRAM为加载完整U-Boot做准备。因为片内SRAM很小完整的U-Boot必须载入到外部DDR中运行。U-Boot Proper完整的引导加载程序。它进一步初始化硬件加载设备树DTS最后从存储介质中加载Linux内核和设备树到内存并跳转执行。KernelLinux内核启动接管硬件挂载根文件系统。Rootfs根文件系统启动运行初始化进程如systemd或busybox init最终启动你的应用程序。3.1 烧录模式与工具RV1106支持两种主要的烧录方式Loader模式也称为MaskROM模式。这是芯片最底层的烧录模式。通常需要短接板子上的测试点让芯片在上电时直接进入BootROM等待主机通过USB OTG口发送烧录指令。这种方式用于板子“变砖”后的救砖或者第一次烧写空片。U-Boot模式当板子上已有可运行的U-Boot时可以通过串口中断U-Boot启动进入U-Boot命令行使用rockusb或ums命令让板子模拟成一个USB存储设备然后进行烧录。这种方式更常用也更安全。官方提供的烧录工具是RKDevToolWindows或upgrade_toolLinux。我强烈推荐在Linux下使用upgrade_tool脚本化操作更高效。3.2 使用 upgrade_tool 烧录首先确保你的开发板通过USB OTG口连接到电脑并进入Loader模式具体操作需参考你的底板原理图通常是按住某个按键或短接测试点上电。# 1. 查看设备是否被识别 lsusb | grep -i rockchip # 应该能看到类似 “2207:1106” 的ID其中1106代表RV1106。 # 2. 使用upgrade_tool烧录 cd /home/yourname/rv1106_sdk # 假设工具在 tools/linux/Linux_Upgrade_Tool/ 下 sudo ./tools/linux/Linux_Upgrade_Tool/upgrade_tool uf rockdev/update.img烧录过程会有进度条显示。完成后让板子重新上电就能从串口看到启动日志了。实操心得烧录失败最常见的原因有两个。一是USB线或接口接触不良换条质量好的USB线试试。二是没有正确进入Loader模式仔细核对板子的进入方法。另外upgrade_tool可能需要sudo权限才能访问USB设备。4. 外设驱动与硬件接口调试RV1106的引脚功能复用非常灵活几乎所有GPIO都可以通过配置复用为不同的功能UART, I2C, SPI, PWM等。这带来了设计的灵活性也增加了软件配置的复杂性。4.1 设备树DTS配置Linux内核通过设备树Device Tree来描述硬件。RV1106的DTS文件位于SDK的kernel/arch/arm/boot/dts/目录下。你需要修改的是对应你板型的DTS文件例如rv1106-evb.dts。假设你要启用一个I2C接口连接一个传感器如光照传感器BH1750你需要确认引脚复用查阅RV1106的Datasheet找到支持I2C功能的引脚组。例如I2C1可能对应GPIO0_C0SCL和GPIO0_C1SDA。在DTS中启用I2C控制器并配置引脚// 在 i2c1 节点中取消状态禁用并设置时钟频率 i2c1 { status okay; // 将默认的disabled改为okay clock-frequency 100000; // 标准模式100kHz pinctrl-names default; pinctrl-0 i2c1m0_xfer; // 使用引脚复用组 i2c1m0_xfer // 添加你的设备子节点 bh1750: light-sensor23 { compatible rohm,bh1750; reg 0x23; status okay; }; };配置引脚控制Pinctrl确保在pinctrl节点中对应的引脚复用组如i2c1m0_xfer已经正确定义了引脚和上下拉等电气属性。这部分通常在通用的DTSI文件中已经定义好你只需要引用即可。修改DTS后需要重新编译内核并更新到板子上。4.2 调试外设以I2C为例驱动加载成功后如何在用户空间验证# 查看I2C总线是否被识别 ls /dev/i2c-* # 应该能看到 /dev/i2c-1 # 使用i2c-tools工具进行扫描 sudo apt-get install i2c-tools sudo i2cdetect -y 1 # 这个命令会扫描I2C总线1上的所有地址如果BH1750地址0x23连接正常你会看到对应的地址被显示出来。如果扫描不到设备按以下顺序排查硬件连接用万用表测量SDA/SCL线是否通电压是否正常通常是3.3V。上拉电阻是否焊接通常4.7K-10K欧姆。引脚复用确认DTS配置的引脚与实际硬件连接的引脚是否一致。可以通过cat /sys/kernel/debug/pinctrl/pinctrl/pinmux-pins查看当前引脚的复用状态。设备地址确认传感器地址是否正确BH1750地址可以是0x23或0x5C取决于ADDR引脚电平。4.3 利用内置MCURV1106内置的MCU是一个亮点它可以独立于A7核心运行处理实时性要求高的任务如电机控制、ADC高速采样或者在外设休眠时维持低功耗运行。瑞芯微提供了MCU的SDK通常是基于RTOS如FreeRTOS。开发流程是在A7侧的Linux系统中通过一个特定的驱动程序如rpmsg与MCU建立通信通道。MCU程序独立编译生成二进制固件。在Linux启动后将MCU固件加载到其专属内存中并启动它。双方通过共享内存或消息队列进行数据交换。这部分的开发相对独立需要参考瑞芯微提供的《RV1106 MCU开发指南》。5. NPU开发释放0.5T算力RV1106的NPU神经网络处理单元是其智能化的核心。它支持INT8/INT16量化能高效运行诸如人脸检测、车牌识别、手势识别等模型。5.1 模型转换与部署流程你不能直接把PyTorch或TensorFlow训练出的.pt或.pb模型扔给NPU。需要经过瑞芯微的RKNN-Toolkit2工具链进行转换。标准流程如下模型训练与导出在PC上使用主流框架训练模型并导出为ONNX格式。这是目前兼容性最好的中间格式。模型转换在PC上安装RKNN-Toolkit2。这是一个Python工具包它负责将ONNX模型转换成RV1106 NPU能识别的.rknn格式。在这个过程中你可以进行量化精度从FP32降到INT8以提升速度、降低功耗和内存占用、模型优化算子融合、内存优化和性能模拟。from rknn.api import RKNN rknn RKNN() # 加载ONNX模型 ret rknn.load_onnx(model./mobilenet_v2.onnx) # 构建模型指定目标平台为RV1106 ret rknn.build(do_quantizationTrue, dataset./dataset.txt, target_platformrv1106) # 导出RKNN模型 ret rknn.export_rknn(./mobilenet_v2.rknn) rknn.release()关键点量化需要提供一个校准数据集dataset.txt里是图片路径列表用于统计激活值的分布。量化是精度和速度的权衡需要仔细评估。模型部署将生成的.rknn模型文件放到RV1106板子的文件系统中。在C/C应用程序中调用瑞芯微提供的RKNN API来加载模型、创建推理会话、输入数据并获取输出。#include “rknn_api.h” rknn_context ctx; // 1. 加载模型 rknn_init(ctx, model_path, 0, 0, NULL); // 2. 获取模型输入输出信息 rknn_input_output_num io_num; rknn_query(ctx, RKNN_QUERY_IN_OUT_NUM, io_num, sizeof(io_num)); // 3. 设置输入 rknn_input inputs[1]; inputs[0].index 0; inputs[0].buf image_data; inputs[0].size input_size; inputs[0].pass_through RKNN_INPUT_PASS_THROUGH; // 或进行预处理 rknn_inputs_set(ctx, io_num.n_input, inputs); // 4. 运行推理 rknn_run(ctx, nullptr); // 5. 获取输出 rknn_output outputs[io_num.n_output]; rknn_outputs_get(ctx, io_num.n_output, outputs, NULL); // 6. 后处理 outputs[0].buf 中的数据... // 7. 释放资源 rknn_outputs_release(ctx, io_num.n_output, outputs); rknn_destroy(ctx);5.2 NPU开发避坑指南算子支持不是所有TensorFlow/PyTorch算子都被NPU支持。在转换前务必查阅《RKNN-Toolkit2 OP支持列表》。遇到不支持的算子可能需要修改模型结构或用支持的算子组合替代。内存限制RV1106的NPU有专用的内部SRAM但容量有限。过大的模型如一些大型目标检测网络可能无法运行。RKNN-Toolkit2在转换时会评估内存占用如果超限会报错。这时需要考虑模型剪枝、量化或选择更轻量的模型。预处理对齐模型训练时的数据预处理归一化、减均值除方差必须与推理代码中的预处理完全一致否则精度会严重下降。RKNN API提供了RKNN_INPUT_PASS_THROUGH模式允许你在CPU上完成复杂的预处理再将数据传给NPU也支持直接在NPU内部进行简单的归一化。多模型切换如果需要动态切换不同模型注意rknn_destroy和rknn_init是有开销的。对于实时性要求高的场景可以考虑预加载多个模型上下文或者使用模型流水线技术。6. ISP与摄像头开发RV1106集成了第三代ISP支持多帧HDR、3DNR时域降噪、WDR宽动态等算法能显著提升图像质量这对于视觉AI应用至关重要。6.1 摄像头接口与配置RV1106支持MIPI CSI和DVP两种摄像头接口最多可接3个sensor。驱动开发主要围绕Media Controller (媒体控制器)和V4L2 (Video for Linux 2)框架。Sensor驱动首先确保你的摄像头Sensor如OV5648、SC2310的驱动已经在内核中启用编译为模块或内置。这需要在Linux内核配置中打开对应的CONFIG_VIDEO_XXX。设备树配置在DTS中描述摄像头硬件连接。这包括指定I2C总线用于配置sensor寄存器。配置MIPI CSI或DVP接口的引脚。定义时钟树sensor需要主时钟MCLK。链接到V4L2的subdev架构。i2c1 { status okay; ov5648: ov564836 { compatible ovti,ov5648; reg 0x36; clocks cru CLK_CIF_OUT; clock-names xvclk; // ... 其他属性如复位引脚、电源控制等 port { ov5648_out: endpoint { remote-endpoint mipi_in_ucam0; ># 查看识别到的视频设备 v4l2-ctl --list-devices # 通常会是 /dev/video0, /dev/video1... # 获取设备支持格式 v4l2-ctl -d /dev/video0 --list-formats-ext # 使用GStreamer或ffmpeg进行抓图预览 gst-launch-1.0 v4l2src device/dev/video0 ! videoconvert ! ximagesink6.2 ISP调优出厂默认的ISP参数可能不适合你的具体场景如室内、室外、低光。瑞芯微提供了rkisp-tuning工具一个运行在板子上的GUI或命令行工具可以实时调整3A自动对焦、自动曝光、自动白平衡参数、色彩矩阵、降噪强度、锐化等级等。调优是一个迭代过程在标准光照环境下使用标定板如24色卡进行色彩和灰阶校准。针对不同场景如人脸识别需要肤色还原准确车牌识别需要增强边缘对比度微调相关参数。将调优后的参数保存为IQ文件并集成到固件中开机自动加载。注意事项ISP调优专业性较强如果对图像质量没有极端要求使用默认参数或参考公版参数通常也能获得不错的效果。盲目调整可能使图像质量变差。7. 系统优化与电源管理对于电池供电的IoT设备功耗是生命线。RV1106在这方面提供了多种机制。7.1 CPU频率与功耗模式RV1106的Cortex-A7核心支持动态电压频率调整DVFS和多级休眠。CPU调频Linux内核的cpufreq子系统默认是启用的。你可以通过以下命令或API调整策略。# 查看可用策略 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_available_governors # 通常有 performance, powersave, ondemand, conservative, userspace # 设置为按需调频平衡性能与功耗 echo ondemand /sys/devices/system/cpu/cpu0/cpufreq/scaling_governor # 查看当前频率 cat /sys/devices/system/cpu/cpu0/cpufreq/scaling_cur_freq对于大多数视觉AI应用建议使用ondemand或conservative策略。在持续推理时CPU频率会自动升至最高以保证流畅在空闲时自动降频省电。系统休眠Linux支持suspend-to-RAM(mem) 和suspend-to-idle(freeze) 等休眠状态。可以通过echo mem /sys/power/state触发。但需要注意的是当系统休眠时大部分外设包括NPU、ISP都会掉电。如果你的应用需要低功耗下持续感知如PIR触发唤醒可能需要利用内置MCU来实现。7.2 使用内置MCU实现低功耗待机这是RV1106的杀手级特性。一个典型的设计是主A7 Linux系统完成初始化、加载模型后进入深度休眠甚至完全断电。内置MCU保持运行以极低的功耗毫瓦级别监控一个GPIO如连接PIR传感器或定时器。当MCU检测到唤醒事件如有人移动它可以通过一个GPIO中断或直接控制电源管理ICPMIC来唤醒A7核心和整个Linux系统。A7系统快速启动可以从休眠中恢复或冷启动调用NPU进行AI识别完成任务后再次进入休眠。这种“MCU哨兵 A7/NPU突击队”的模式可以轻松将设备的待机功耗从几百毫瓦降到几毫瓦极大延长电池寿命。实现它需要仔细设计硬件电源树和相应的MCU/Linux协同驱动。8. 常见问题与排查实录在实际开发中你肯定会遇到各种问题。这里记录几个我踩过的典型深坑。8.1 系统启动失败现象上电后串口无任何输出。排查电源首先用万用表测量核心电压如VDD_LOGIC, VDD_CPU和DDR电压是否正常、稳定。电源不稳是首要嫌疑。时钟检查24MHz主晶振是否起振。可以用示波器测量。Boot介质确认EMMC或SPI NAND的焊接是否良好数据线是否有短路或断路。检查原理图中Boot引脚如BOOT_SEL的上拉/下拉电阻配置是否正确这决定了芯片从哪个介质启动。串口确认串口线连接正确TX/RX是否交叉波特率是否设置为1500000瑞芯微U-Boot早期打印常用这个波特率。8.2 内核启动卡住现象串口有输出但卡在某个地方例如“Starting kernel ...”或者卡在文件系统挂载。排查内核日志仔细查看卡住前最后几行打印的信息通常会有错误提示。设备树最常见的原因是设备树DTB不匹配或错误。确认你编译和烧录的DTB文件是否对应你的板型内存型号、外设接口。可以在U-Boot阶段使用fdt print命令查看当前加载的设备树信息。文件系统如果是挂载根文件系统失败检查root内核参数指向的分区是否正确文件系统镜像是否损坏。可以尝试在U-Boot下使用ext4ls mmc 0:1之类的命令查看EMMC分区内容。驱动冲突某个外设驱动初始化失败导致内核恐慌。可以尝试在内核命令行添加loglevel8或ignore_loglevel来打印更详细的内核信息或者逐个禁用可疑的外设驱动通过修改DTS的status “disabled”。8.3 NPU推理结果异常现象模型能运行但识别结果完全不对或者精度远低于PC端模拟。排查输入数据这是最高频的问题。用printf或写文件的方式把实际传给rknn_inputs_set的原始数据 dump 出来与PC端预处理后的数据进行逐字节比对。确保尺寸、颜色通道顺序RGB/BGR、数值范围归一化到0-1还是0-255完全一致。量化误差INT8量化必然会引入精度损失。对于某些敏感的任务如关键点检测可以尝试使用INT16量化或者使用更复杂的量化校准方法如使用有代表性的校准数据集。模型转换配置检查RKNN转换时设置的mean_values和std_values是否与训练时一致。channel_mean_value这个参数很容易配错。RKNN API版本确保PC端转换模型使用的RKNN-Toolkit2版本与板端运行时库librknnrt.so的版本兼容。不匹配的版本可能导致未知行为。8.4 摄像头无图像或花屏现象v4l2-ctl --list-devices能看到设备但gst-launch预览黑屏、绿屏或花屏。排查电源和时钟确认给摄像头模组的供电DOVDD, AVDD, DVDD是否正常MCLK是否有输出且频率正确。I2C通信使用i2cdetect检查能否扫描到sensor的I2C地址。扫描不到检查I2C线路和上拉电阻。数据链路对于MIPI接口检查差分对CLK, CLK-, DATA, DATA-是否连接正确有没有阻抗不连续。可以用示波器粗略看下MIPI波形需要高速示波器。驱动配置检查DTS中配置的>