前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >camera调试:i2c不通如何排查?

camera调试:i2c不通如何排查?

作者头像
用户6280468
发布2024-03-04 15:39:15
2210
发布2024-03-04 15:39:15
举报
文章被收录于专栏:txp玩Linuxtxp玩Linux

前言:

这篇文章介绍一下在调试camera驱动的过程,最常见的一个问题,i2c不通导致驱动注册不上,应该如何排查。常见的报错log如下:

代码语言:javascript
复制
[    1.973566][    T1] gc8034 4-0037: driver version: 00.01.09
[    1.973648][    T1] gc8034 4-0037: Failed to get power-gpios, maybe no use
[    1.973682][    T1] gc8034 4-0037: Failed to get reset-gpios
[    1.974133][    T1] gc8034 4-0037: lane_num(2)  pixel_rate(319887360)
[    1.979292][    T1] gc8034 4-0037: gc8034 read reg:0xf0 failed !
[    1.979461][    T1] gc8034 4-0037: gc8034 read reg:0xf1 failed !
[    1.979477][    T1] gc8034 4-0037: Unexpected sensor id(000000), ret(-6)

camera 模组的i2c不通,与主控的CIF和ISP控制器模块没有关系,一般都是上电时序的没满足要求。下面介绍一下常见的排查方向。

一、i2c地址问题:

①确认i2c地址是否配置正确:

一般sensor的datasheet都会明确给出i2c的地址,需要注意的是,大多数sensor都有SID选择引脚,有两个i2c地址可以选择,这里需要硬件确认选择是哪个地址。

②i2c总线地址是否正确:

需要根据硬件原理图明确i2c是挂载在哪路i2c总线下,并在DTS正确配置。

③是否配置成8位地址:

DTS中配置的i2c地址是7位地址,不包括最后的读写位,检查是否配置成8位地址,如上图展示的某sensor,其i2c地址有0x6c和0x20,这就是8位地址,在dts中需要配置为0x36或者0x10。如下:

