RK3568驱动OV13850摄像头模组调试过程

news2024/11/25 11:42:25
  1. 摄像头介绍

  • 品牌:Omnivision

  • 型号:CMK-OV13850

  • 接口:MIPI

像素:1320W

OV13850彩色图像传感器是一款低电压、高性能1/3.06英寸1320万像素CMOS图像传感器,使用OmniBSI+?技术提供了单-1320万像素(4224×3136)摄像头的功能。通过串行摄像头控制总线(SCCB)接口的控制,它提供了全帧、下采样、开窗的10位MIPI图像。

OV13850拥有一个能够在10位1320万像素分辨率下以每秒24帧(fps)的速度运行的图像阵列,用户可以完全控制图像质量、格式和输出数据传输。所有需要的图像处理功能,包括曝光控制、白平衡、缺陷像素消除等,都可以通过SCCB接口进行编程。

此外,OmniBSI图像传感器使用专有的传感器技术,通过减少或消除固定图案噪声、污迹等常见的图像污染光源来提高图像质量,从而产生干净、完全稳定的彩色图像。

为了提供定制信息,OV13850包括一个单编程(OPT)存储器。OV13850拥有最多4车道的MIPI接口。

硬件连接方式如下图:摄像头的I2C接口使用RK3568的I2C4引脚,RESET, PWRDOWN使用普通IO口,三路电源供电使用LDO,LDO由普通IO来控制使能,用于控制上电时序。图像传输接口使用CSI2, 4lan MIPI接口。

  1. RK3568设备树修改

OV13850的设备树修改可以参考其他芯片的设备树,在RK3568 Linux SDK中可以搜索到很多,主要是就是配置OV13850使用的复位控制引脚,I2C通信引脚,PWDNB引脚,三路电源上电控制引脚,CIF_CLK时钟引脚,如下面的I2C部分的设备树,调试OV13850时应首先从I2C调试开始,I2C通了后才会加载MIPI部分的驱动。

&i2c4 {
    status = "okay";
    clock-frequency = <400000>;

    ov13850: ov13850@10 {
        compatible = "ovti,ov13850";
        status = "okay";
        reg = <0x10>;
        clocks = <&cru CLK_CIF_OUT>;
        clock-names = "xvclk";
        power-domains = <&power RK3568_PD_VI>;
        pinctrl-names = "rockchip,camera_default","rockchip,camera_sleep";
        pinctrl-0 = <&cif_clk>;
        pinctrl-1 = <&cam0_sleep_pins>;
        //pinctrl-2 = <&cif_clk>;
        
        
        avdd-supply = <&avdd_2v8_camera_power>;  /* 2.8v */
        dvdd-supply = <&dvdd_1v2_camera_power>;  /* 1.2v */
        dovdd-supply = <&dovdd_1v8_camera_power>; /* 1.8v */

        /* reset and pwdn */
        reset-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>;
        pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;
        
        rockchip,camera-module-index = <0>;
        rockchip,camera-module-facing = "back";
        rockchip,camera-module-name = "CMK-CT0116";
        rockchip,camera-module-lens-name = "Largan-50013A1";
        lens-focus = <&vm149c>;

        port {
            ov13850_out0: endpoint {
                remote-endpoint = <&mipi_in_ucam0>;
                data-lanes = <1 2 3 4>;
            };
        };
    };

    vm149c: vm149c@0c {
        compatible = "silicon touch,vm149c";
        status = "okay";
        reg = <0x0c>;
        rockchip,camera-module-index = <0>;
        rockchip,camera-module-facing = "back";
        rockchip,vcm-start-current = <20>; // 马达的启动电流
        rockchip,vcm-rated-current = <80>; // 马达的额定电流
        rockchip,vcm-step-mode = <13>; // 马达驱动 ic 的电流输出模式

    };

};

    /*camera avdd 2.8V LDO poweren*/
    avdd_2v8_camera_power:avdd-2v8-camera-regulator {
        compatible = "regulator-fixed";
        regulator-name = "avdd_2v8_camera_power";
        enable-active-high;
        gpio = <&gpio3 RK_PA7 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "default";
        pinctrl-0 = <&avdd2v8_camera_en_pin>;
        //regulator-always-on;

    };

    /*camera dvdd 1.2V LDO poweren*/
    dvdd_1v2_camera_power:dvdd-1v2-camera-regulator {
        compatible = "regulator-fixed";
        regulator-name = "dvdd_1v2_camera_power";
        enable-active-high;
        gpio = <&gpio3 RK_PC5 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "default";
        pinctrl-0 = <&dvdd1v2_camera_en_pin>;
        //regulator-always-on;

    };

    /*camera dovdd 1.8V LDO poweren*/
    dovdd_1v8_camera_power:dovdd-1v8-camera_regulator {
        compatible = "regulator-fixed";
        regulator-name = "dovdd_1v8_camera_power";
        enable-active-high;
        gpio = <&gpio3 RK_PC1 GPIO_ACTIVE_HIGH>;
        pinctrl-names = "default";
        pinctrl-0 = <&dovdd1v8_camera_en_pin>;
        //regulator-always-on;
    };

