TI中文支持网
TI专业的中文技术问题搜集分享网站

TMS320DM368:关于i2c_davinci.c

我在使用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:

你好,

很高兴问题已经解决!

能否告知一下修改代码后的问题是如何解决的?谢谢!

赞(0)
未经允许不得转载:TI中文支持网 » TMS320DM368:关于i2c_davinci.c
分享到: 更多 (0)