• 4.图像sensor的特性和驱动解析


    修改 摄像头SDK中支持的sensor需要做的事

    例如:ar0130 --> ov9712

    1.修改加载load3518e脚本的参数 vi /etc/profile

    ./load3518e -i -sensor ar0130 -osmem 32 -total 64
    修改参数为

    /load3518e -i -sensor ov9712 -osmem 32 -total 64 

    2.应用程序修改配置

    1)使用提供的已配置好的程序进行测试

    执行sample_9712

    rtsp://192.168.1.10:554/test.264

    测试无误

    2)修改mpp/sample/makefile.param重新编译之前的程序

    SENSOR_TYPE ?= OMNIVISION_OV9712_DC_720P_30FPS

    #SENSOR_TYPE ?= APTINA_AR0130_DC_720P_30FPS 

    make clean

    cd venc_ortp

    make

    cp sample_venc_ortp ~/nfs_hi/ov9712_ortp 

    ./ov9712_ortp 0 

    VLC播放器打开文件demo.sdp

    4.1.本季课程主要内容和安排

    4.1.1、本课程主要内容
    (1)查看SDK中相应文档,重点是SoC对Sensor的支持

    load3518e脚本中的重点内容

    #!/bin/sh
    # Useage: ./load3518e [ -r|-i|-a ] [ sensor ]
    #         -r : rmmod all modules
    #         -i : insmod all modules
    #    default : rmmod all moules and then insmod them
    #
    
    
    # imx222 9m034 ov9752 ar0230 ar0130 ov9712 mn34222
    
    
    
    ####################Variables Definition##########################
    
    
    SNS_TYPE=ar0230             # sensor type
    
    mem_total=64;               # 64M, total mem
    mem_start=0x80000000;       # phy mem start
    
    os_mem_size=32;             # 32M, os mem
    mmz_start=0x82000000;       # mmz start addr
    mmz_size=32M;               # 32M, mmz size
    
    
    ##################################################################




    insert_sns()
    {
    case $SNS_TYPE in
    ar0130|9m034)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    #cmos pinmux
    himm 0x200f007c 0x1; # VI_DATA13
    himm 0x200f0080 0x1; # VI_DATA10
    himm 0x200f0084 0x1; # VI_DATA12
    himm 0x200f0088 0x1; # VI_DATA11
    himm 0x200f008c 0x2; # VI_VS
    himm 0x200f0090 0x2; # VI_HS
    himm 0x200f0094 0x1; # VI_DATA9

    himm 0x2003002c 0xc4001; # sensor unreset, clk 27MHz, VI 99MHz
    ;;
    ar0230)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    himm 0x2003002c 0xb4005; # sensor unreset, clk 27MHz, VI 148.5MHz
    himm 0x20030104 0x1; # vpss 148.5MHz
    ;;
    imx222)
    himm 0x200f0040 0x1 # SPI0_SCLK
    himm 0x200f0044 0x1 # SPI0_SDO
    himm 0x200f0048 0x1 # SPI0_SDI
    himm 0x200f004c 0x1 # SPI0_CSN

    #cmos pinmux
    himm 0x200f007c 0x1; # VI_DATA13
    himm 0x200f0080 0x1; # VI_DATA10
    himm 0x200f0084 0x1; # VI_DATA12
    himm 0x200f0088 0x1; # VI_DATA11
    himm 0x200f008c 0x2; # VI_VS
    himm 0x200f0090 0x2; # VI_HS
    himm 0x200f0094 0x1; # VI_DATA9

    himm 0x2003002c 0x94001; # sensor unreset, clk 37.125MHz, VI 99MHz

    insmod extdrv/sensor_spi.ko;
    ;;
    ov9712)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    #cmos pinmux
    himm 0x200f007c 0x1; # VI_DATA13
    himm 0x200f0080 0x1; # VI_DATA10
    himm 0x200f0084 0x1; # VI_DATA12
    himm 0x200f0088 0x1; # VI_DATA11
    himm 0x200f008c 0x2; # VI_VS
    himm 0x200f0090 0x2; # VI_HS
    himm 0x200f0094 0x1; # VI_DATA9

    himm 0x2003002c 0xb4001; # sensor unreset, clk 24MHz, VI 99MHz
    ;;
    ov9732)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    #cmos pinmux
    himm 0x200f007c 0x1; # VI_DATA13
    himm 0x200f0080 0x1; # VI_DATA10
    himm 0x200f0084 0x1; # VI_DATA12
    himm 0x200f0088 0x1; # VI_DATA11
    himm 0x200f008c 0x2; # VI_VS
    himm 0x200f0090 0x2; # VI_HS
    himm 0x200f0094 0x1; # VI_DATA9

    himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
    ;;

    ov9752)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
    ;;
    ov9750)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
    ;;

    ov2718)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    himm 0x2003002c 0xc4001; # sensor unreset, clk 24MHz, VI 99MHz
    ;;

    mn34222)
    himm 0x200f0040 0x2; # I2C0_SCL
    himm 0x200f0044 0x2; # I2C0_SDA

    himm 0x2003002c 0x94001; # sensor unreset, clk 37.125MHz, VI 99MHz
    ;;

    bt1120)
    himm 0x200f0008 0x4; # VI_VS
    himm 0x200f000c 0x4; # VI_HS
    himm 0x200f007c 0x1; # VI_DATA13
    himm 0x200f0080 0x1; # VI_DATA10
    himm 0x200f0084 0x1; # VI_DATA12
    himm 0x200f0088 0x1; # VI_DATA11
    himm 0x200f008c 0x1; # VI_DATA15
    himm 0x200f0090 0x1; # VI_DATA14
    himm 0x200f0094 0x1; # VI_DATA9

    himm 0x2003002c 0x94003; # sensor unreset, clk 24MHz, VI 99MHz
    ;;

    *)
    echo "xxxx Invalid sensor type $SNS_TYPE xxxx"
    report_error;;
    esac
    }

     

     查看/etc/profile中的内容(此次为自行添加的内容)


    ifconfig lo 127.0.0.1
    ifconfig eth0 192.168.1.10

    cd /ko
    ./load3518e -i -sensor ar0130 -osmem 32 -total 64
    mount -t nfs -o nolock 192.168.1.14:/home/swann/nfs_hi /mnt
    cd /mnt

    .

    修改参数为

    /load3518e -i -sensor ov9712 -osmem 32 -total 64


    (2)更换另一个Sensor(OV9712),并实现之前的实验
    (3)Sensor接口:并口/LVDS/MIPI CSI
    (4)SoC的Sensor接口引脚复用设置
    (5)sensor驱动源码详解
    (6)sample中sensor相关的部分详解
    4.1.2、查看SDK的2个相关文档


    4.2.更换OV9712并且做配置更改和测试
    4.2.1、更改配置脚本
    4.2.2、运行rtsp传输的测试版本
    4.2.3、运行官方SDK sample的测试版本
    4.2.4、运行ORTP传输的测试版本
    4.2.5、更换sensor的总结
    (1)程序框架做好多种sensor支持的框架
    (2)注意硬件接线上面的差异
    (3)加载不同的驱动,做不同的参数设置

    修改mpp/sample/makefile.param,更换sensor type,如何make clean,

    进入venc文件夹,make


    4.3_4.MIPI和LVDS和并口的细节讲解1_2
    4.3.1、并口Sensor
    (1)OV9712和AR0130都是并口的
    (2)并口的接口定义:参考AR0130的原理图pdf
    (3)并口传输的是CMOS电平信号(重点是非差分)
    (4)并口sensor属于较低端老旧的,新型高像素的都是MIPI/LVDS/HISPI等差分信号的
    4.3.2、LVDS
    (1)low voltage differential signal,低电压差分信号
    (2)接口由1组差分clock和若干组差分信号线组成
    (3)LVDS主要用于视频传输的2个领域:camera和主控、LCD和主控
    (4)LVDS利用差分抗干扰能力,提升clock频率从而提升带宽,传输距离也更远
    (5)LVDS的数据线组数越多带宽越大、clock频率越高带宽越大(牺牲抗干扰和距离)
    (6)并口和LVDS之间可以互转,但是需要专门的电平转换芯片(类似于232和485)
    4.3.3、MIPI(MIPI-CSI2)
    (1)MIPI: mobile industry processor interface,移动工业处理器接口
    (2)MIPI接口由1组差分clock和1-4组差分信号线组成
    (3)MIPI和LVDS虽然都是差分对信号,但是不兼容,不能直接对接
    (4)MIPI的架构层次更分明,广泛应用在手机平板等领域中,可以认为MIPI是LVDS的升级版
    (5)MIPI的数据线组数越多带宽越大、clock频率越高带宽越大(牺牲抗干扰和距离)
    (6)MIPI和LVDS和并口之间均可以互相转换,但是需要专门的电平转换芯片
    4.3.4、总结
    (1)老旧的、低端的、数据量小的就用电平信号;新的、高端的、数据量大的都用差分信号
    (2)要通信,物理层、协议层、应用层都得能对接才行。
    (3)因为历史原因,很多行业会使用不同的接口标准,必要时需要去互相转换


    4.5_6.HI3518E的Sensor接口引脚复用设置1_2
    4.5.1、查看引脚定义框图
    4.5.2、找到相应设置寄存器
    4.5.3、himm工具


    4.7.sensor驱动源码解析1
    4.7.1、sensor驱动源码寻找
    (1)从sample入手
    (2)sensor层驱动在component/isp中(mppcomponentispsensorar0130)
    (3)底层i2c驱动在kernel中
    4.7.2、sensor驱动的框架
    (1)mpp定义了一套sensor驱动的实现和封装
    (2)xxxx_cmos.c中定义回调和上层函数
    (3)xxxx_sensor_ctl.c中定义底层硬件相关的寄存器值配置函数
    (4)kernel中的I2C驱动提供i2c层面的物理层操作接口

    SAMPLE_COMM_VI_StartIspAndVi

    SAMPLE_COMM_ISP_Init

    sensor_register_callback由开始对接驱动和应用层

    cmos_init_sensor_exp_function(&stIspRegister.stSnsExp);
    s32Ret = HI_MPI_ISP_SensorRegCallBack(IspDev, AR0130_ID, &stIspRegister);

    HI_S32 cmos_init_sensor_exp_function(ISP_SENSOR_EXP_FUNC_S *pstSensorExpFunc)
    {
    memset(pstSensorExpFunc, 0, sizeof(ISP_SENSOR_EXP_FUNC_S));

    pstSensorExpFunc->pfn_cmos_sensor_init = sensor_init;
    pstSensorExpFunc->pfn_cmos_sensor_exit = sensor_exit;
    pstSensorExpFunc->pfn_cmos_sensor_global_init = sensor_global_init;
    pstSensorExpFunc->pfn_cmos_set_image_mode = cmos_set_image_mode;
    pstSensorExpFunc->pfn_cmos_set_wdr_mode = cmos_set_wdr_mode;

    pstSensorExpFunc->pfn_cmos_get_isp_default = cmos_get_isp_default;
    pstSensorExpFunc->pfn_cmos_get_isp_black_level = cmos_get_isp_black_level;
    pstSensorExpFunc->pfn_cmos_set_pixel_detect = cmos_set_pixel_detect;
    pstSensorExpFunc->pfn_cmos_get_sns_reg_info = cmos_get_sns_regs_info;

    return 0;
    }

    void sensor_init()
    {

    if (1 == gu8SensorImageMode) /* SENSOR_720P_30FPS_MODE */
    {
    sensor_init_720p_30fps();
    bSensorInit = HI_TRUE;
    }
    else if (2 == gu8SensorImageMode) /* SENSOR_960P_30FPS_MODE */
    {
    sensor_init_960p_30fps();
    bSensorInit = HI_TRUE;
    }
    else
    {
    printf("Not support this mode ");
    }

    }

    sensor_write_register(0x200, 0x31); //sensor_write_register(0x200, 0x01)

    在以下函数中对接sensor驱动和内核IIC接口

    int sensor_write_register(int addr, int data)
    {
    #ifdef HI_GPIO_I2C
        i2c_data.dev_addr = sensor_i2c_addr;
        i2c_data.reg_addr = addr;
        i2c_data.addr_byte_num = sensor_addr_byte;
        i2c_data.data = data;
        i2c_data.data_byte_num = sensor_data_byte;
    
        ret = ioctl(g_fd, GPIO_I2C_WRITE, &i2c_data);
    
        if (ret)
        {
            printf("GPIO-I2C write faild!
    ");
            return ret;
        }
    #else
        int idx = 0;
        int ret;
        char buf[8];
    
        buf[idx++] = addr & 0xFF;
        if (sensor_addr_byte == 2)
        {
            ret = ioctl(g_fd, I2C_16BIT_REG, 1);
            buf[idx++] = addr >> 8;
        }
        else
        {
            ret = ioctl(g_fd, I2C_16BIT_REG, 0);
        }
    
        if (ret < 0)
        {
            printf("CMD_SET_REG_WIDTH error!
    ");
            return -1;
        }
    
        buf[idx++] = data;
        if (sensor_data_byte == 2)
        {
            ret = ioctl(g_fd, I2C_16BIT_DATA, 1);
            buf[idx++] = data >> 8;
        }
        else
        {
            ret = ioctl(g_fd, I2C_16BIT_DATA, 0);
        }
    
        if (ret)
        {
            printf("hi_i2c write faild!
    ");
            return -1;
        }
    
        ret = write(g_fd, buf, idx);
        if(ret < 0)
        {
            printf("I2C_WRITE error!
    ");
            return -1;
        }
    #endif
        return 0;
    }


    4.8.sensor驱动源码解析2
    4.8.1、xxxx_cmos.c中实现和注册回调
    4.8.2、xxxx_sensor_ctl.c中配置sensor寄存器


    4.9.ISP_3A框架解读


    4.10.sensor驱动编译实战
    4.10.1、sensor的注册接口分析
    4.10.2、黑电平

    HI_U32 cmos_get_isp_black_level(ISP_CMOS_BLACK_LEVEL_S *pstBlackLevel)
    {
        HI_S32  i;
        
        if (HI_NULL == pstBlackLevel)
        {
            printf("null pointer when get isp black level value!
    ");
            return -1;
        }
    
        /* Don't need to update black level when iso change */
        pstBlackLevel->bUpdate = HI_FALSE;
    
        switch (genSensorMode)
        {
            default :
            case WDR_MODE_NONE :
                for (i=0; i<4; i++)
                {
                    pstBlackLevel->au16BlackLevel[i] = 0xC8;
                }
                break;
    
        }
    
        return 0;    
    }
    修改 pstBlackLevel->au16BlackLevel[i] = 0xC8;更改黑电平值


    4.10.3、sensor驱动编译实战
    (1)修改驱动源码
    (2)清除,并重新编译
    (3)确认mpp中lib目录下的libsnsxxx.a/so已经被更新
    (4)重新编译sample并运行查看效果


    4.11.sensor驱动的寄存器操作
    4.11.1、sensor的寄存器设置
    (1)sensor内部有若干寄存器,可以通过I2C接口来读写
    (2)数据手册有对寄存器的基本说明
    (3)经验:大部分寄存器设置厂家会给,偶尔需要自己调一些
    4.8.4、实战任务:修改sensor的flip和mirror寄存器查看效果
    (1)查sensor数据手册的寄存器列表
    (2)改sensor驱动代码

    void sensor_init_720p_30fps()

    在pll初始化前添加
    (3)重新编译isp
    (4)确认sensor库已经更新到mpp中
    (5)重新编译sample,运行测试


    4.12.sensor驱动部分贯通总结
    4.12.1、体系思想
    (1)成熟的商业解决方案都是一整套设计好的模式
    (2)第一步是理解,第二步是用起来,第三步是小修改,第四步是大修改,第五步是创造
    4.12.2、海思方案的sensor驱动相关体系关键点
    (1)搞清楚sensor的本质:光电转换+AD+ISP+并口/MIPI/LVDS
    (2)ISP有多种实现:sensor内置、主SoC内置、外接专用ISP芯片
    (3)3A是为最终图像效果负责的,3A的实现有赖于镜头、sensor、isp等各部门协同工作
    (4)海思的体系中把sensor和3A、ISP实现为:指针挂接注册的各自独立模块
    4.12.3、扩展学习方向
    (1)sensor的各种参数
    (2)其他几种sensor的驱动和对比实现
    (3)isp的firmware
    (4)3A算法相关知识

  • 相关阅读:
    <原创>engine中地块的自动编号函数
    <原创>获取窗口上RadioButton的Tag值
    <原创>SQLServer一个高效的存储过程
    ArcEngine中放大、缩小、移动等功能实现的方法
    sublime No packages available for installation
    特殊字符,英文,中文排序
    关于 js中replace 特殊符号 ‘.’ 的问题
    12.3日电话面试
    electron 打包后node_modules 体积过于庞大
    git 本地同步分支数,删除远程已经删除掉的多余分支
  • 原文地址:https://www.cnblogs.com/ordinary-world/p/9983355.html
Copyright © 2020-2023  润新知