RV1106嵌入式AI视觉开发全流程:从环境搭建到模型部署实战

1. 项目概述:为什么是RV1106?

最近在嵌入式视觉项目里,RV1106这颗芯片的出镜率越来越高。如果你正在寻找一款能跑轻量级AI算法、支持高清编码、同时功耗和成本都控制得不错的SoC,它大概率会进入你的候选名单。我手头几个安防和物联网的项目,从门禁考勤机到智能猫眼,都陆续用上了它。和之前常用的海思或全志方案相比,RV1106在“性价比”和“开发生态”之间找到了一个不错的平衡点。

简单来说,RV1106是瑞芯微面向视觉物联网市场推出的一款芯片。它的核心是一个Cortex-A7处理器,搭配一个独立的MCU,这种“大小核”架构在低功耗场景下很实用——A7负责跑Linux系统和复杂的应用逻辑,MCU则在系统休眠时处理简单的传感器唤醒和事件监听。最吸引人的是它集成了0.5TOPS算力的NPU,虽然比不上那些动辄几T的大家伙,但对于人脸检测、车牌识别、行为分析这类经典CV任务,完全够用,而且功耗和成本优势明显。再加上它原生支持H.264/H.265的5M@30fps编码,以及瑞芯微一直不错的ISP(图像信号处理器),让它成为了智能摄像头、可视门铃、执法记录仪等产品的热门选择。

这篇文章,我会结合自己从零搭建RV1106开发环境的实际经历,把SDK获取、系统编译、烧录调试、驱动开发到应用部署的全流程拆解清楚。过程中踩过的坑、验证过的技巧,都会毫无保留地分享出来。无论你是刚接触瑞芯微平台的新手,还是从其他平台迁移过来的老鸟,希望这些经验能帮你少走弯路。

2. 开发环境搭建与SDK深度解析

上手RV1106,第一步就是把“武器库”准备好。这里的环境搭建不仅仅是装个编译器那么简单,涉及到官方SDK的获取、编译工具链的配置、以及整个源码目录结构的理解。弄明白了这些,后面的开发才能事半功倍。

2.1 官方资源获取与初识SDK

瑞芯微的开发者资源主要在其官方的Wiki平台和Git仓库。对于RV1106,你需要关注的是RKNPURKISP以及RV1106 Linux SDK这几个部分。

1. SDK获取途径:通常,你需要联系瑞芯微的销售或技术支持,签署相关协议后,才能获得完整的、带BSP(板级支持包)的Linux SDK。这个SDK包体积不小,可能有好几十个G,里面包含了U-Boot、Kernel、Buildroot/Yocto根文件系统、预编译的工具链、以及各种中间件和示例代码。对于个人学习或评估,也可以先从其GitHub上的开源仓库入手,例如rockchip-linux仓库里有一些核心的驱动和配置,但完整的、能直接编译出可烧录镜像的SDK,还是需要官方提供。

2. SDK目录结构扫盲:拿到SDK后,别急着编译,先花半小时浏览一下目录结构。一个典型的RV1106 SDK目录可能长这样:

sdk/ ├── app/ # 上层应用示例,如摄像头预览、编码测试 ├── buildroot/ # Buildroot构建系统,用于制作根文件系统 ├── device/rockchip/rv1106/ # 设备树文件,板级硬件配置的核心 ├── docs/ # 开发文档,非常重要但常被忽略 ├── external/ # 第三方库,如rkmedia, mpp ├── kernel/ # Linux内核源码 ├── prebuilts/ # 预编译的工具链、库文件 ├── rkbin/ # Rockchip二进制工具和固件(如DDR初始化、Miniloader) ├── tools/ # 各种开发工具(如烧录工具rkdeveloptool) └── u-boot/ # Bootloader源码

重点要关注device/下的板级配置和docs/下的文档。docs/里通常有《编译指南》、《烧录指南》和《硬件设计指南》,是避坑的第一手资料。

