海思UVC调试

前言

本文记录一下这几天调试海思UVC的心得,本次使用的芯片及SDK是海思3531DV100,最终的结果是两路USB摄像头接入海思的两个USB(不同的root hub),HDMI输出四分屏,显示两个摄像头的画面

参考过的文章如下:

https://blog.csdn.net/zhenglie110/article/details/89360312
https://blog.csdn.net/zhenglie110/article/details/89360423
https://blog.csdn.net/zhenglie110/article/details/89361644
http://bbs.ebaina.com/thread-37986-1-1.html

但是上面这些文章里面也不全对,而且每个人需求都不太一样,因此下面我会重头再解释一遍

内核的修改

配置menuconfig增加驱动

make ARCH=arm CROSS_COMPILE=arm-hisiv500-linux- menuconfig

Device Drivers  --->
	[*] USB support  --->
		<*>   Support for Host-side USB
		[*]     Enable USB persist by default
		<*>     xHCI HCD (USB 3.0) support
		<*>       xHCI support for Hisilicon SoCs
		<*>     EHCI HCD (USB 2.0) support
		[*]       Improved Transaction Translator scheduling
		<*>     Generic EHCI driver for a platform device
		<*>     OHCI HCD (USB 1.1) support
		<*>       OHCI support for PCI-bus USB controllers
		<*>       Generic OHCI driver for a platform device
		<*>     USB Mass Storage support
		<*>   USB Gadget Support  --->
		
	<*> Multimedia support  --->
		[*]   Cameras/video grabbers support
		[*]   Media Controller API
		[*]   V4L2 sub-device userspace API
		[*]   Media USB Adapters  --->
			<*>   USB Video Class (UVC)
			[*]     UVC input events device support
			<*>   GSPCA based webcams  --->
		[*]   Media PCI Adapters  --->
		[*]   V4L platform devices  --->
			<M>   Marvell 88ALP01 (Cafe) CMOS Camera Controller support
			<*>   SoC camera support
			<*>   platform camera support 
		[*]   Autoselect ancillary drivers (tuners, sensors, i2c, frontends)

我目前的配置就上面这些,而且是将驱动编译进了内核,网上有人把 Device Drivers -> PHY Subsystem —> Hisilicon Inno USB2 PHY support 打开了,经过我的测试打开这个选项将会导致USB2.0的接口无法识别设备,具体原因不清楚

驱动的修改

将USB摄像头插入板子上,观察打印信息

usb 1-1: USB disconnect, device number 15
usb 1-1: new high-speed USB device number 16 using xhci-hcd
uvcvideo: quirks = 512
uvcvideo: Found UVC 1.00 device USB Camera (0bda:3035)
input: USB Camera as /devices/soc/11000000.xhci/usb1/1-1/1-1:1.0/input/input15

上面已经报告了VID 和 PID,因此不需要在windows里面费那么大劲去找VID和PID

修改文件 linux-3.18.y\drivers\media\usb\uvc\uvc_driver.c

struct usb_device_id uvc_ids[]的末尾模仿之前的加上自己的USB设备信息,如果不加的话,设备插入时调用probe将会按默认的id_table来加载驱动,也就是这个uvc_ids末尾说的Generic USB Video Class

/*  my test USB Camera */
{
    
    .match_flags	= USB_DEVICE_ID_MATCH_DEVICE| USB_DEVICE_ID_MATCH_INT_INFO,
    .idVendor		= 0x0bda,
    .idProduct		= 0x3035,
    .bInterfaceClass	= USB_CLASS_VIDEO,
    .bInterfaceSubClass	= 1,
    .bInterfaceProtocol	= 0,
    .driver_info		= UVC_QUIRK_RESTRICT_FRAME_RATE},
/* Generic USB Video Class */
{
    USB_INTERFACE_INFO(USB_CLASS_VIDEO, 1, 0) },

注意一下这个driver_info的赋值,可以用来限制帧率,UVC_QUIRK_RESTRICT_FRAME_RATE的值是512,这个设置好像是跟带宽有关系,没有深入了解,如果设的过小,将导致无法出图。而且USB2.0的带宽上限也只有480Mbit/s,连一个摄像头都够呛了。

sample_uvc

直接上sample代码了,原本SDK是没有uvc例子的,这个是我自己实现的,代码上传到附件,包括以下几个文件:

  • sample_comm.h
  • sample_comm_sys.c
  • sample_comm_vdec.c
  • sample_comm_vo.c
  • sample_comm_vpss.c
  • sample_uvc.c

下载地址:https://download.csdn.net/download/whitefish520/13216318

