应用层操作I2C(MTK)

本文介绍了在MTK平台上,通过用户空间读写I2C设备遇到的问题及解决方案。内容涉及I2C驱动的配置、权限问题、MTK内核i2c_msg结构体差异、repeated start信号的处理,以及数据存储逻辑的分析。通过对内核代码的跟踪和理解,成功解决了I2C读取数据的不一致问题。

linux 驱动中I2C设备驱动有两种,其一为用户模式设备驱动,依赖i2c子系统中的i2c-dev驱动,在用户空间去读写i2c设备,另一种就是普通的设备驱动。本文主要讨论第一种:在用户空间读写I2C设备。

首先关于用户空间读写I2C的基本操作, 《i2c驱动之调用ioctl函数进行读写at24c08》 这篇文章看一下就好,不重复说了。然后是MTK平台,I2C驱动的分析,可以看一下 《MTK I2C驱动代码分析》

下面开始干活:
首先打开文件

	fd=open("/dev/i2c-2",O_RDWR);

发现 /dev 路径下并没有i2c-2这个节点,查看 (project)/kernel-3.18/drivers/i2c 下的Makefile

obj-$(CONFIG_I2C_CHARDEV)	+= i2c-dev.o

而在 (project)/kernel-3.18/arch/arm64/configs/(project)_defconfig中默认情况下,CONFIG_I2C_CHARDEV 这个宏是没有打开的。

# CONFIG_I2C_CHARDEV is not set

把这个宏打开就可以了。这时候又会引出一个权限问题,这个根据SEAndroid的规则,申请相应的权限就好,否则第三方应用无法操作 /dev/i2c-2 这个节点。

然后继续,设置i2c_rdwr_ioctl_data.msgs参数

	vcnl4200_i2c_data.nmsgs = 2;
	vcnl4200_i2c_data.msgs[0].len = 1;
	vcnl4200_i2c_data.msgs[0].flags = 0; //write
	vcnl4200_i2c_data.msgs[0].addr = 0x6B;
    data[0][0]=0x00;
    vcnl4200_i2c_data.msgs[0].buf=data[0];
    
	vcnl4200_i2c_data.msgs[1].len = 2;
	vcnl4200_i2c_data.msgs[1].flags = I2C_M_RD;  //read
	vcnl4200_i2c_data.msgs[1].addr = 0x6B;
    data[1][0]=0;
    data[1][1]=0;
    vcnl4200_i2c_data.msgs[1].buf=data[1];

结果发现无论怎样设置都没有数据输出,即I2C没有波形输出,但是抓log又没有看到报错。最后发现,MTK的内核i2c_msg结构体与linux标准的不一样:

struct i2c_msg {
   
   
	__u16 addr;	/* slave address			*/
	__u16 flags;
#define I2C_M_TEN		0x0010	/* this is a ten bit chip address */
#define I2C_M_RD		0x0001	/* read data, from slave to master */
#define I2C_M_STOP		0x8000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NOSTART		0x4000	/* if I2C_FUNC_NOSTART */
#define I2C_M_REV_DIR_ADDR	0x2000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_IGNORE_NAK	0x1000	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_NO_RD_ACK		0x0800	/* if I2C_FUNC_PROTOCOL_MANGLING */
#define I2C_M_RECV_LEN		0x0400	/* length will be first received byte */
	__u16 len;		/* msg length				*/
	__u8 *buf;		/* pointer to msg data			*/
#ifdef CONFIG_MTK_I2C_EXTENSION
	__u32 timing;	/* parameters of timings		*/
	__u32 ext_flag;
#endif
};

mtk做的i2c_msg结构体多了 timing和ext_flag这两个成员变量。按照上面的参数设置,会出现参数校验失败,而这个参数校验失败,系统不会报错。
修改应用的i2c_msg结构体定义,与内核一致。

完整的I2C读数据函数:

unsigned char _i2c_read ( unsigned char device_addr, unsigned char sub_addr, unsigned char * buff, short int ByteNo )
{
   
   
    unsigned int fd, ret;
    struct i2c_rdwr_ioctl_data vcnl4200_i2c_data;
    const char * i2c_dev = "/dev/i2c-2";
	unsigned char data[2][10];
  
    fd = open ( i2c_dev, O_RDWR );
    if ( fd < 0 )
    {
   
   
        LOGE("error (errno=%d)", errno);
        LOGE ( "no /dev/i2c-2\r\n" );
        return FAIL;
    }
	ioctl(fd, I2C_TIMEOUT, 2);
	ioctl(fd, I2C_RETRIES, 1);
	
	vcnl4200_i2c_data.nmsgs = 2;
	vcnl4200_i2c_data.msgs 
评论 3
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值