2.2 编译工具链与依赖安装

RV1106的A7核心是armv7-a架构,你需要对应的交叉编译工具链。SDK的prebuilts/gcc/目录下通常已经提供了。如果没有,可以安装Linaro或Arm官方的arm-linux-gnueabihf-工具链。

在Ubuntu 20.04/22.04 LTS系统上,基础的依赖安装命令如下:

sudo apt-get update sudo apt-get install -y git-core gnupg flex bison gperf build-essential \ zip curl zlib1g-dev gcc-multilib g++-multilib libc6-dev-i386 \ libncurses5-dev lib32ncurses5-dev x11proto-core-dev libx11-dev \ lib32z1-dev libgl1-mesa-dev libxml2-utils xsltproc unzip \ device-tree-compiler libssl-dev bc

这里有个关键点:务必使用64位的主机系统。因为编译过程中,尤其是构建Buildroot根文件系统时,有些步骤需要处理大量的32位和64位库的兼容性问题,在纯32位系统或某些旧版本系统上会非常棘手。

实操心得:Python版本管理瑞芯微的很多编译脚本是用Python 2.7或Python 3写的。现在Ubuntu 22.04默认是Python 3,但有些旧脚本可能仍需要Python 2。建议使用update-alternatives来管理全局的python命令指向,或者更推荐的是,在编译时显式地指定解释器,例如在调用./build.sh时,查看其首行是否是#!/usr/bin/env python,并根据需要修改。我个人的习惯是在系统里同时安装python2和python3,并通过虚拟环境(venv)来为不同的SDK版本隔离Python环境,避免污染系统。

2.3 源码编译全流程实操

RV1106 SDK通常使用一个顶层的build.sh脚本来控制编译。但理解其背后的分步过程,对于调试至关重要。

1. 编译U-Boot:U-Boot是硬件上电后运行的第一段主要代码,负责初始化DDR、加载并验证下一阶段镜像。

cd /path/to/sdk ./build.sh uboot

这个过程会使用rkbin目录下的预编译二进制文件(如DDR初始化代码rkbin/bin/rv11/rv1106_ddr_xxx.bin)和U-Boot的源码,最终生成uboot.imgtrust.img(ATF,ARM Trusted Firmware)。编译前,务必确认device/rockchip/rv1106/下选择的板级配置文件(例如rv1106-evb.config)与你手上的开发板匹配。

2. 编译Kernel:Linux内核的配置和编译。

./build.sh kernel # 或者进入kernel目录进行手动配置 cd kernel make ARCH=arm rv1106_defconfig # 加载默认配置 make ARCH=arm menuconfig # 图形化界面调整配置(可选) make ARCH=arm rv1106-evb.img -j$(nproc) # 编译并打包成内核镜像

内核配置是性能优化的关键。对于RV1106,你需要重点关注:

  • NPU驱动CONFIG_ROCKCHIP_RKNPU,这是AI算力的基础。
  • ISP驱动CONFIG_VIDEO_ROCKCHIP_ISP,图像处理管线。
  • 视频编解码CONFIG_ROCKCHIP_MPP_VCODEC,多媒体处理平台。
  • 具体的Sensor驱动:如CONFIG_VIDEO_OVXXXX

3. 编译Rootfs:使用Buildroot构建一个轻量级的根文件系统。

./build.sh rootfs

这一步会在output/rockchip_rv1106/目录下生成rootfs.ext4镜像。Buildroot的配置(board/rockchip/rv1106/下的defconfig)决定了根文件系统里包含哪些软件包。你可以在这里添加你需要的库,如OpenCV、Python3、MQTT客户端等。

4. 打包统一固件:将前面编译出的所有镜像打包成一个方便烧录的update.img

./build.sh updateimg

这个update.img包含了Loader、Parameter、Uboot、Kernel、Rootfs等所有分区镜像,可以通过瑞芯微的升级工具(如upgrade_tool)一次性烧录。

