基于avd7181c解决视频输入效果差的问题<二>---疑难调试手记

简介: 基于avd7181c解决视频输入效果差的问题---疑难调试手记          笔者在上一篇文章中讲述了基于AVD7181C来解决平台视频输入效果差的问题大概解决方案。

基于avd7181c解决视频输入效果差的问题<>---疑难调试手记

 

       笔者在上一篇文章中讲述了基于AVD7181C来解决平台视频输入效果差的问题大概解决方案。在这个探索研究中,也遇到了一些比较麻烦的问题。下面就讲述一些遇到的几个让人欢喜让人忧的问题。

      Avd7181c是通过IIC来控制的。因为iic也是一种非常成熟的通讯接口,我们就直接用全志平台里整理过的iic操作sensor_read, sensor_write接口,这两个接口在平台支持的camera有很多种型号,都是正常使用的,笔者利用者这些接口也移植到了其他几个iic接口的外设中。

/*****************************************************************************************************/
声明:本博内容均由http://blog.csdn.net/sundesheng125原创,转载请注明出处,谢谢!

/*****************************************************************************************************/

       刚开始,在驱动架构搭建好以后,加载AVD7181C驱动后,再加载csi的驱动,就会执行到AVD7181C probe函数,可以得到iicclient,得到adapter,也就是linux iic驱动中对象的总管。笔者调试时,希望在probe函数里大概操作一下AVD7181C的寄存器,也就把ypbpr设置的一组寄存器操作下去。结果显示,这一组寄存器全部都可以正常写进去,这样写寄存器就没有问题。但是,当笔者去读寄存器的值的时候,发现总是读不出来,iic总是返回错误,据错误码分析就iic发出读数据指令后,AVD7181C没有回应数据,但是是收到了接收iic地址的ack。因为用的AVD7181C小模块板也是新做的,我们又检查一下iic的配置以及其他resetstandby两个供电的正常性。

       一步步排除,首先笔者移植了一个已经成熟使用的在其他平台是小模块,因为数据接口的一些不同,直接使用它调试不方便,但是为了验证iic驱动的问题,就飞了两个供电以及iic。问题还是一样,错误信息如下:  

[   44.891141] fuction=sensor_read, client->addr=0x21
[   44.905885] incomplete xfer (0x48)
[   44.905894] [CSI_ERR][7181C]Error -70 on register read
[   44.905903] [CSI_ERR][7181C]err at sensor_read! i = 0, ret=-70,regs.value = -431473217
[   44.934190] fuction=sensor_read, client->addr=0x21
[   44.939380] incomplete xfer (0x48)
[   44.942838] [CSI_ERR][7181C]Error -70 on register read
[   44.948002] [CSI_ERR][7181C]err at sensor_read! i = 1, ret=-70,regs.value = -431473217

        面对这种情况,非常的奇怪,wince的平台、AVD7181Cdemo板子通过pc软件都可以正常操作AVD7181C的寄出去,读写正常。凭着经验判断,这肯定是iic通讯出了问题。可是移植的sensor_read接口也是很成熟,那么多camera都是使用那个接口,都可以正常的读,怎么会有问题呢?带着疑问,跟几个同事聊起这件奇怪的事情,刚好有个同事说以前在在小系统调试过AVD7181C的时候,碰到过类似的问题,就是iic在读的兼容性的问题。面对高手的指路,得一步步证实、验证。

      笔者借用了逻辑分析仪来抓通讯的波形,抓到不能正常读的iic时序图,如下: 

     笔者另外又抓了一个用AVD7181C demo板能正常读它寄存器的iic时序图,如下:

 

      面对这两幅有力的证据,下一步就是找解决办法了。很明显,全志写的sensor_read,很明显是一个读动作,是先发送iic地址后,送出寄存器的地址,然后就是一个stop的命令,接着再重启,发送iic地址,收到ack后,对方并没有发送应该送的数据。显示,就是没对上眼,对方没有理解主机发送的秋波。sensor_read的源代码如下: 

