应用层操作I2C(MTK)

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

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

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 
### SCP、MTKI2C 实现与故障排除 #### SCP (System Control Processor) SCP 是一种用于处理低功耗管理和控制功能的处理器,在嵌入式系统和移动设备中起到至关重要的作用。它通常负责电源管理、温度监控和其他外设接口的任务。 对于基于 Mediatek 平台的设计,SCP 可以独立运行并执行多种后台操作,从而减轻应用处理器的工作负担[^1]。 ```c // 示例:初始化SCP模块 void scp_init(void) { // 配置SCP参数 config_scp_params(); // 启动SCP服务 start_scp_service(); } ``` #### MTK (MediaTek) 芯片组支持 Mediatek 提供了一系列针对不同应用场景优化的芯片解决方案。这些方案不仅集成了高性能的应用处理器,还包含了专门设计用来辅助主CPU工作的协处理器单元如上述提到的SCP。 在开发过程中,开发者可以利用 MediaTek 的 SDK 来简化驱动程序编写以及硬件抽象层(HAL)实现过程。这有助于加速产品上市时间,并确保最佳性能表现[^2]。 #### I2C 总线协议及其实施细节 I2C(Inter-Integrated Circuit)是一种简单有效的双向二线制同步串行通信总线标准,广泛应用于各种微控制器之间的小数据量传输场景。其特点在于只需要两根信号线即可完成多器件间的通讯连接——SDA(数据线)和SCL(时钟线),并且允许多个从机挂载在同一总线上工作而不发生冲突。 当涉及到具体到 MT6795 或其他型号 SoCs 上面时,则需特别关注如下几个方面: - **配置寄存器**:通过编程设置相应的寄存器来定义波特率、地址模式等重要属性; - **中断机制**:合理规划中断优先级和服务例程逻辑结构,以便及时响应外部事件触发; - **错误检测与恢复策略**:建立完善的异常捕捉流程,保障整个系统的稳定性; ```cpp #include <linux/i2c.h> #include <linux/module.h> static int i2c_example_probe(struct i2c_client *client, const struct i2c_device_id *id){ printk(KERN_INFO "Probing device at address %02x\n", client->addr); return 0; } static const struct i2c_device_id example_ids[] = { {"example_i2c_dev", 0}, {} }; MODULE_DEVICE_TABLE(i2c, example_ids); static struct i2c_driver example_driver = { .driver.name= "example_i2c", .probe = i2c_example_probe, .id_table = example_ids, }; module_i2c_driver(example_driver); ```
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值