注意:首次编译可能会非常耗时(取决于主机性能,可能长达数小时),主要是Buildroot需要从网络下载并编译大量的软件包。建议保持网络通畅,并可以使用dl目录缓存下载的包,供后续编译复用。

3. 系统烧录与硬件调试实战

镜像编译出来只是第一步,把它正确地“灌进”开发板并跑起来,才是真正考验的开始。RV1106支持多种启动和烧录模式,最常用的是Loader模式MaskRom模式

3.1 两种关键烧录模式详解

1. Loader模式(正常升级模式):这是最常用的模式。开发板正常启动进入U-Boot或系统后,通过命令让芯片进入一个等待接收固件的状态。此时,芯片内部的BootROM已经加载了第一级Loader(通常是MiniLoaderAll.bin),这个Loader会初始化USB或串口,等待主机发送固件。

  • 进入方式:在U-Boot命令行下执行rockusb 0 mmc 0命令,或者在某些系统中通过upgrade_tool工具发送切换命令。
  • 优点:无需拆机短接,方便快捷,适合日常开发和迭代。
  • 缺点:需要系统能正常启动到U-Boot或能运行切换命令的环境。如果BootLoader损坏,此模式将失效。

2. MaskRom模式(救砖模式):这是芯片的终极恢复模式。当Flash为空、或Loader严重损坏时,芯片上电后会直接运行固化在芯片内部ROM中的一小段代码。这段代码会检测特定引脚(通常是eMMC的DATA0引脚)是否被拉低,如果被拉低,则进入MaskRom模式,并通过USB等待烧录。

  • 进入方式:断开电源,用镊子短接开发板上eMMC芯片的DATA0引脚与地(GND),然后上电,保持短接约1-2秒后松开。具体短接点需要查阅开发板原理图。
  • 优点:只要芯片物理没坏,一定能进入,是“救砖”的最后手段。
  • 缺点:需要物理操作,有一定风险。

3.2 使用upgrade_tool进行烧录

瑞芯微官方提供的upgrade_tool(Linux版本)或RKDevTool(Windows版本)是标准的烧录工具。这里以Linux下的命令行工具为例,它更利于自动化脚本集成。

1. 连接与识别:让开发板进入Loader或MaskRom模式,并通过USB线连接到主机。执行lsusb命令,应该能看到一个ID为2207:350a(或其他以2207开头的)的Rockchip USB设备。

sudo upgrade_tool ld

如果连接成功,这个命令会列出当前连接的设备。

2. 烧录统一固件(推荐):这是最简单的方式,直接烧录打包好的update.img

sudo upgrade_tool uf /path/to/update.img

工具会自动解析update.img中的分区表(parameter文件),并将各个部分写入对应的Flash分区。

3. 分步烧录(用于调试):有时我们需要单独更新某个分区,比如只更新内核。

  • 首先,查看分区表:
    sudo upgrade_tool pl
    这会显示Flash中的分区布局,例如0x00002000:0x00008000 uboot
  • 然后,烧录指定分区:
    sudo upgrade_tool di -p parameter.txt # 烧录分区表(谨慎!) sudo upgrade_tool di uboot uboot.img sudo upgrade_tool di kernel kernel.img sudo upgrade_tool di rootfs rootfs.ext4

4. 擦除Flash:在更换系统或遇到奇怪问题时,可以尝试擦除整个Flash(MaskRom模式下)。

sudo upgrade_tool ef /path/to/update.img # 擦除后写入 # 或单独擦除 sudo upgrade_tool el

重要提示:烧录parameter(分区表)和uboot是高风险操作,一旦出错可能导致板子无法启动。务必在操作前确认镜像文件是正确的,并且板子有进入MaskRom模式进行恢复的能力。

3.3 串口调试与系统启动日志分析

串口是嵌入式开发的“眼睛”。RV1106开发板通常会引出一个UART调试串口(通常是UART2)。

