因为时间的原因,这次点亮摄像头的时间特别短,昨天下午模组到公司,今天下午点亮。
几个人一起调试,发现的问题也很多,今天下午发现有一个怀疑的问题,我马上驱车几十公里去模组厂调试,回来的时候,同事已经把摄像头点亮了。时间虽然很短,但是我觉得应该把排查的问题点总结一下,避免下次调试摄像头的时候遇到同样的问题。
也希望大家看了我的文章后,如果遇到调试摄像头相关的工作,可以迎刃而解。
#模组供电电压
模拟供电电源可以理解为里面有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的链接 https://github.com/weiqifa0/i2c-tool
今天去模组厂的一个原因就是因为这个问题,为什么我写0x37的器件地址,芯片没有应答。但是我写0x24的器件地址,芯片有应答信号。这真的是百思不得姐啊。
正常I2C有应答的波形
调通后,我想了下,这个现象刚好说明了。因为没有正常的上电时序,芯片里面也没有正常工作了。而且这个不正常工作还让我怀疑这个芯片是不是坏掉了。
#总结
看看深圳的夜景
回复「 篮球的大肚子」进入技术群聊
回复「1024」获取1000G学习资料