i2c总线是一种十分常见的板级总线,本文以linux3.14.0为参考, 讨论Linux中的i2c驱动模型并利用这个模型写一个mpu6050的驱动, 最后在应用层将mpu6050中的原始数据读取出来

i2c子系统框架

下图就是我理解的i2c驱动框架示意图, 类似中断子系统, i2c子系统中也使用一个对象来描述一个物理实体, 设备对象与驱动分离, 驱动结合设备对象对硬件设备的描述才可以驱动一个具体的物理设备, 体现了分离的设计思想, 实现了代码的复用, 比如:

  • 一个i2c控制器就对应一个i2c_board_info, 它驱动就是s3c2410_i2c_driver, 他们通过platform_bus_type协调工作。

  • 一个i2c总线上的设备就对应内核中的一个i2c_client类型的对象, 它的驱动就是的i2c_driver, 二者通过i2c_bus_type协调工作。

  • 同样是抽象的思路, 对于i2c总线本身, 内核也使用i2c_bus_type来描述。

事实上, 对于任何一种总线, 内核都有一个bus_type类型的对象与之对应, 但是platform_bus_type并没有对应的实际的物理总线, 这也就是platform总线也叫虚拟总线的原因.

除了分离,i2c子系统也体现的软件分层的设计思想, 整个i2c子系统由3层构成:设备驱动层--i2c核心--控制器驱动

平面设计培训,网页设计培训,美工培训,游戏开发,动画培训

除了经典的分层与分离模型,我们也可以看到一个有意思的现象——Linux 的应用程序不但可以通过设备驱动来访问i2c从设备,还可以通过一个并没有直接挂接到i2c_bus_type的i2c_cleint来找到主机控制器进而访问任意一个i2c设备, 这是怎么回事呢? 我会在下一篇说^-^

核心结构和方法简述

核心结构

  • i2c_adapter对象实现了一组通过一个i2c控制器发送消息的所有信息, 包括时序, 地址等等, 它被i2c主机驱动创建, 通过i2c-core.c和i2c_client和i2c_driver联系到一起, 这样设备端驱动就可以通过其中的方法以及i2c物理控制器来和一个i2c总线的物理设备进行交互

  • i2c_algorithm描述一个i2c主机的发送时序的信息,该类的对象algo是i2c_adapter的一个域

  • i2c_client描述一个挂接在硬件i2c总线上的设备的设备信息,即i2c设备的设备对象

  • i2c_driver描述一个挂接在硬件i2c总线上的设备的驱动方法,即i2c设备的驱动对象,通过i2c_bus_type和设备对象相连

  • i2c_msg描述一个在设备端和主机端之间进行流动的数据, 在设备驱动中打包并通过i2c_transfer()发送。相当于skbuf之于网络设备,urb之于USB设备。