iic子系统

I2C子系统详解

I2C子系统分析

firefly-3399
linux内核版本:4.4

参考博客:
https://www.cnblogs.com/deng-tao/p/6130080.html
http://blog.youkuaiyun.com/w89436838/article/details/38660631
http://blog.youkuaiyun.com/wangpengqi/article/details/17711165

I2C硬件

一个I2C总线上挂载了多个I2C接口器件,但是这些I2C从设备的地址可能会重突,大部分以0xA开头的,所以在ARM的SOC上会有多个I2C适配器,每个I2C适配器上挂在1到2个从设备

I2C 总线在物理连接上非常简单,分别由SDA(串行数据线)和SCL(串行时钟线)及上拉电阻组成。通信原理是通过对SCL和SDA线高低电平时序的控制,来 产生I2C总线协议所需要的信号进行数据的传递。在总线空闲状态时,这两根线一般被上面所接的上拉电阻拉高,保持着高电平。

I2C子系统驱动

首先,I2C的架构和SPI的很相似,有适配器,设备,通过核心来进行连接,这样的分离架构可以使得Adapter和Device几乎没有耦合性,m+n个驱动可以形成m*n个搭配方式

  • I2C核心层:代码位于i2c-core.c ,注册了i2c总线,实现了i2c_adapter的注册函数,i2c_driver和i2c_device的注册函数
  • I2C适配器层:代码位于i2c-rk3x.c,提供i2c adapter的algorithm
  • I2C驱动层:代码位于i2c-dev.c(通用的驱动),注册了设备节点,提供了file_operations
I2C核心层

/**
*   i2c-core.c
*   注册了i2c总线,实现了i2c_adapter的注册函数,i2c_driver和i2c_device的注册函数
*   起到了连接上下层的作用,上层指的是i2c-dev.c中的通用用户层接口驱动程序,下层是i2c-rk3x.c中的soc内部适配器(bus)驱动程序  
**/

struct bus_type i2c_bus_type = {
    .name       = "i2c",                        //  总线的名字
    .match      = i2c_device_match,             //  总线下设备与设备驱动的匹配函数
    .probe      = i2c_device_probe,             //  总线层的probr函数   
    .remove     = i2c_device_remove,            //  总线卸载时执行的函数  
    .shutdown   = i2c_device_shutdown,          //  电源管理
};
static struct i2c_driver dummy_driver = {
    .driver.name    = "dummy",
    .probe      = dummy_probe,          //null实现
    .remove     = dummy_remove,         //null实现
    .id_table   = dummy_id,
};


postcore_initcall(i2c_init)
i2c_init
    bus_register(&i2c_bus_type)                 //注册i2c总线  /sys/bus/i2c
    class_compat_register("i2c-adapter")        //创建一个class /sys/class/i2c-adapter
    i2c_add_driver(&dummy_driver)               //注册一个i2c_driver,null驱动
i2c_device_probe(struct device *dev)//当i2c总线下的i2c_device和i2c_driver匹配后执行
    i2c_client  *client = i2c_verify_client(dev)                    // 通过device指针获取到对应的i2c_client指针 
    i2c_driver  *driver = = to_i2c_driver(dev->driver)              // 通过device->dr
Linux系统中,通常所说的IIC驱动IIC子系统驱动有一定的关联和区别。 IIC子系统Linux内核中用于管理I2C设备和驱动的一套机制。Linux启动阶段会创建一个IIC总线`i2c_bus_type`,该总线用于管理`i2c_client`设备和`i2c_driver`驱动,它实现了自己的`match`和`probe`函数等,和Linux驱动之设备模型里的总线类似,起到协调和管理I2C相关设备与驱动的作用 [^2]。 而IIC驱动则是基于IIC子系统来实现对具体I2C设备进行操作的代码。Linux系统提供了2种IIC驱动实现方法 [^1]: - **IIC - DEV方式**:对应`driver/i2c/i2c - dev.c`,这种方法只是封装了主机的IIC基本操作,并且向应用层提供相应的操作接口。应用层代码需要自己去实现对`slave`的控制和操作,相当于传统的驱动中干的活都丢给了应用去做,所以又叫做“应用层驱动”。其优势在于把差异化都放在了应用层,当设备比较难缠(尤其是`slave`是非标准的IIC时),不用动驱动,只需要修改应用就可以实现对各种设备的驱动- **驱动层实现方式**:所有代码都放在驱动层实现,直接向应用层提供最终结果。应用层甚至不需要知道这里面有IIC存在,例如电容式触摸屏驱动,直接向应用层提供`/dev/input/event1`的操作接口,应用层编程的人根本不知道`event1`中涉及到了IIC。 ### 区别总结 IIC子系统驱动更侧重于整个I2C设备管理机制的搭建和维护,是一个通用的框架;而IIC驱动则是利用这个框架针对具体的I2C设备编写的操作代码,不同的IIC设备的主要不同点在于其寄存器列表不同、初始化不同,但对不同的IIC设备的操作方法基本相同 [^1]。 ### 示例代码理解IIC操作 ```c // 假设这是一个简单的IIC写操作函数示例 #include <linux/i2c.h> int i2c_write(struct i2c_client *client, u8 reg, u8 value) { int ret; u8 buf[2]; buf[0] = reg; buf[1] = value; ret = i2c_master_send(client, buf, 2); if (ret != 2) { printk(KERN_ERR "I2C write failed\n"); return ret; } return 0; } ``` 此代码展示了一个简单的I2C写操作函数,通过`i2c_master_send`函数向指定的I2C设备寄存器写入数据。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值