RK3288 uvc摄像头调试

本文介绍了解决RK平台UVC摄像头热插拔问题的过程,从内核配置到摄像头驱动框架验证,遇到的挑战及最终解决方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >


曾经在全志平台上调试过UVC摄像头,当时调试过程比较流畅,丝毫没有碰上异常情况,这一次在RK上碰到较大的困难,下面介绍一下我的调试过程。


首先,不用说当然在内核配置中配置上UVC摄像头,重新编译内核,烧录。

  1. Device Drivers --->
    <*> Multimedia support --->
    	<*> Video For Linux
    	   [*] Enable Video For Linux API 1 (DEPRECATED)
    		[*] Video capture adapters --->
    			[*] V4L USB devices --->
    			    <*> USB Video Class (UVC)
    				[*] UVC input events device support


然后查看内核信息,cat /proc/kmsg    然后接上摄像头,会看到类似的设备信息,说明我们的摄像头已经可以正常使用了。

usb 1-1.1: new full speed USB device using address 3
usb 1-1.1: New USB device found, idVendor=0ac8, idProduct=3450
usb 1-1.1: New USB device strings: Mfr=1, Product=2, SerialNumber=0
usb 1-1.1: Product: Deasy USB2.0 Camera
uvcvideo: Found UVC 1.00 device Deasy USB2.0 Camera (0ac8:3450)


接着我们可以在/dev 目录下看到 videoX 的节点。

然后,尝试一下用系统相机看看是否能点亮摄像头,这里提示我无法连接上摄像头。

E/SensorService(  471): Error activating sensor 0 (Operation not permitted)
V/CAM_PhotoModule( 1041): On resume.
V/CAM_PhotoModule( 1041): Executing onResumeTasks.
V/CAM_PhotoModule( 1041): Open camera device.
V/CameraHolder( 1041): open camera 0
E/CameraService(  163): CameraService::connect X (pid 1041) rejected (invalid cameraId 0).


这里只能看出来CameraService 连接相机0失败,invalid cameraId 0 除此之外,不太明白为什么会有这样的信息。
抛开系统相机我们先自己写一个小应用来测试一下video是否正常工作。
linux下的摄像头驱动框架是V4L2,只要根据相关的API来写测试程序,然后封装成JNI函数,交给Android层调用即可。
这里我比较懒用了一下一个开源项目的相机demo来验证我的相机在当前环境下是工作正常的。

SimpleWebCam

https://bitbucket.org/neuralassembly/simplewebcam/src
附件也会提供这个项目稍微修改过的工程,因为涉及到Jni代码的编译,直接提供的工程就省去很多麻烦。
这里存在一个权限的问题,只是测试用,chmod 777 /dev/video* 防止因为权限打不开相机.

这里用的640x480 resolution with YUYV format 的可能有些摄像头不支持,就需要研究一下改一下JNI代码了,
然后确认了LINUX驱动层不存在问题,我们就开始考虑一下故障的地方在哪里了。

首先进入
frameworks/av/services/camera/libcameraservice/CameraService.cpp 查看异常的日志是哪里打印出来,很快就发现

 if (cameraId < 0 || cameraId >= mNumberOfCameras) {
        ALOGE("CameraService::connect X (pid %d) rejected (invalid cameraId %d).",
          callingPid, cameraId);
        return -ENODEV;
    }


然后 我们知道cameraId==0, 那么 Cameras的数量是0

为了验证相机的数量,我们在上一次启动相机的时候打印确认一下是不是真的是0

然后打印调试信息,发现确实是获取Camera的数量是0,这里相机的数量是直接调用HAL层相机的层层封装函数得到的。
那么很有可能uvc热插拔信息并没有在HAL层更新出来,从而导致并不知道存在这一个相机。
这个推理是通过我反复重启发现有事确实可以打开相机,但是死机了。
packages/apps/LegacyCamera/src/com/android/camera/CameraHolder.java
这个是相机程序的代码,可以看出是直接获取相机数量 。
android.hardware.Camera.getNumberOfCameras();

 private CameraHolder() {
        HandlerThread ht = new HandlerThread("CameraHolder");
        ht.start();
        mHandler = new MyHandler(ht.getLooper());
        mNumberOfCameras = android.hardware.Camera.getNumberOfCameras();
        mInfo = new CameraInfo[mNumberOfCameras];
        for (int i = 0; i < mNumberOfCameras; i++) {
            mInfo[i] = new CameraInfo();
            android.hardware.Camera.getCameraInfo(i, mInfo[i]);
            if (mBackCameraId == -1 && mInfo[i].facing == CameraInfo.CAMERA_FACING_BACK) {
                mBackCameraId = i;
            }
            if (mFrontCameraId == -1 && mInfo[i].facing == CameraInfo.CAMERA_FACING_FRONT) {
                mFrontCameraId = i;
            }
        }
    }



