基于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就只正常比较老的那种也没什么别的办法。吃一堑,长一智,困难越来越多,疲劳越多,白头发也会越多,当然收获也是最多,也会更有价值。

目录
相关文章
|
中间件 测试技术
NestJS 7.x 折腾记: (1) 项目初始化及常规提交门禁加入
系列常规操作,没兴趣的可以跳过这篇水文. 写过Angular 2+的小伙伴会有一种天然的熟悉感. 因为Nest基本就是同一个思想模式搞得~~
284 0
|
SQL 数据库
开发指南—DDL语句—分区表语法—DROP DATABASE
DROP DATABASE语句用于删除数据库。
144 0
|
10天前
|
存储 关系型数据库 分布式数据库
PostgreSQL 18 发布,快来 PolarDB 尝鲜!
PostgreSQL 18 发布,PolarDB for PostgreSQL 全面兼容。新版本支持异步I/O、UUIDv7、虚拟生成列、逻辑复制增强及OAuth认证,显著提升性能与安全。PolarDB-PG 18 支持存算分离架构,融合海量弹性存储与极致计算性能,搭配丰富插件生态,为企业提供高效、稳定、灵活的云数据库解决方案,助力企业数字化转型如虎添翼!
|
8天前
|
存储 人工智能 Java
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
本文讲解 Prompt 基本概念与 10 个优化技巧,结合学术分析 AI 应用的需求分析、设计方案,介绍 Spring AI 中 ChatClient 及 Advisors 的使用。
389 130
AI 超级智能体全栈项目阶段二:Prompt 优化技巧与学术分析 AI 应用开发实现上下文联系多轮对话
|
3天前
|
存储 安全 前端开发
如何将加密和解密函数应用到实际项目中?
如何将加密和解密函数应用到实际项目中?
197 138
|
9天前
|
人工智能 Java API
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
本文介绍AI大模型的核心概念、分类及开发者学习路径,重点讲解如何选择与接入大模型。项目基于Spring Boot,使用阿里云灵积模型(Qwen-Plus),对比SDK、HTTP、Spring AI和LangChain4j四种接入方式,助力开发者高效构建AI应用。
376 122
AI 超级智能体全栈项目阶段一:AI大模型概述、选型、项目初始化以及基于阿里云灵积模型 Qwen-Plus实现模型接入四种方式(SDK/HTTP/SpringAI/langchain4j)
|
3天前
|
存储 JSON 安全
加密和解密函数的具体实现代码
加密和解密函数的具体实现代码
194 136
|
21天前
|
弹性计算 关系型数据库 微服务
基于 Docker 与 Kubernetes(K3s)的微服务:阿里云生产环境扩容实践
在微服务架构中,如何实现“稳定扩容”与“成本可控”是企业面临的核心挑战。本文结合 Python FastAPI 微服务实战,详解如何基于阿里云基础设施,利用 Docker 封装服务、K3s 实现容器编排,构建生产级微服务架构。内容涵盖容器构建、集群部署、自动扩缩容、可观测性等关键环节,适配阿里云资源特性与服务生态,助力企业打造低成本、高可靠、易扩展的微服务解决方案。
1344 8