MIPI部分的设备树可以参考原来开发板上提供的XC7160摄像头来修改,使用full mode ,即4lan CSI2接口,最后修改的如下。

&csi2_dphy_hw {
    status = "okay";
};


&csi2_dphy0 {
    status = "okay";

    ports {
        #address-cells = <1>;
        #size-cells = <0>;
        port@0 {
            reg = <0>;
            #address-cells = <1>;
            #size-cells = <0>;

            mipi_in_ucam0: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&ov13850_out0>;
                data-lanes = <1 2 3 4>;
            };

        };
        port@1 {
            reg = <1>;
            #address-cells = <1>;
            #size-cells = <0>;

            csidphy_out: endpoint@0 {
                reg = <0>;
                remote-endpoint = <&isp0_in>;
            };
        };
    };
};

&rkisp_vir0 {
    status = "okay";

    port {
        #address-cells = <1>;
        #size-cells = <0>;

        isp0_in: endpoint@0 {
            reg = <0>;
            remote-endpoint = <&csidphy_out>;
        };
    };
};

&rkisp_vir1 {
    status = "disabled";
};

&csi2_dphy1 {
    status = "disabled";
    /*
    * dphy1 only used for split mode,
    * can be used  concurrently  with dphy2
    * full mode and split mode are mutually exclusive
    */
};

&csi2_dphy2 {
    status = "disabled";
    /*
    * dphy2 only used for split mode,
    * can be used  concurrently  with dphy1
    * full mode and split mode are mutually exclusive
    */
};

&rkisp {
    status = "okay";
};

&rkisp_mmu {
    status = "okay";
};

硬件由于是公司第一次做,驱动第一次调,所以调试过程中肯定会遇到问题。果不然,设备树改好后,上电I2C通信不上,即无法使用0x10的地址来识别摄像头。而且识别的摄像头I2C从机地址是0x0b,0x0C,其中0x0C是摄像头内的一个芯片AD5823, 对应的驱动程序就是设备树中的vm149c。

经过使用 sudo i2ctransfer -f -y 4 w2@0x0c 0x30 0x0a r2 读取摄像头ID寄存器0x300A 测试,发现摄像头返回的是0x30 0x0A,总结出来的规律就是读任何寄存器,都返回的是寄存器的地址。

由于一时找不到软件的问题,就让硬件使用示波器测试了一下,三路电源上电的时序是avdd先上,之后是dovdd和dvdd,根据手册上电之间的延时大于0ns即可,如下图。示波器测量显示上电顺序是按照avdd,dovdd,dvdd的顺序,之间的延时为50us, 这个延时就是程序执行先后打开各路电源的运行时间。

之后又测量了I2C的时钟,数据线也未发现问题,测量了一下CIF_CLKOUT信号,这个信号是由RK3568输出给摄像头的,时钟频率是24M,由于摄像头I2C初始读取ID失败后,会关闭电源与时钟,所以24M的时钟只是在初始化时有,一会就没有了。

硬件测试也没有找到问题,那看来还得接着找软件的问题,当然看了不少csdn文章,之后又研究了一下ov13850的驱动程序,ov13850.c,重点看了一下__ov13850_power_on函数,这个函数。

static const char * const ov13850_supply_names[] = {
    "avdd",        /* Analog power */
    "dovdd",    /* Digital I/O power */
    "dvdd",        /* Digital core power */
};