这里稍微增加cameraopne的时候去读相机的信息。
1.死机后的信息
D/CameraHolder( 1043): CameraHoler().go
D/CameraHolder( 1043): mMockCameraInfo ==null, getNumberOfCameras()
D/CameraHolder( 1043): return number === 1
2.提示打不开的信息
D/CameraHolder( 1043): CameraHoler().go
D/CameraHolder( 1043): mMockCameraInfo ==null, getNumberOfCameras()
D/CameraHolder( 1043): return number === 0



说明了一切问题的根源在于相机打开的过程中获取相机数量是不正确,这里又查看了CameraHal代码被加载的流程分析,发现
uvc摄像头是在CameraHal代码被加载后才发现的,非常关键的信息是存储在HAL层的一个数组中的。

那么,我们肯定了HAL层不支持热插拔,那么如何要支持热插拔呢,我们需要分析一下cameraService中的流程。
frameworks/av/services/camera/libcameraservice/CameraService.cpp
  1. void CameraService::onFirstRef()  
  2. {  
  3.     BnCameraService::onFirstRef();  
  4.   
  5.     if (hw_get_module(CAMERA_HARDWARE_MODULE_ID,//这个定义为"came"  
  6.                 (const hw_module_t **)&mModule) < 0) {
  7.         ALOGE("Could not load camera HAL module");  
  8.         mNumberOfCameras = 0;  
  9.     }  
  10.     else {  
  11.         mNumberOfCameras = mModule->get_number_of_cameras();  
  12.         if (mNumberOfCameras > MAX_CAMERAS) {  
  13.             ALOGE("Number of cameras(%d) > MAX_CAMERAS(%d).",  
  14.                     mNumberOfCameras, MAX_CAMERAS);  
  15.             mNumberOfCameras = MAX_CAMERAS;  
  16.         }  
  17.         for (int i = 0; i < mNumberOfCameras; i++) {  
  18.             setCameraFree(i);  
  19.         }  
  20.     }  
  21. }  
这个函数非常关键,我们发现这里加载的HAL的初始化代码,我们也通过上面的日志得出hal实际上能获取数量的,只是当时确实是没有相机。所以,我们修改了getNumberOfCameras函数,每次发现没有摄像头说明,就应该重新初始化一次这样就解决了热插拔的问题。 那么问题来了,当我有两个随意的摄像头时,随意热插拔还是有问题,那么改成<2 吧,最大只支持两个相机。
int32_t CameraService::getNumberOfCameras() {
    if(mNumberOfCameras == 0) {
       ALOGE("no camera found before! check again...");
       onFirstRef();
    }
    return mNumberOfCameras;
}




