1. 硬件连接:你需要一个USB转TTL串口模块。连接时注意:

  • 开发板TX->串口模块RX
  • 开发板RX->串口模块TX
  • 开发板GND->串口模块GND千万不要接VCC!开发板需要独立供电。

2. 软件配置:在PC上使用minicompicocomscreen等工具。常用配置为:波特率1500000(瑞芯微平台常用,尤其是BootLoader阶段),数据位8,停止位1,无校验。

sudo picocom -b 1500000 /dev/ttyUSB0

上电后,你应该能在串口终端看到类似以下的启动日志:

U-Boot 2017.09 ... DRAM: 128 MiB ... Hit any key to stop autoboot: 3

在U-Boot的倒计时阶段按任意键,可以进入U-Boot命令行,进行手动引导、设置环境变量等操作。

3. 启动问题排查:如果系统卡住,串口日志是唯一的线索。

  • 卡在“Starting kernel ...”:通常是内核镜像(kernel.img)损坏,或者设备树(dtb)与硬件不匹配。检查编译出的内核镜像大小是否合理,并确认U-Boot传递给内核的设备树地址和文件名是否正确。
  • 卡在“Kernel panic ...”:内核崩溃。最常见的原因是根文件系统挂载失败。检查root=内核启动参数是否正确指向了存放根文件系统的设备(如root=/dev/mmcblk0p5),以及rootfs.ext4镜像是否完整。
  • 无法进入Loader模式:检查USB线、驱动,尝试不同的USB口。在Linux下,可能需要sudo权限或配置udev规则。

4. 外设驱动开发与配置要点

系统跑起来后,下一步就是让板子上的各种硬件“活”起来。RV1106的硬件功能大多通过Linux内核驱动来管理,而配置的核心在于设备树(Device Tree)

4.1 设备树(DTS)配置精髓

设备树是一种描述硬件拓扑和资源的数据结构,替代了旧内核中大量的板级硬编码。对于RV1106,设备树源文件(.dts.dtsi)通常位于kernel/arch/arm/boot/dts/目录下。

1. 核心文件结构:

  • rv1106.dtsi:芯片级的通用定义,包含CPU、内存、内部外设(如GPIO控制器、时钟、Pinctrl)的节点。一般不需要修改
  • rv1106-xxx.dtsi:基于芯片的板级通用定义,比如共用某款PMIC电源管理芯片的配置。
  • rv1106-xxx-evb-v10.dts你的主战场。这是针对特定评估板(EVB)的最终设备树文件,它通过#include引用了上面的.dtsi文件,并覆盖或添加具体的硬件配置,如LED、按键、摄像头接口、屏幕接口等。

2. 关键配置示例:假设我们要启用一个连接到I2C1总线、地址为0x3c的OLED屏幕。

// 在 rv1106-evb.dts 的 &i2c1 节点中添加 &i2c1 { status = "okay"; // 启用I2C1控制器 clock-frequency = <400000>; // 设置I2C时钟频率为400kHz oled_display: oled@3c { // 定义设备节点,标签为 oled_display compatible = "solomon,ssd1306"; // 驱动匹配的关键字 reg = <0x3c>; // I2C设备地址 reset-gpios = <&gpio2 RK_PC1 GPIO_ACTIVE_LOW>; // 复位引脚,使用GPIO2_C1,低电平有效 vbat-supply = <&vcc_3v3>; // 电源引用 status = "okay"; }; };
  • compatible属性是灵魂,它告诉内核用哪个驱动来匹配这个设备。这里的值必须和驱动代码里of_device_id表里的字符串一致。
  • reg是设备在总线上的地址。
  • reset-gpios使用了GPIO的Phandle格式。&gpio2指向GPIO控制器,RK_PC1是瑞芯微定义的一个宏,表示GPIO2组的C1引脚(具体换算需要查数据手册)。
  • vbat-supply引用了系统中定义的稳压器节点,实现电源管理。

