我在使用TVP5150的时候,最原始的IPNC_RDK5.0,就可以对5150进行i2c读写操作,但ADV7441A只能进行i2c写操作,不能进行读操作。
在参考对比TVP51501和ADV7441数据手册中关于i2c时序的时候,发现TVP5150的读操作中在主机发送从机寄存器之后,等待从机应答,主机会紧接着发送一个STOP信号,但ADV7441却没有这个STOP信号。
TVP5150和ADV7441的i2c时序如下:
另外,我在进行i2c的内核调试时候,发现应用层的i2c读写函数,都会调用文件Source\dvsdk_ipnctools\ipnc_psp_03_21_00_04\kernel\drivers\i2c\busses\i2c_davinci.c中的函数i2c_davinci_xfer_msg。
所以,想请教一下,怎样去掉函数i2c_davinci_xfer_msg中关于STOP信号的代码?
malik:
回复 Chris Meng:
Chris Meng,
你好,谢谢您的回复。
我根据您给的链接,参照修改了Source\ipnc_rdk\av_capture\framework\drv\kermod\src目录下的文件dev_i2c.c。
将代码:
int I2C_read(I2C_Obj *pObj, uint8_t *reg, uint8_t *buffer, uint8_t count, uint8_t dataSize){ uint8_t i; int err; struct i2c_client *client; struct i2c_msg msg[1]; unsigned char data[1];
if(pObj==NULL){ return -ENODEV; }
client = &pObj->client; if(!client->adapter){ return -ENODEV; }
if(dataSize<=0||dataSize>4){ return -1; } for(i=0; i<count; i++) { msg->addr = client->addr; msg->flags = 0; msg->len = 1; msg->buf = data; data[0] = reg[i]; err = i2c_transfer(client->adapter, msg, 1); if(err<0) { printk( KERN_ERR " i2c_transfer(0x%x, 0x%x)\n", msg->addr, msg->buf[0]); }
if (err >= 0) { msg->flags = I2C_M_RD; msg->len = dataSize; err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) { if(dataSize==1) { buffer[i] = data[0]; } else if(dataSize==2) { buffer[2*i] = data[1]; buffer[2*i+1] = data[0]; } } } if (err<0) return -ENODEV; } return 0;}
修改成:
int I2C_read(I2C_Obj *pObj, uint8_t *reg, uint8_t *buffer, uint8_t count, uint8_t dataSize){ uint8_t i; int err; struct i2c_client *client; unsigned char data[2]; struct i2c_msg msg[2] = { { client->addr, 0, 1, &data[0] }, { client->addr, I2C_M_RD, 1, &data[1] }, };
if(pObj==NULL){ return -ENODEV; }
client = &pObj->client; if(!client->adapter){ return -ENODEV; }
if(dataSize<=0||dataSize>4){ return -1; } for(i=0; i<count; i++) { data[0] = reg[i]; data[1] = 0xff; err = i2c_transfer(client->adapter, msg, 2); if(err<0) { printk( KERN_ERR " i2c_transfer(0x%x, 0x%x)\n", msg->addr, msg->buf[0]); }
if (err >= 0) { buffer[i] = data[0]; } if (err<0) return -ENODEV; } return 0;}
但是,在运行之后的结果却是这样:
而未修改前的运行结果是这样的:
请问:我的代码还需要哪些修改?
Chris Meng:
回复 malik:
你好,
你不是说你用的是psp目录kernel下的驱动么? 你为什么要去改IPNC软件里面的i2c驱动呢?
malik:
回复 Chris Meng:
Chris Meng,
你好!
因为我理解的dm368的整个i2c调用流程是:Source\ipnc_rdk\av_capture\framework\drv\usermod\src\drv_i2c.c中的i2c读函数会进入文件Source\ipnc_rdk\av_capture\framework\drv\kermod\src\dev_i2c.c中的I2C_read函数,然后进入文件Source\dvsdk_ipnctools\ipnc_psp_03_21_00_04\kernel\drivers\i2c\i2c-core.c中的函数i2c_transfer,最后才会进入文件Source\dvsdk_ipnctools\ipnc_psp_03_21_00_04\kernel\drivers\i2c\busses\i2c-davinci.c。
所以,我参考您给的链接对dev_i2c.c中的I2C_read函数(如果我没找错地方的话)进行修改,但我不知道我哪里修改不正确,导致上面的问题出现?
以下是我参考的部分:
Problem solved! No driver changes necessary. See below for details….
Although most of the drivers don't seem to do this for their xxx_i2c_read functions (I guess because most i2c slave devices don't seem to care about the stop in between a write/read pair), you can actually pass multiple i2c_msg structures to a singe i2c_transfer() call and the stop bit will only be sent on the last command. For example, this is how I got the read to work fr this device:
unsigned char data[2]; struct i2c_msg msg[2] = { { client->addr, 0, 1, &data[0] }, { client->addr, I2C_M_RD, 1, &data[1] }, }; data[0] = reg; data[1] = 0xff; /* just init to some value */ err = i2c_transfer(client->adapter, msg, 2); if (err >= 0) { *val = data[1]; }
Instead of doing this (2 separate calls, which is the code prevalent in most of the drivers):
struct i2c_msg msg[1]; unsigned char data[1]; msg->addr = client->addr; msg->flags = 0; msg->len = 1; msg->buf = data; data[0] = reg; err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) { msg->flags = I2C_M_RD; msg->len = 1; err = i2c_transfer(client->adapter, msg, 1); if (err >= 0) { *val = data[0]; } } }
Chris Meng:
回复 malik:
malikif (err >= 0) { buffer[i] = data[0]; }
这里是否应该是
buffer[i] = data[1];
malik:
回复 Chris Meng:
Chris Meng ,
你好!
我按照您说的修改以后,发现程序还是相同的错误。
另外我在跟踪程序的时候,发现程序根本未进入dev_i2c.c的i2c_read函数,而是在drv_i2c.c中就出现了错误。
具体是在:
但程序上我只修改了dev_i2c.c文件的i2c_read函数,未修改前是能进入这个函数的。
malik:
回复 malik:
Chris Meng,
您好!
我已经把程序修改完了,./i2crw.out程序能够正常结束,而不是出现内存错误,但读出来的值还是最初写入的值,即data[1]的0xff。
您能给我一些建议,关于这个问题?
Chris Meng:
回复 malik:
你好,
请问你还修改了什么解决的之前的问题?
如果修改data【1】的值为其他值(不是0xff),最后你读到的还是data【1】的值么?
如果是,你能否测量下I2C上的信号,看看读的时候返回的值是否正确?
malik:
回复 Chris Meng:
Chris Meng ,
您好!
我的问题已经解决了!谢谢您的帮助!
Chris Meng:
回复 malik:
你好,
很高兴问题已经解决!
能否告知一下修改代码后的问题是如何解决的?谢谢!