<think>嗯,用户现在在问关于RK平台5648摄像头调试的方法或教程。首先,我需要看看用户提到的引用内容,看看有没有相关的信息可以提取。用户引用了四篇调试不同摄像头模组的文章,包括BT656协议、DVP摄像头UVC设备以及YUV格式播放的问题。这些可能和5648摄像头调试有关联,但需要具体分析。 首先,5648摄像头可能指的是某种分辨率的摄像头,比如5648x...?或者是型号中的一部分?需要确认一下。不过通常摄像头型号如OV5648之类的,可能是指OmniVision的某个型号,比如OV5640之类的。假设这里5648是一个型号,比如OV5648,那么可能需要配置相应的驱动和接口。 接下来,用户提到的RK平台,比如RK3588、RK3288,都是Rockchip的处理器,所以调试方法可能有共通之处。引用[1]中提到了BT656接口的调试,引用[2]是DVP接口的YUYV格式摄像头调试,引用[3]是关于YUV数据的播放,引用[4]是UVC设备无法打开的问题。这些可能涉及不同的接口协议,比如DVP、MIPI CSI、BT656等,所以需要先确定5648摄像头使用的接口类型。 用户的问题可能涉及到硬件连接、驱动配置、图像格式设置、时钟同步、数据校验等步骤。根据引用内容,调试过程中可能遇到无法打开设备、图像异常、时钟同步问题等,需要逐步排查。 首先,硬件接口确认,比如DVP或MIPI CSI,引脚连接是否正确,电压是否稳定。然后,检查设备树中的配置,比如引用[1]中提到的bt656配置,可能需要在设备树中设置相关节点,包括时钟频率、数据格式、分辨率等。如果5648使用MIPI接口,可能需要配置CSI节点,而DVP接口则需要配置DVP相关设置。 然后是驱动部分,内核中是否有对应的摄像头驱动,比如ov5648的驱动是否已启用。引用[2]提到驱动层的问题,如果驱动不存在或配置错误,会导致无法识别摄像头。可能需要在内核配置中启用相关驱动模块,或者添加设备树节点。 接下来是图像格式,比如YUYV、NV12等,需要与传感器输出格式一致。引用[3]中用ffplay播放YUV数据,如果图像格式不匹配,会导致花屏或颜色异常。需要确认sensor的输出格式,并在驱动或应用层进行相应的配置。 调试工具方面,可能需要使用v4l2-utils工具集,如v4l2-ctl来列出设备、设置格式,以及使用yavta捕获图像数据,再用ffplay查看。引用[3]中的命令可以用来播放原始YUV数据,帮助验证数据是否正确。 此外,时钟和电源管理也很重要,比如pwdn和reset引脚的控制,确保sensor正确上电和初始化。引用[1]中提到bt656的时钟配置,可能涉及到HSYNC、VSYNC等信号的同步问题,如果时序不对,会导致图像错乱。 常见问题方面,比如引用[4]中的uvc设备无法打开,可能是权限问题或驱动冲突。需要检查/dev/videoX节点的权限,或者是否有其他驱动占用了设备。如果是权限问题,可以通过chmod或udev规则解决。 最后,用户可能需要具体的步骤,比如设备树配置示例、驱动加载、工具使用命令等,以及如何验证各阶段是否正确。需要将这些步骤分点说明,确保用户能逐步调试,并解决可能遇到的问题。</think>### RK平台5648摄像头调试方法指南 #### 一、硬件接口确认 1. 确认摄像头接口类型为DVP/MIPI-CSI,检查硬件连接是否包含以下信号: - DVP接口:PCLK、HSYNC、VSYNC、D0-D9数据线 - MIPI-CSI接口:CLK+/CLK-、DATA+/DATA-差分对 - 需测量PWDN/RESET引脚电压是否正常(通常1.8V/3.3V)[^1] 2. 设备树配置示例: ```dts &csi_dphy { status = "okay"; ports { port@0 { csi_dphy_input: endpoint { remote-endpoint = <&ov5648_out>; data-lanes = <1 2>; // MIPI通道配置 }; }; }; }; &i2c1 { ov5648: camera@36 { compatible = "ovti,ov5648"; reg = <0x36>; pinctrl-names = "default"; pinctrl-0 = <&camera_pwr>; clocks = <&cru CLK_CIF_OUT>; clock-names = "xvclk"; powerdown-gpios = <&gpio1 12 GPIO_ACTIVE_LOW>; reset-gpios = <&gpio1 13 GPIO_ACTIVE_LOW>; port { ov5648_out: endpoint { remote-endpoint = <&csi_dphy_input>; data-lanes = <1 2>; clock-lanes = <0>; }; }; }; }; ``` #### 二、驱动调试步骤 1. 检查内核驱动支持: ```bash make menuconfig # 确认启用CONFIG_VIDEO_OV5648驱动 dmesg | grep -i "camera" # 查看内核识别日志 ``` 2. 图像格式配置验证: ```bash v4l2-ctl --list-formats-ext # 查看支持的像素格式 v4l2-ctl --set-fmt-video=width=2592,height=1944,pixelformat=NV12 ``` 3. 数据捕获测试: ```bash yavta /dev/video0 --capture=10 -s 2592x1944 -f NV12 > /tmp/test.yuv ffplay -video_size 2592x1944 -pixel_format nv12 -f rawvideo /tmp/test.yuv ``` #### 三、常见问题排查 1. **图像花屏问题**: - 检查PCLK时钟频率是否匹配$f_{pclk} = \frac{(width + hblank) \times (height + vblank) \times fps}{10^6}$ MHz - 验证数据线是否接触不良(示波器测量D0-D9信号完整性) 2. **设备无法识别**: ```bash i2cdetect -y 1 # 检测I2C地址是否响应 ``` 正常应显示类似: ``` 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- -- -- -- -- -- -- -- -- -- 36 -- -- -- ``` 3. **DMA传输错误**: 在内核日志中若出现`dwc2 ff300000.usb: DMA error`,需调整CMA内存分配: ```dts / { reserved-memory { linux,cma { size = <0x2000000>; // 至少32MB }; }; }; ``` #### 四、进阶调试工具 1. 使用`media-ctl`进行拓扑分析: ```bash media-ctl -p -d /dev/media0 ``` 2. 时钟域同步验证: ```bash cat /sys/kernel/debug/clk/clk_summary | grep -E 'cif|vip' ``` 3. 使用逻辑分析仪抓取信号波形,验证HSYNC/VSYNC时序是否符合: $$ t_{h} = \frac{1}{f_{pclk}} \times (width + hblank) $$ $$ t_{v} = t_{h} \times (height + vblank) $$
评论 11
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值