static int sensor_read(struct v4l2_subdev *sd, unsigned char *reg,
		unsigned char *value)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	u8 data[REG_STEP];
	struct i2c_msg msg;
	int ret,i;
	
	for(i = 0; i < REG_ADDR_STEP; i++)
		data[i] = reg[i];
	
	data[REG_ADDR_STEP] = 0xff;
	/*
	 * Send out the register address...
	 */
	msg.addr = client->addr;
	msg.flags = 0;
	msg.len = REG_ADDR_STEP;
	msg.buf = data;
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret < 0) {
		csi_dev_err("Error %d on register write\n", ret);
		return ret;
	}
	/*
	 * ...then read back the result.
	 */
	
	msg.flags = I2C_M_RD;
	msg.len = REG_DATA_STEP;
	msg.buf = &data[REG_ADDR_STEP];
	
	ret = i2c_transfer(client->adapter, &msg, 1);
	if (ret >= 0) {
		for(i = 0; i < REG_DATA_STEP; i++)
			value[i] = data[i+REG_ADDR_STEP];
		ret = 0;
	}
	else {
		csi_dev_err("Error %d on register read\n", ret);
	}
	return ret;
}

       接着分析比较能够正常读的时序图,发现在是先发送iic地址后,送出寄存器的地址后,没有发送停止信号,而是直接重新启动,发送iic地址,收到AVD7181Cack后,很快就收到了数据,然后才是整个通讯的停止信号。

     为了解决这个问题,当然得按照能demo板的时序处理来改写sensor_read。改写后的程序大概如下 

static int sensor_read(struct v4l2_subdev *sd, unsigned char *reg,
		unsigned char *value)
{
	struct i2c_client *client = v4l2_get_subdevdata(sd);
	u8 data[REG_STEP];
	struct i2c_msg msg[2];
	int ret,i;
	
	for(i = 0; i < REG_ADDR_STEP; i++)
		data[i] = reg[i];
	
	data[REG_ADDR_STEP] = 0x0;
	/*
	 * Send out the register address...
	 */
	msg[0].addr = gi2c_addr;//client->addr;
	msg[0].flags = 0x0;
	msg[0].len = REG_ADDR_STEP;
	msg[0].buf = data;
	
	msg[1].addr = gi2c_addr;//client->addr;
	msg[1].flags = I2C_M_RD;
	msg[1].len = REG_DATA_STEP;
	msg[1].buf = &data[REG_ADDR_STEP];
	ret = i2c_transfer(client->adapter, msg, 2);
	if (ret < 0) {
		avd7181c_dev_err("Error %d on register write\n", ret);
		return ret;
	}

for(i = 0; i < REG_DATA_STEP; i++)
			value[i] = data[i+REG_ADDR_STEP];

	ret = 0;

	return ret;
}

       改写后,驱动读寄出去就正常了,说明AVD7181C iic读寄存器兼容性有问题,也确实不常见,现在多数的iic设备,两种sensor_read的处理方式都是可以支持的,AVD7181C就只正常比较老的那种也没什么别的办法。吃一堑,长一智,困难越来越多,疲劳越多,白头发也会越多,当然收获也是最多,也会更有价值。

目录
相关文章
|
Python
Python: 1029 旧键盘_关于我只用了3min这件事
Python: 1029 旧键盘_关于我只用了3min这件事
71 0
|
Windows
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(一)
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(一)
185 0
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(一)
|
Windows
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(三)
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(三)
196 0
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(三)
|
Windows
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(二)
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(二)
149 0
【Windows 逆向】OD 调试器工具 ( CE 中获取子弹动态地址前置操作 | OD 中调试指定地址的数据 )(二)
|
Python
ZZULIOJ-1083,数值统计(多实例测试)(Python)
ZZULIOJ-1083,数值统计(多实例测试)(Python)
|
C++ Python
ZZULIOJ-1097,计算平均成绩(函数专题)(Python)
ZZULIOJ-1097,计算平均成绩(函数专题)(Python)
|
Python
ZZULIOJ-1063,最大公约与最小公倍(Python)
ZZULIOJ-1063,最大公约与最小公倍(Python)
|
Python
ZZULIOJ-1099,角谷猜想(多实例测试)(Python)
ZZULIOJ-1099,角谷猜想(多实例测试)(Python)
|
自然语言处理
【Qt编程】基于Qt的词典开发系列&lt;十一&gt;系统托盘的显示
    本文主要讨论Qt中的系统托盘的设置。系统托盘想必大家都不陌生,最常用的就是QQ。系统托盘以简单、小巧的形式能让人们较快的打开软件。废话不多说,下面开始具体介绍。
1299 0