3. Pinctrl(引脚复用)配置:RV1106的引脚功能高度复用,一个物理引脚可能是GPIO、UART的TX、I2C的SDA等等。这需要通过Pinctrl子系统在设备树中配置。

&pinctrl { // 定义一组引脚配置,命名为 i2c1_xfer i2c1 { i2c1_xfer: i2c1-xfer { rockchip,pins = <2 RK_PB5 1 &pcfg_pull_none>, // SDA, 复用功能1,无上下拉 <2 RK_PB6 1 &pcfg_pull_none>; // SCL }; }; // 定义OLED复位引脚为GPIO功能,默认输出高电平 oled { oled_reset: oled-reset { rockchip,pins = <2 RK_PC1 RK_FUNC_GPIO &pcfg_output_high>; }; }; }; // 然后在I2C1节点中引用这个pinctrl配置 &i2c1 { pinctrl-names = "default"; pinctrl-0 = <&i2c1_xfer>; ... };

避坑指南:GPIO编号的混乱。在设备树、驱动代码和用户空间(/sys/class/gpio)中,GPIO的编号方式可能不同。设备树里用的是“组内序号”,而Linux系统全局的GPIO编号是计算出来的。最可靠的方法是使用内核提供的gpio_get_desc()等API,或者直接使用驱动中定义好的GPIO资源。在用户空间,可以通过cat /sys/kernel/debug/gpio来查看当前所有GPIO的状态和全局编号。

4.2 摄像头与ISP图像通路搭建

RV1106的视觉能力离不开其ISP。连接一个摄像头并让系统识别,需要驱动和设备树协同工作。

1. 硬件连接与时钟:常见的MIPI CSI摄像头需要连接正确的数据线和时钟线。在设备树中,你需要配置csi2_dphy节点和具体的sensor节点。

// 启用MIPI CSI DPHY硬件 &csi2_dphy_hw { status = "okay"; }; // 配置MIPI CSI DPHY通道 &csi2_dphy0 { status = "okay"; ports { port@0 { csi_dphy_input: endpoint { remote-endpoint = <&ov5647_out>; // 与sensor的输出端点连接 ># 安装工具 sudo apt install v4l-utils # 查看拓扑 media-ctl -p -d /dev/media0 # 设置链路(例如,将sensor连接到ISP的输入) media-ctl -l '"ov5647 2-0036":0 -> "rockchip-mipi-csi2":0[1]'

在应用层,通过标准的V4L2 API(ioctl调用)就可以打开设备(如/dev/video0),设置格式(分辨率、像素格式如NV12),并获取图像数据。

4.3 NPU驱动与AI模型部署

RV1106的0.5T NPU是其亮点。瑞芯微提供了RKNN-Toolkit模型转换工具和librknn_runtime运行时库。

1. 驱动与内核配置:确保内核配置了CONFIG_ROCKCHIP_RKNPU,并且设备树中启用了NPU节点。

&npu { status = "okay"; };

系统启动后,NPU设备通常会出现在/dev/rknpu

2. 模型转换(RKNN-Toolkit):这是一个在PC上进行的步骤。你需要将训练好的模型(如TensorFlow Lite.tflite、PyTorch.pt、ONNX.onnx或Caffe.caffemodel)转换成RKNN格式。

from rknn.api import RKNN rknn = RKNN() # 加载模型 ret = rknn.load_tflite(model='./mobilenet_v1.tflite') # 配置模型输入、输出、目标平台 ret = rknn.build(do_quantization=True, dataset='./dataset.txt', target_platform='rv1106') # 导出RKNN模型 ret = rknn.export_rknn('./mobilenet_v1.rknn') rknn.release()

量化(Quantization)是关键步骤,它能将FP32模型转换为INT8,大幅减少模型体积并提升在NPU上的推理速度,但可能会带来精度损失。dataset.txt里需要提供一批代表性的校准图片。

3. 在RV1106上运行推理:将转换好的.rknn模型文件放到板子上。使用C或Python API加载模型并推理。

// C语言示例片段 #include <rknn/rknn_runtime.h> rknn_context ctx; int ret = rknn_init(&ctx, model_data, model_size, 0, NULL); // 初始化 // 设置输入 rknn_input inputs[1]; inputs[0].index = 0; inputs[0].buf = input_image_data; inputs[0].size = input_size; inputs[0].pass_through = 0; ret = rknn_inputs_set(ctx, 1, inputs); // 运行推理 ret = rknn_run(ctx, NULL); // 获取输出 rknn_output outputs[1]; outputs[0].want_float = 1; ret = rknn_outputs_get(ctx, 1, outputs, NULL); // ... 处理输出结果 outputs[0].buf rknn_outputs_release(ctx, 1, outputs); rknn_destroy(ctx);

性能调优心得

  • 输入数据对齐:NPU对输入数据的地址和尺寸可能有对齐要求(如要求128字节对齐)。使用posix_memalign分配内存可以避免性能问题。
  • 零拷贝:如果可能,让ISP处理后的图像数据直接送入NPU,避免在CPU内存和NPU内存间来回拷贝。这需要深入了解rkmedia等中间件,或直接使用V4L2 buffer与NPU API进行对接。
  • 多模型并发:RV1106的NPU支持一定程度的多模型并发执行,但需要仔细管理内存和计算资源,官方示例中有相关演示。

5. 应用开发与系统优化

当底层驱动和硬件都调通后,就到了开发上层应用,并让整个系统跑得更快、更稳的阶段。

5.1 使用RKMedia进行多媒体应用开发

直接操作V4L2和NPU的API比较底层。瑞芯微提供的RKMedia中间件封装了这些复杂操作,提供了更友好的音视频采集、编码、解码、显示和AI推理的管道(Pipeline)API。

1. RKMedia核心概念:RKMedia将处理单元抽象为MODULE(如VI视频输入、VENC视频编码、RGA图形处理、AI推理),并通过LINK将它们连接起来形成数据流。例如,一个简单的摄像头编码流程可以是:VI -> RGA(缩放/裁剪) -> VENC -> FILE

2. 快速实现摄像头H.264编码存储:

#include <rkmedia/rkmedia_api.h> // 1. 初始化 RK_MPI_SYS_Init(); // 2. 配置视频输入(VI)通道(从/dev/video0获取数据) VI_CHN_ATTR_S vi_attr; vi_attr.pcVideoNode = "/dev/video0"; vi_attr.u32Width = 1920; vi_attr.u32Height = 1080; vi_attr.enPixFmt = IMAGE_TYPE_NV12; vi_attr.enBufType = VI_CHN_BUF_TYPE_MMAP; RK_MPI_VI_SetChnAttr(0, &vi_attr); // 使用VI通道0 RK_MPI_VI_EnableChn(0); // 3. 配置视频编码(VENC)通道(H.264编码) VENC_CHN_ATTR_S venv_attr; venv_attr.stVencAttr.enType = RK_CODEC_TYPE_H264; venv_attr.stVencAttr.u32PicWidth = 1920; venv_attr.stVencAttr.u32PicHeight = 1080; venv_attr.stVencAttr.u32Bitrate = 4000000; // 4 Mbps RK_MPI_VENC_CreateChn(0, &venv_attr); // 4. 绑定数据流:VI通道0 -> VENC通道0 MPP_CHN_S src, dst; src.enModId = RK_ID_VI; src.s32ChnId = 0; dst.enModId = RK_ID_VENC; dst.s32ChnId = 0; RK_MPI_SYS_Bind(&src, &dst); // 5. 启动编码并获取码流(例如写入文件) VENC_STREAM_S stStream; FILE *fp = fopen("output.h264", "wb"); while(running) { RK_MPI_VENC_GetStream(0, &stStream, -1); // 阻塞获取码流包 for(int i=0; i<stStream.u32PackCount; i++) { fwrite(stStream.pstPack[i].pu8Addr, 1, stStream.pstPack[i].u32Len, fp); } RK_MPI_VENC_ReleaseStream(0, &stStream); // 释放流 } // 6. 反绑定、销毁通道、去初始化...

使用RKMedia可以大大简化开发,但需要注意其版本与SDK的匹配,以及各模块属性的详细配置。

5.2 系统性能调优与稳定性保障

产品化过程中,系统必须稳定高效。

1. 内存优化:RV1106内存不大(常见128MB或256MB DDR)。优化策略包括:

  • 使用busybox精简根文件系统:在Buildroot配置中,只选择必要的软件包。
  • 静态链接 vs 动态链接:对于关键应用,静态链接可以避免动态库加载的开销和依赖问题,但会增大单个可执行文件体积。需要权衡。
  • 监控内存使用:使用freetop命令,关注SlabCache的使用情况。内核slabtop命令可以查看内核对象缓存。
  • 防止内存泄漏:长时间运行后,使用cat /proc/meminfo观察MemFreeBuffers/Cached的变化趋势。Valgrind不适合资源受限的嵌入式环境,更多的是依靠代码审查和压力测试。

2. 启动速度优化:

  • U-Boot优化:减少不必要的设备初始化,关闭启动延迟。修改include/configs/rv1106_common.h中的CONFIG_BOOTDELAY
  • 内核裁剪:使用make menuconfig移除所有不需要的驱动和功能模块。特别是文件系统、网络协议、调试功能等。
  • Initramfs:对于简单应用,可以考虑使用initramfs作为根文件系统,直接打包进内核,省去从存储设备加载根文件系统的时间。
  • 并行初始化:利用systemd或Busybox init的并行启动能力(如果支持)。

3. 电源管理:RV1106的MCU核心可以在A7休眠时维持低功耗运行。

  • CPU频率调节:使用cpufreq子系统。echo performance > /sys/devices/system/cpu/cpufreq/policy0/scaling_governor切换到性能模式,echo powersave切换到省电模式。
  • 休眠与唤醒:配置GPIO中断作为唤醒源。在设备树中为按键或传感器配置wakeup-source属性,并在驱动中实现相应的中断处理。让系统进入休眠状态可以通过echo mem > /sys/power/state实现。

5.3 常见问题排查与解决实录

开发过程中,以下问题我遇到得最多:

1. 内核启动时卡住,串口无输出。

  • 检查点1:电源。用万用表测量核心电压(如VDD_LOGIC)和DDR电压是否稳定且在正常范围内。RV1106对电源纹波比较敏感。
  • 检查点2:时钟。检查24MHz主晶振是否起振。可以用示波器探头(高阻)测量晶振引脚,看是否有正弦波。
  • 检查点3:Boot引脚。确认板子的Boot Mode引脚(如eMMC vs SPI Flash)电平设置是否正确,与你的烧录介质匹配。
  • 检查点4:DDR配置。这是最棘手的问题之一。rkbin里的DDR初始化二进制文件(rv1106_ddr_xxx.bin)必须与板上焊接的DDR颗粒型号和时序完全匹配。如果不对,轻则不稳定,重则无法启动。需要根据DDR颗粒的数据手册,核对或重新生成这个bin文件。

2. 摄像头不出图,media-ctl报错。

  • 检查点1:I2C通信。首先用i2cdetect -y 2(假设I2C总线是2)检查传感器地址(如0x36)是否能被探测到。探测不到,检查电源、复位引脚、I2C上拉电阻和接线。
  • 检查点2:时钟和MIPI信号。用示波器检查Sensor的MCLK(主时钟)是否正常。MIPI信号需要用高速示波器或MIPI协议分析仪查看,难度较大。可以尝试降低分辨率或帧率,看是否是信号完整性问题。
  • 检查点3:设备树配置。反复核对设备树中的remote-endpoint链接、>

最新新闻

日新闻

周新闻

月新闻