static int __ov13850_power_on(struct ov13850 *ov13850)
{
    int ret;
    u32 delay_us;
    struct device *dev = &ov13850->client->dev;
    //硬件设计中摄像头的三路电源全是分别控制的,所以此power_gpio没有引脚对应,也没有设备树
    if (!IS_ERR(ov13850->power_gpio))
        gpiod_set_value_cansleep(ov13850->power_gpio, 1);

    usleep_range(1000, 2000);
    //pins_default对应设备树中的cif_clk,用于初始RK3568输出的24M时钟,此程序用于配置时钟引脚的为时钟输出功能
    if (!IS_ERR_OR_NULL(ov13850->pins_default)) {
        ret = pinctrl_select_state(ov13850->pinctrl,
                       ov13850->pins_default);
        if (ret < 0)
            dev_err(dev, "could not set pins\n");
    }
   //设置xvclk时钟为24M
    ret = clk_set_rate(ov13850->xvclk, OV13850_XVCLK_FREQ);
    if (ret < 0)
        dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
    if (clk_get_rate(ov13850->xvclk) != OV13850_XVCLK_FREQ)
        dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
    ret = clk_prepare_enable(ov13850->xvclk);
    if (ret < 0) {
        dev_err(dev, "Failed to enable xvclk\n");
        return ret;
    }
    if (!IS_ERR(ov13850->reset_gpio))
        //复位信号输出为无效,即如果设备树中reset-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>,此时输出的电源就是低电平
        gpiod_set_value_cansleep(ov13850->reset_gpio, 0);
    //打开摄像头供电的三路电源,电源的打开的顺序按照ov13850_supply_names数组中定义的顺序,由于设备树中使用的regulaor来控制电源,所以这部分代码有效
    ret = regulator_bulk_enable(OV13850_NUM_SUPPLIES, ov13850->supplies);
    if (ret < 0) {
        dev_err(dev, "Failed to enable regulators\n");
        goto disable_clk;
    }

    if (!IS_ERR(ov13850->reset_gpio))
        //复位信号输出为有效,即如果设备树中reset-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>,此时输出的电源就是高电平
        gpiod_set_value_cansleep(ov13850->reset_gpio, 1);

    usleep_range(500, 1000);
    if (!IS_ERR(ov13850->pwdn_gpio))
        //pwdn_gpio信号输出为有效,即如果设备树中pwdn-gpios = <&gpio1 RK_PD1 GPIO_ACTIVE_HIGH>,此时输出的电源就是高电平
        gpiod_set_value_cansleep(ov13850->pwdn_gpio, 1);

    /* 8192 cycles prior to first SCCB transaction */
    delay_us = ov13850_cal_delay(8192);
    usleep_range(delay_us, delay_us * 2);

    return 0;

disable_clk:
    clk_disable_unprepare(ov13850->xvclk);

    return ret;
}

上面的程序看懂了,下面开始使用万用表来测量reset,pwdn这两个引脚的状态,由于摄像头初始化失败后会进行power_off操作,所以为了测量上电时电平是否正常,把__ov13850_power_off函数中代码关闭,使之一直保持在上电状态。

程序改好后,下载,测量,果然发现pwdn这个信号电平不对,这个信号串联了一个22欧姆的电阻,测量这两个电阻两边的电压一端是0V, 一端是1.8V,电阻坏了,换一个新的,同时检查了一下其他电阻有也坏的,一起更换。换好后,发现电平信号是低电平,电阻两端都是低电平,对着上电时序一下,上电后应该为高电平才对,修改设备树pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_LOW>; -->pwdn-gpios = <&gpio1 RK_PD2 GPIO_ACTIVE_HIGH>;同样对比了一个reset管脚,也是设备树的配置成低电平了。编译程序,开机,摄像头驱动成功加载了,能够识别到摄像头芯片的ID, 加载了视频驱动设备video0-video8, media0。

总结调试遇到的问题,硬件问题与软件问题都有,所以一定要2方面都去查找。硬件问题就是电阻坏了。软件问题是开始设备树写的并不对,先后调整了很多次最后才调试出来的。其他要说的一点就是OV13850驱动程序的reset,pwrdn引脚的有效电平问题与其他芯片驱动的有效电平的意思正好相反,reset信号是在低电平时复位,pwrdn信号是在低电平时有效,所以原来设备树中写成GPIO_ACTIVE_LOW的方式是符合常理的,是驱动程序中把电平的高低有效用反了,实际最应该修改驱动程序ov13850.c中的程序的reset, pwrdn信号的控制电平。

  1. 显示效果