有一处错误,上传后才发现:tv_fmt.fmt.pix.height = uvcParam.u32inputHeight;

以下只粘贴了sample_uvc.c在这里,因为其它的内容基本上都是SDK里面原本就提供的,基本上没有改动,sample_uvc.c是这几天以来的心血,从0开始写的,关于程序中一些设置的解释,放在下一个章节,如果程序看的不太懂,先看后文的解读。

/******************************************************************************
  A simple program of Hisilicon Hi35xx video input and output implementation.
  Copyright (C), 2014-2015, Hisilicon Tech. Co., Ltd.
 ******************************************************************************
    Modification:  2015-1 Created
******************************************************************************/

#ifdef __cplusplus
#if __cplusplus
extern "C"{
   
#endif
#endif /* End of #ifdef __cplusplus */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <signal.h>
#include <fcntl.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/ioctl.h>
#include <sys/mman.h>
#include <sys/prctl.h>
#include <sys/ioctl.h>
#include <linux/videodev2.h>

#include "sample_comm.h"
#include "hi_comm_vb.h"
#include "mpi_vb.h"

// usb video camera number
#define     UVC_NUM     2
// save stream as file, do not store at flash
#define     SAVE_FILE   0
// video memory
typedef struct{
   
    void *start;
	int length;
}uvc_buf_t;

struct hiUvcParam
{
   
    HI_S32 fd[UVC_NUM];
	HI_CHAR cFileName[UVC_NUM][128];
    HI_CHAR cNodeName[UVC_NUM][128];
    HI_U32 u32inputWidth;
    HI_U32 u32inputHeight;
    HI_U32 u32Width;
    HI_U32 u32Height;
    HI_U32 pixelformat;
    HI_U32 V4L2_buffer_num;
    HI_U32 buffer_num[UVC_NUM];
    uvc_buf_t *uvc_buf[UVC_NUM];
    HI_U32 u32BlkSize;
    HI_U32 u32BlkCnt;
	VB_POOL VbPool;
    VB_BLK VbBlk;
    HI_U32 u32phyAddr;
    HI_U8 *pVirAddr;
    VDEC_CHN VdChn[UVC_NUM];
    VPSS_GRP VpssGrp[UVC_NUM];
    VPSS_CHN VpssChn;
    VO_DEV VoDev;
    VO_CHN VoChn[UVC_NUM];
    VO_LAYER VoLayer;
    SAMPLE_VO_MODE_E enMode;
    HI_BOOL pthRun;
    pthread_t ptuvc;
}uvcParam;

/******************************************************************************
* function : YUV422P(YUYV) 转 YUV422SP(NV16)
* 		YUYVYUYV  ->  YYYYUVUV          
******************************************************************************/
HI_VOID yuv422p_to_yuv422sp(HI_U8* yuv, HI_S32 width, HI_S32 height)
{
   
    HI_S32 i, j, k;
    HI_U8 yuv422p[width*height*2];
    memcpy(yuv422p, yuv, width*height*2);
    HI_U8* y = yuv;
    HI_U8* uv = &yuv[width*height];

    for(i=0, j=0, k=0; i<width*height*2; i+=4, j+=2, k+=2)
    {
   
        y[j] = yuv422p[i];
        y[j+1] = yuv422p[i+2];
        uv[k] = yuv422p[i+3];
        uv[k+1] = yuv422p[i+1];
    }
}

/******************************************************************************
* function : usb video camera parameter set
******************************************************************************/
HI_S32 HI_UVC_Param_Set(HI_VOID)
{
   
    HI_S32 i, j=0;
    for(i=0; i<UVC_NUM; i++)
    {
   
        while(j < 64)
        {
   
            sprintf(uvcParam.cNodeName[i], "/dev/video%d", j++);
            if(0 == access(uvcParam.cNodeName[i], F_OK))
                break;
        }
       
        sprintf(uvcParam.cFileName[i], "/app/uvc/uvcVideo%d.yuv", i);
        uvcParam.fd[i] = -1;
        uvcParam.buffer_num[i] = 0;
        uvcParam.uvc_buf[i] = NULL;
        uvcParam.pVirAddr = NULL;
        uvcParam.VdChn[i] = i;
        uvcParam.VpssGrp[i] = i;
        uvcParam.VpssChn = i;
    }
    uvcParam.u32inputWidth = HD_WIDTH;
    uvcParam.u32inputHeight = HD_HEIGHT;
    uvcParam.u32Width = HD_WIDTH;
    uvcParam.u32Height = HD_HEIGHT;
    //uvcParam.pixelformat = V4L2_PIX_FMT_YUYV;
    uvcParam.pixelformat = V4L2_PIX_FMT_MJPEG;
    uvcParam.V4L2_buffer_num = 10;
    uvcParam.u32BlkSize = uvcParam.u32Width * uvcParam.u32Height * 2;
    uvcParam.u32BlkCnt = 15;
    uvcParam.VpssChn = 0;
    uvcParam.enMode = VO_MODE_4MUX;
    uvcParam.pthRun = HI_TRUE;
    if(j >= 64)
        return HI_FAILURE;
    else
        return HI_SUCCESS;
}

/******************************************************************************
* function : open usb video camera device
******************************************************************************/
HI_S32 HI_UVC_Open(HI_VOID)
{
   
	struct v4l2_input inp;
 	HI_S32 i, j;
    for(i=0; i<UVC_NUM; i++)
    {
   
        uvcParam.fd[i] = open(uvcParam.cNodeName[i], O_RDWR, 0);
        if(uvcParam.fd[i] < 0)
        {
   	
            SAMPLE_PRT("camera[%d] : %s open failed ! \n", i, uvcParam.cNodeName[i]);
            return HI_FAILURE;
        }

        for(j=0;j<16;j++)
        {
   
            inp.index = j;
            if (-1 == ioctl (uvcParam.fd[i], VIDIOC_S_INPUT, &inp))
            {
   
                SAMPLE_PRT("camera[%d] : VIDIOC_S_INPUT failed %d !\n", i, j);
            }
            else
            {
   
                printf("camera[%d] : VIDIOC_S_INPUT success %d !\n", i, j);
                break;
            }
        }
    }
	return HI_SUCCESS;
}

/******************************************************************************
* function : close usb video camera device
******************************************************************************/
HI_S32 HI_UVC_Close(HI_VOID)
{
   
    HI_S32 i;
    for(i=0; i<UVC_NUM; i++)
    {
   
        if(uvcParam.fd[i] > 0)
            close(uvcParam.fd[i]);
    }
	return HI_SUCCESS;
}

/******************************************************************************
* function : usb video camera init
******************************************************************************/
HI_S32 HI_UVC_Init(HI_VOID)
{
   
    HI_S32 i;
	struct v4l2_capability 	cap;	    /* decive fuction, such as video input */
	struct v4l2_fmtdesc 	fmtdesc;  	/* detail control value */
	struct v4l2_format 		fmt; 

	HI_S32 ret = HI_FAILURE;
	
	/* get width and height*/
	fmt.type = V4L2_BUF_TYPE_VIDEO_CAPTURE; 

    for(i=0; i<UVC_NUM; i++)
    {
   
        if(ret = ioctl(uvcParam.fd[i], VIDIOC_G_FMT, &fmt)<0)
        {
   
            SAMPLE_PRT("camera[%d] : fail to ioctl VIDIOC_G_FMT\n", i);
            return HI_FAILURE;
        }
        printf
  • 7
    点赞
  • 28
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
华为海思sensor调试是指对华为海思公司的传感器进行调试工作。传感器是一种能够感知和检测环境中各种物理量和信号的装置,它可以将感知到的信息转化为可识别和可利用的信号,为后续的数据处理和分析提供基础。 在进行华为海思sensor调试时,首先需要对传感器进行连接和配置。连接是指将传感器与调试工具或设备连接起来,以确保传感器能够与外部系统进行数据传输。配置则是指根据实际需求对传感器的参数进行设置,如采样率、灵敏度等,以使传感器能够按照预期工作。 接下来,进行传感器的校准工作。校准是通过对传感器进行精确的调整和校对,以消除误差和偏差,提高测量的准确性和精度。校准过程中需要使用标准参考信号或物理量进行比对和调整,以使传感器输出的测量值与实际值尽可能接近。 调试过程中还需要进行传感器的功能测试。功能测试是指对传感器的各项功能进行验证,如是否能够正常感知和检测目标物体或环境、是否能够正确输出测量值等。可以通过模拟测试场景或实际应用场景对传感器的功能进行测试,以确认其是否符合设计要求。 最后,对传感器进行性能评估。性能评估是通过对传感器进行多个指标的测试和分析,评估其在实际使用中的性能表现,如响应时间、信噪比、动态范围等。根据评估结果可以判断传感器是否能够满足实际应用需求,以及是否需要进一步优化和改进。 综上所述,华为海思sensor调试是一个对传感器进行连接、配置、校准、功能测试和性能评估的过程,旨在确保传感器能够准确、可靠地感知环境并输出准确的测量值,以满足实际应用的需求。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值