因为时间的原因,这次点亮摄像头的时间特别短,昨天下午模组到公司,今天下午点亮。
几个人一起调试,发现的问题也很多,今天下午发现有一个怀疑的问题,我马上驱车几十公里去模组厂调试,回来的时候,同事已经把摄像头点亮了。时间虽然很短,但是我觉得应该把排查的问题点总结一下,避免下次调试摄像头的时候遇到同样的问题。
也希望大家看了我的文章后,如果遇到调试摄像头相关的工作,可以迎刃而解。
#模组供电电压
模拟供电电源可以理解为里面有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学习资料
转载:https://blog.csdn.net/weiqifa0/article/details/104935295