显示效果如下,此时摄像头只能显示天花板上面的灯,其他物体无法成像,只有在强光照射下才能成像,因此还需要做进一步的调试。

  1. 特别鸣谢

在调试摄像头的过程中,参考了很多csdn朋友写的文章,感谢各位的分享,我也以分享的方式回馈大家。具体参考链接如下:

RK3566调试GC2053_火柴棍mcu的博客-CSDN博客

(24条消息) 摄像头ov13850移植笔记_布道师Peter的博客-CSDN博客

(7条消息) 关于RK3399平台OV13850摄像头调试的问题_ov13850摄像头好吗_溯之源的博客-CSDN博客

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/392294.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++20 协程体验

1 介绍协程是比线程更加轻量级并发编程方式&#xff0c;CPU资源在用户态进行切换,CPU切换信息在用户态保存。协程完成异步的调用流程&#xff0c;并对用户展示出同步的使用方式。协程的调度由应用层决定&#xff0c;所以不同的实现会有不同的调度方式&#xff0c;调度策略比较灵…

麻雀算法SSA优化LSTM长短期记忆网络实现分类算法

1、摘要 本文主要讲解&#xff1a;麻雀算法SSA优化LSTM长短期记忆网络实现分类算法 主要思路&#xff1a; 准备一份分类数据&#xff0c;数据介绍在第二章准备好麻雀算法SSA&#xff0c;要用随机数据跑起来用lstm把分类数据跑起来将lstm的超参数交给SSA去优化优化完的最优参数…

Python可变对象与不可变对象的浅拷贝与深拷贝

前言 本文主要介绍了python中容易面临的考试点和犯错点&#xff0c;即浅拷贝与深拷贝 首先&#xff0c;针对Python中的可变对象来说&#xff0c;例如列表&#xff0c;我们可以通过以下方式进行浅拷贝和深拷贝操作&#xff1a; import copya [1, 2, 3, 4, [a, b]]b a …

小众实用!5款不为人知的Windows软件,让你工作更轻松

分享5款冷门但值得下载的Windows软件&#xff0c;个个都是实用&#xff0c;你可能一个都没见过&#xff0c;但是 我觉得你用过之后可能就再也离不开了。 1.键盘可视化——Keyviz Keyviz是一款免费开源的小工具&#xff0c;它的作用是可以实时展示键盘的操作&#xff0c;就可以…

编程语言分类

目录 ❤ 机器语言 机器语言的编程 ❤ 汇编语言 ❤ 高级语言(编程语言) 编译型 解释型 ❤ 动态语言和静态语言 ❤ 强类型定义语言和弱类型定义语言 ❤ 主流语言介绍 C语言 C java python JavaScript SQL PHP python从小白到总裁完整教程目录:https://blog…

浅入浅出keepalived+mysql实现高可用双机热备

当数据库发生宕机的情况&#xff0c;如果配置了数据库主从同步模式或主主同步模式&#xff0c;则可以从从库中获取数据。 当数据库发生宕机的情况&#xff0c;要求应用系统实现高可用&#xff0c;应用系统不会受到影响&#xff0c;需要对mysql进行双机热备实现数据库的高可用。…

断点调试(debug)

目录 F8案例 ​编辑 debug过程中报错 ​编辑用debug查看方法源码 一层一层查看 Arrays.sort()方法 F9 DebugExercise 介绍&#xff1a;断点调试是指在程序的某一行设置一个断电&#xff0c;调试时&#xff0c;程序运行到这一行就会停住&#xff0c;然后可以一步步往下调试…

微服务引擎 MSE 企业版全新升级

作者&#xff1a;流士 随着企业应用大规模云上迁徙与应用微服务化步伐加快&#xff0c;微服务治理的重要性对企业不言而喻&#xff0c;但微服务治理本身的规范化与标准化尚未形成&#xff0c;导致很多企业在微服务治理方面正经历着痛苦的试错期&#xff0c;甚至难以满足线上环境…

工作日志day03

同时构建静态和动态库 //如果用这种方式&#xff0c;只会构建一个动态库&#xff0c;虽然静态库的后缀是.a ADD_LIBRARY(hello SHARED ${LIBHELLO_SRC}) ADD_LIBRARY(hello STATIC ${LIBHELLO_SRC}) //修改静态库的名字&#xff0c;这样是可以的&#xff0c;但是我们往往希望他…

RK3568平台开发系列讲解(显示篇)DRM的atomic接口