代码语言:javascript
复制
 ov16a10: ov16a10@36 {
  compatible = "ovti,ov16a10";
  status = "okay";
  reg = <0x36>;

④i2c总线是否正确引用pinctrl:

需要检查一下i2c的引脚是否正确的引用,可以先看原理图对应的gpio,在检查dts是否正确引用。如下示例引用i2c6m4_xfer。

代码语言:javascript
复制
&i2c6 {
 status = "okay";
 pinctrl-names = "default";
 pinctrl-0 = <&i2c6m4_xfer>;

二、上电时序与MCLK时钟问题:

上电时序与时钟的检查可以一起完成,下面一起讲一下如何检查这类问题。sensor的驱动一般都是在使用的时候才会打开mclk和电源,因此出现问题的时候一半mclk和电源都是关闭的状态,我们可以让sensor不下电,或者直接卡死在下电的流程,然后再确认时钟和电源的问题:

①检查MCLK是否正常,电压幅度是否正确

一般sensor都是24M或者27M的clk,使用示波器确认clk的频率是否正确,如果测量不到24M的mclk,可以怀疑如下原因:

  • sensor的驱动上电的时候是否正确打开clk,参考如下:
代码语言:javascript
复制
 ret = clk_set_rate(ov16a10->xvclk, OV16A10_XVCLK_FREQ);
 if (ret < 0)
  dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
 if (clk_get_rate(ov16a10->xvclk) != OV16A10_XVCLK_FREQ)
  dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
 ret = clk_prepare_enable(ov16a10->xvclk);
 if (ret < 0) {
  dev_err(dev, "Failed to enable xvclk\n");
  return ret;
 }
  • gpio是否被其他模块占用了,可以使用io命令查询iomux复用是否正确,一般串口log也会打印相应的错误。
  • MCLK的电压幅度不对,比较大的可能是电源域io-domain配置错误,有1.8V和3.3V,需要根据实际原理图进行配置io-domian。

②检查供电

sensor的供电一般是avdd,dvdd,diovdd三路电源,使用万用表确认3路电源是否正常。入不正常,可检查驱动代码是否有打开对应的电源,或者硬件设计错误。

③检查reset,powdn引脚状态:

可以查看sensor的datasheet对这引脚的描述,确定是高电平有效还是低电平有效:示例如下的sensor说明reset和PWDN都是低电平有效,那么说明低电平的时候会复位或者进入power down,因此需要正常工作的话,这两个引脚都应该是高电平的状态才正确。

如果引脚状态错误的话,一般是驱动代码和dts配置没有统一,修改其中一个配置即可。

这里说明一下容易出错的地方:dts配置的gpio的GPIO_ACTIVE_HIGH跟datasheet说的没关系,dts配置的高/低有效是给驱动代码使用的,如果是高有效,那么驱动代码写1则是输出高,写0输出低,反之同理。

  • dts配置GPIO_ACTIVE_HIGH,驱动操作设置为1,最终输出高电平
  • dts配置GPIO_ACTIVE_HIGH,驱动操作设置为0,输出低电平
  • dts配置GPIO_ACTIVE_LOW,驱动操作设置为1,输出低电平
  • dts配置GPIO_ACTIVE_LOW,驱动操作设置为0,输出高电平

如果dts和驱动代码都操作正确,但是gpio始终无法改变,需要确认:

  • gpio是否被其他的模块复用
  • gpio是否默认上拉或者下拉,需要配置成pcfg_pull_none。

④检查上电时序:

sensor的datasheet都会描述sensor需要的上电时序,驱动的控制需要符合上电时序要求,比较严格的sensor,这里更加容易出错:

驱动上电函数:

代码语言:javascript
复制
static int __ov13855_power_on(struct ov13855 *ov13855)
{
 int ret;
 u32 delay_us;
 struct device *dev = &ov13855->client->dev;
 
 if (!IS_ERR(ov13855->power_gpio))
  gpiod_set_value_cansleep(ov13855->power_gpio, 1);
 
 usleep_range(1000, 2000);
 
 if (!IS_ERR_OR_NULL(ov13855->pins_default)) {
  ret = pinctrl_select_state(ov13855->pinctrl,
        ov13855->pins_default);
  if (ret < 0)
   dev_err(dev, "could not set pins\n");
 }
 ret = clk_set_rate(ov13855->xvclk, OV13855_XVCLK_FREQ);
 if (ret < 0)
  dev_warn(dev, "Failed to set xvclk rate (24MHz)\n");
 if (clk_get_rate(ov13855->xvclk) != OV13855_XVCLK_FREQ)
  dev_warn(dev, "xvclk mismatched, modes are based on 24MHz\n");
 ret = clk_prepare_enable(ov13855->xvclk);
 if (ret < 0) {
  dev_err(dev, "Failed to enable xvclk\n");
  return ret;
 }
 if (!IS_ERR(ov13855->reset_gpio))
  gpiod_set_value_cansleep(ov13855->reset_gpio, 0);
 
 ret = regulator_bulk_enable(OV13855_NUM_SUPPLIES, ov13855->supplies);
 if (ret < 0) {
  dev_err(dev, "Failed to enable regulators\n");
  goto disable_clk;
 }
 
 if (!IS_ERR(ov13855->reset_gpio))
  gpiod_set_value_cansleep(ov13855->reset_gpio, 1);
 
 usleep_range(5000, 6000);
 if (!IS_ERR(ov13855->pwdn_gpio))
  gpiod_set_value_cansleep(ov13855->pwdn_gpio, 1);
 
 /* 8192 cycles prior to first SCCB transaction */
 delay_us = ov13855_cal_delay(8192);
 usleep_range(delay_us * 2, delay_us * 3);
 
 return 0;
 
disable_clk:
 clk_disable_unprepare(ov13855->xvclk);
 
 return ret;
}

⑤供电、CLK等正确,i2c依旧不通

有时候camera我们使用的是转接小板,需要使用主板对转接小板进行供电,这时候执行上电函数之后,主板给小板供电比较慢,可能会导致check ID失败,这时候可以在驱动的上电函数(power_on)适当的加上一些延时,保证小板成功供电,再执行check id的操作。

参考:https://blog.csdn.net/qq_34341546/article/details/129030535

本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2024-03-01,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 txp玩Linux 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言:
  • 一、i2c地址问题:
    • ①确认i2c地址是否配置正确:
      • ②i2c总线地址是否正确:
        • ③是否配置成8位地址:
          • ④i2c总线是否正确引用pinctrl:
          • 二、上电时序与MCLK时钟问题:
            • ①检查MCLK是否正常,电压幅度是否正确
              • ②检查供电
                • ③检查reset,powdn引脚状态:
                  • ④检查上电时序:
                    • ⑤供电、CLK等正确,i2c依旧不通
                    领券
                    问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档