ITPub博客

首页 > > > 记一次摄像头调试总结

记一次摄像头调试总结

作者:dapan 时间:2020-03-16 21:58:23 0 删除 编辑

因为时间的原因,这次点亮摄像头的时间特别短,昨天下午模组到公司,今天下午点亮。

几个人一起调试,发现的问题也很多,今天下午发现有一个怀疑的问题,我马上驱车几十公里去模组厂调试,回来的时候,同事已经把摄像头点亮了。时间虽然很短,但是我觉得应该把排查的问题点总结一下,避免下次调试摄像头的时候遇到同样的问题。

也希望大家看了我的文章后,如果遇到调试摄像头相关的工作,可以迎刃而解。

#模组供电电压

  • 模拟供电电源可以理解为里面有ADC转换相关的电路,需要一个基准电压,这个就是模拟电源电压。
  • IOVDD ,这个是I2C通信的GPIO口电压,有的GPIO口电压是3.3V,而摄像头芯片的IOVDD是1.8V,就需要转换电路把电压转换成1.8V。
  • DVDD 是数字电压这个需要按照模组规格书提供正确供电。

这三路电压是供电要求,一定要按照摄像头模组设计要求。

3.3V转1.8V的电路

复位脚和PWDN脚电平转换电路


#时钟MCLK

摄像头模组里面是有芯片的,有芯片就需要有时钟,没有时钟的芯片是不能工作的。就好像一个人,没了心跳的话也是不能正常工作的。

时钟这个问题非常关键,我们刚开始有点忽略时钟的问题。实话说,我也很长时间没有调试摄像头了。我2013年在ZTE调过摄像头,到现在也已经很长时间了,经验这个东西还是很有必要的。但是排除经验的话,就是基础的问题了。没有基础的话,根本就不知道其中的原因,只知道需要这个,却不知道为什么需要这个,知所以,但不知所以然。

但是这个时钟是什么时候产生也是很有必要说明的,我跟硬件沟通,这个时钟硬件是直接从CPU连接出来的,中间就加了一个电阻。但是我们开机后还是量不到MCLK。所以这部分应该是软件问题。

从软件流程上可以看出,在开机的时候,我们会打开MCLK,然后去读CHIP ID,如果读到ID,就保持MCLK打开状态,如果读不到,就退出关闭MCLK。所以在开机后去测量MCLK是有可能量不到的。

MCLK在dts里面设置如下

gc5025: gc5025@37 {
		status = "okay";
		compatible = "galaxycore,gc5025";
		reg = <0x37>;
		clock-frequency = <400000>;

		pinctrl-names = "default";
		pinctrl-0 = <&cif_clkout_m0>;

		clocks = <&cru SCLK_CIF_OUT>;
		clock-names = "xvclk";

		avdd-supply = <&vcc2v8_dvp>;
		dovdd-supply = <&vcc1v8_dvp>;
		dvdd-supply = <&vdd1v2_dvp>;

		reset-gpios = <&gpio3 RK_PA3 GPIO_ACTIVE_LOW>;
		pwdn-gpios = <&gpio0 RK_PA0 GPIO_ACTIVE_HIGH>;

		rockchip,camera-module-index = <0>;
		rockchip,camera-module-facing = "front";
		rockchip,camera-module-name = "CMK-CW4191-FG1";
		rockchip,camera-module-lens-name = "CK5502";

		port {
			ucam_out: endpoint {
				remote-endpoint = <&mipi_in_ucam>;
				data-lanes = <1 2>;
			};
		};
	};

对应的dts位置

cif_clkout_m0: cif-clkout-m0 {
				rockchip,pins = <2 RK_PB3 RK_FUNC_1 &pcfg_pull_none_12ma>;/* cif_clkout */
			};

这个GPIO口对应原理图

我们开机后会打开MCLK,然后读取CHIP ID。如果读不到呢?就会关闭MCLK。 看看代码 获取DTS里面的配置设置MCLK

gc5025->xvclk = devm_clk_get(dev, "xvclk");
	if (IS_ERR(gc5025->xvclk)) {
		dev_err(dev, "Failed to get xvclk\n");
		return -EINVAL;
	}
	ret = clk_set_rate(gc5025->xvclk, GC5025_XVCLK_FREQ);
	if (ret < 0) {
		dev_err(dev, "Failed to set xvclk rate (24MHz)\n");
		return ret;
	}
	if (clk_get_rate(gc5025->xvclk) != GC5025_XVCLK_FREQ)
		dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");

如果没有读到CHIP ID 会进入这里

static void __gc5025_power_off(struct gc5025 *gc5025)
{
	int ret;

	if (!IS_ERR(gc5025->pwdn_gpio))
		gpiod_set_value_cansleep(gc5025->pwdn_gpio, 1);
	clk_disable_unprepare(gc5025->xvclk);
	if (!IS_ERR(gc5025->reset_gpio))
		gpiod_set_value_cansleep(gc5025->reset_gpio, 1);
	if (!IS_ERR_OR_NULL(gc5025->pins_sleep)) {
		ret = pinctrl_select_state(gc5025->pinctrl,
			gc5025->pins_sleep);
		if (ret < 0)
			dev_dbg(&gc5025->client->dev, "could not set pins\n");
	}
	regulator_bulk_disable(GC5025_NUM_SUPPLIES, gc5025->supplies);
}

里面有一句

clk_disable_unprepare(gc5025->xvclk);

就是用来关闭时钟的。

如果时钟不是问题,那就是其他的问题了,我们开机后,打开时钟,读取CHIP ID,读不到后,就关闭时钟。读不到的原因就应该从其他地方排查了。

#上电时序

上电时序是很重要的,做单片机的同学应该都有调时序的经验。每个芯片都有自己的脾气,有的芯片对时序严格,有的对时序不够严格。但是如果通信不成功。就需要排查这方面的问题。

GC5025要求的上电时序是。

三路电开启后,MCLK开启后,需要先拉高PWDN,再拉高reset脚。我们正好在这个问题上做错了。 修改后的代码如下


#异常问题

还没调通前,我们摄像头在开机后,我使用命令「如下图」读写I2C寄存器

0x37 是手册上写的 GC5025 的器件地址。但是用这个地址是读不出内容的。但是我把器件地址修改成0x24,却能看到应答信号,而且读寄存器都能正常成功。

你们可能想知道我是如何找到这个0x24的,因为我写了一个脚本。

@echo off
setlocal ENABLEDELAYEDEXPANSION
set /a ii=3
for /l %%i in (1,1,116) do (
echo "adb shell i2cget -y -f 2 !ii! 0xf0 w"
adb shell "i2cget -y -f 2 !ii! 0xf0 w"
set /a ii+=1
)
pause

还有i2c-tools的链接 github.com/weiqifa0/i2c

今天去模组厂的一个原因就是因为这个问题,为什么我写0x37的器件地址,芯片没有应答。但是我写0x24的器件地址,芯片有应答信号。这真的是百思不得姐啊。


正常I2C有应答的波形


调通后,我想了下,这个现象刚好说明了。因为没有正常的上电时序,芯片里面也没有正常工作了。而且这个不正常工作还让我怀疑这个芯片是不是坏掉了。

#总结

看看深圳的夜景

原文作者:;如有侵权,请联系管理员删除。

请登录后发表评论 登录
全部评论

注册时间:2020-08-07

  • 博文量
    4504
  • 访问量
    87205