🚀返回专栏总目录 文章目录 一、Property二、Standard Properties三、代码案例沉淀、分享、成长,让自己和他人都能有所收获!😄 📢目前DRM主要推荐使用的是 Atomic(原子的) 接口。 一、Property Property(属性)—– Atomic操作必须依赖的基本元素 Property把前面的…

【教学典型案例】28.生产环境nginx限制上传大小

目录一&#xff1a;背景介绍二&#xff1a;Nginx限制上传大小1、Nginx官方文档说明2、设置参数1&#xff09;、在server模块中设置2&#xff09;、在http模块中设置三&#xff1a;问题分析过程四&#xff1a;总结一&#xff1a;背景介绍 二&#xff1a;Nginx限制上传大小 1、N…

X264简介-Android使用(二)

X264简介-Android使用&#xff08;二&#xff09; 4、Ubuntu上安装ffmpeg&#xff1a; 检查更新本地软件包&#xff08;如果未更新&#xff0c;reboot Vmware&#xff09;&#xff1a; sudo apt update sudo apt upgrade官网下载的source文件安装&#xff1a; http://ffmpe…

基于JSP的网上书城

技术&#xff1a;Java、JSP等摘要&#xff1a;随着科技的迅速发展&#xff0c;计算机技术已应用到社会的各个领域。随着计算机技术和通信技术的迅速发展&#xff0c;网络的规模也逐渐增大&#xff0c;网络的元素也随之不断增加&#xff0c;有的利用其通信&#xff0c;有的利用其…

【C++】30h速成C++从入门到精通(IO流)

C语言的输入与输出C语言中我们用到的最频繁的输入输出方式就是scanf ()与printf()。 scanf(): 从标准输入设备(键盘)读取数据&#xff0c;并将值存放在变量中。printf(): 将指定的文字/字符串输出到标准输出设备(屏幕)。注意宽度输出和精度输出控制。C语言借助了相应的缓冲区来…

网络协议丨从物理层到MAC层

我们都知道TCP/IP协议其中一层&#xff0c;就是物理层。物理层其实很好理解&#xff0c;就是物理攻击的物理。我们使用电脑上网时的端口、网线这些都属于物理层&#xff0c;没有端口没有路由你没有办法上网。网线的头我们叫水晶头&#xff0c;也是物理层的一份子。如果你的面前…

认识CSS之基础选择器

&#x1f31f;所属专栏&#xff1a;前端只因变凤凰之路&#x1f414;作者简介&#xff1a;rchjr——五带信管菜只因一枚&#x1f62e;前言&#xff1a;该系列将持续更新前端的相关学习笔记&#xff0c;欢迎和我一样的小白订阅&#xff0c;一起学习共同进步~&#x1f449;文章简…

SpringCloud——Hystrix 从入门到辗转反侧

SpringCloud-Hystrix 服务故障的“雪崩”效应 微服务的“扇出” 多个微服务之间的关联调用称为服务"扇出"。例如微服务A调用微服务B和微服务C&#xff0c;微服务B和微服务C又调用其他的微服务。 由于网络原因或者自身的原因&#xff0c;服务并不能保证 100% 可用&…

fork的黑科技,它到底做了个啥,源码级分析linux内核的内存管理

最近一直在学习linux内核源码&#xff0c;总结一下 https://github.com/xiaozhang8tuo/linux-kernel-0.11 一份带注释的源码&#xff0c;学习用。 fork的黑科技&#xff0c;它到底做了个啥&#xff0c;源码级分析linux内核的内存管理 先导知识&#xff0c;操作系统&#xff1…

提高生活质量,增加学生对校园服务的需求,你知道有哪些?

随着电子商务平台利用移动互联网的趋势提高服务质量&#xff0c;越来越多的传统企业开始关注年轻大学生消费者的校园市场。 提高生活质量&#xff0c;增加学生对校园服务的需求 大学生越来越沉迷于用手机解决生活中的“吃、喝、玩、乐”等服务&#xff0c;如“吃、喝”——可…

gitlab中文社区

1、获取gitlab中文社区项目 中文社区版项目&#xff1a;https://gitlab.com/xhang/gitlab 2、克隆中文仓库 git clone https://gitlab.com/xhang/gitlab.git 3、查看gitlab版本 diff 获取对应版本的中文 head -1 /opt/gitlab/version-manifest.txt #安装的是gitlab-ce…