您的位置:首页 > 运维架构 > Linux

linux内核I2C子系统学习

2015-06-29 18:08 239 查看
因为I2C的通信肯定至少要有2个芯片完成,所以它的驱动是由2大部分组成:

主芯片的i2c的驱动
从芯片的i2c的驱动

注:万一选的都不支持咋办???(惨了,只能2个芯片的驱动都得实现了,不过过程差不多)

(一).主芯片的I2C的驱动:(具体如何实现在后面在具体讲解)

首先要查看linux内核是否支持主芯片中i2c驱动器,如果支持就配置一下就ok了,否则要编写主控芯片的i2c驱动器

编写方法:

第一.要有i2c总线驱动(首先要查查内核i2c文件是否支持这种总线驱动,一般都有支持,如果没有只好自己倒霉自己写了)
第二.i2c设备驱动(主控芯片的地址等等信息)
这个过程都是差不多的,以后在分析。
一般的主控芯片的i2c控制器linux内核基本上支持的很好,如:2410的i2c驱动器的支持

(二).从芯片的I2C的驱动:

下面主要分析从芯片的I2C驱动(也有2种方式,第一个是利用内核提供的i2c-dev.c来构建,另一个是自己写)
主要分析第一种方式:

利用系统给我们提供的i2c-dev.c来实现一个i2c适配器的设备文件。然后通过在应用层操作i2c适配器来控制i2c设备。
i2c-dev.c并没有针对特定的设备而设计,只是提供了通用的read()、write()和ioctl()等接口,应用层可以借用这些接口访问挂接在适配器上的i2c设备的存储空间或寄存器,并控制I2C设备的工作方式。但是read和write方法适用性有限。
所以用ioctl方法来操作:

一般都不会使用i2c-dev.c的read()、write()方法。最常用的是ioctl()方法。ioctl()方法可以实现上面所有的情况(两种数据格式、以及I2C算法和smbus算法)。
针对i2c的算法,需要熟悉struct i2c_rdwr_ioctl_data 、struct i2c_msg。使用的命令是I2C_RDWR。
struct i2c_rdwr_ioctl_data
    {
   struct i2c_msg __user *msgs; /* pointers to i2c_msgs */
   __u32 nmsgs; /* number of i2c_msgs */

};

struct i2c_msg {

_ _u16 addr; /* slave address */

_ _u16 flags; /* 标志(读、写) */

_ _u16 len; /* msg length */

_ _u8 *buf; /* pointer to msg data */

};
针对smbus算法,需要熟悉struct i2c_smbus_ioctl_data。使用的命令是I2C_SMBUS。对于smbus算法,不需要考虑“多开始信号时序”问题。

struct i2c_smbus_ioctl_data {

__u8 read_write; //读、写

__u8 command; //命令

__u32 size; //数据长度标识

union i2c_smbus_data __user *data; //数据

};
首先在内核中已经包含了对s3c2410 中的i2c控制器(总线驱动)驱动的支持。提供了i2c算法(非smbus类型的,所以后面的ioctl的命令是I2C_RDWR)

static const struct i2c_algorithm s3c24xx_i2c_algorithm = {

.master_xfer = s3c24xx_i2c_xfer,

.functionality = s3c24xx_i2c_func,

};

另外一方面需要确定为了实现对AT24C02 e2prom的操作,需要确定从机芯片的地址及读写访问时序。
在网上找了个例子:
具体分析如下:

  以上讲述了一种比较常用的利用i2c-dev.c操作i2c设备的方法,这种方法可以说是在应用层完成了对具体i2c设备的驱动工作。
  接下来准备具体分析如何写第一部分!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: