I2C学习笔记一

参考:http://blog.csdn.net/fanqipin/article/details/7940061

介绍

I2C(Inter-Intergratedcircuit)及子集smbus(system management Bus)接口是嵌入式系统中比较常见的接口。I2C设备主要有EEPROM,HWMON,RTC等。

I2C为两线接口,SDA和SCL。

I2C设备通常为7位地址,但也有10位地址。


在kernel加载时,会加载dts,遍历到dts文件中的i2c设备;

dts中至少包含设备名称和设备地址;

当设备驱动insmod时,driver中的name与dts中的name一致时,probe函数被调用,并将client传递给driver,如此设备与driver建立联系。

在probe中创建设备节点,供用户空间访问设备。

i2cdev->dev = device_create(i2c_dev_class, NULL, MKDEV(I2C_MAJOR, client->adapter->nr), 
NULL,"i2c-%d",client->adapter->nr);

I2C学习笔记一_第1张图片


目前linux仅支持master模式,不支持slave。
一般来说,我们都会按照I2C驱动框架,将操作I2C从设备的代码整合为一个从设备驱动,注册到I2C-CORE中,通过i2c core提供的adapter接口,与从设备进行通信。

i2c驱动架构中有4中角色:core、adapter、client_driver、client_device。
core负责维护i2c bus匹配已经存在的adapter/driver/client;
adapter负责master控制器,提供通信API
client_device:描述从设备的属性
client_driver:从设备驱动。

设备驱动主要围绕struct i2c_driver和 struct i2c_client结构。
i2c_driver对外提供诸如设备枚举、电源管理等回调;
i2c_client由core在probe时提供给driver,描述关联的设备,比如名称、地址等操作设备的必要信息。
驱动完成设备枚举后,拿到设备对应的i2c_client和i2c_adapter结构,就可以调用core的API访问从设备了。

i2c总线上的I2C设备结构

struct i2c_client{
    unsigned short flags;//div
    unsigned short addr;//7位地址
    char name[I2C_NAME_SIZE];
    struct i2c_adapter *adapter;//i2c主机控制器
    struct i2c_driver *driver;
    struct device dev;//the device structure
    int irq;//irq issued by device
    struct list_head detected;    
};
主机控制器提供访问设备硬件接口
struct i2c_algorithm{
    //i2c模式下,收发函数接口
     int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,int num);
   //用于SMBUS模式下,收发函数接口
     int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,  unsigned short flags, char read_write,  u8 command, int size, union i2c_smbus_data *data);
    //用于检查I2C主控制器所支持访问接口,如I2C_FUNC_SMBUS_BYTE,查看是否支持smbus单字节读取和写操作
     u32 (*functionality) (struct i2c_adapter *);
}
struct i2c_adapter {

        struct module *owner;

        unsigned int class; /* classes to allow probing for */

        const struct i2c_algorithm *algo; /* the algorithm to access the bus */

        void *algo_data;

        /* data fields that are valid for all devices*/

        struct rt_mutex bus_lock;

        int timeout;/* in jiffies */

        int retries;

        struct device dev;/* the adapter device */

        int nr;

        char name[48];

        struct completion dev_released;

        struct mutex userspace_clients_lock;

        struct list_head userspace_clients;

};

I2C学习笔记一_第2张图片

数据收发

int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg*msgs, int num);
// 更加强大并通用的传输函数, 可以由多个struct i2c_msg拼凑出复杂的传输. 其中的i2c_msg定义如下:

struct i2c_msg {

__u16 addr;  /*slave address          */

__u16 flags;

#defineI2C_M_TEN     0x0010   /* this is a ten bit chip address */

#defineI2C_M_RD      0x0001   /* read data, from slave to master */

#defineI2C_M_NOSTART      0x4000   /* ifI2C_FUNC_PROTOCOL_MANGLING */

#defineI2C_M_REV_DIR_ADDR 0x2000   /* if I2C_FUNC_PROTOCOL_MANGLING */

#defineI2C_M_IGNORE_NAK   0x1000   /* if I2C_FUNC_PROTOCOL_MANGLING */

#defineI2C_M_NO_RD_ACK        0x0800   /* ifI2C_FUNC_PROTOCOL_MANGLING */

#defineI2C_M_RECV_LEN     0x0400   /* length will befirst received byte */

__u16 len;       /* msg length                 */

__u8 *buf;       /* pointer to msg data            */

};

i2c_transfer顺序处理*msgs指向的所有的i2c_msg,每个i2c_msg执行前都会发START状态

当最后一个i2c_msg执行完成后会发STOP状态。


int i2c_master_send(const struct i2c_client*client, const char *buf, int count);
int i2c_master_recv(const struct i2c_client *client, char *buf, int count);
// 这2个是基本的传输函数,用于在一个传输周期内(START-STOP)传输slave地址+RW+一段数据。

s32 i2c_smbus_read_byte(const struct i2c_client *client);

s32 i2c_smbus_write_byte(const struct i2c_client *client, u8value);

s32 i2c_smbus_read_byte_data(const struct i2c_client*client, u8 command);

s32 i2c_smbus_write_byte_data(const struct i2c_client*client, u8 command, u8 value);

s32 i2c_smbus_read_word_data(const struct i2c_client*client, u8 command);

s32 i2c_smbus_write_word_data(const struct i2c_client*client, u8 command, u16 value);

s32 i2c_smbus_read_word_swapped(const struct i2c_client*client, u8 command);

s32 i2c_smbus_write_word_swapped(const struct i2c_client*client, u8 command, u16 value);

s32 i2c_smbus_read_block_data(const struct i2c_client*client, u8 command, u8 *values);

s32 i2c_smbus_write_block_data(const struct i2c_client*client, u8 command, u8 length, const u8 *values);

s32 i2c_smbus_read_i2c_block_data(const struct i2c_client*client, u8 command, u8 length, u8 *values);

s32 i2c_smbus_write_i2c_block_data(const struct i2c_client*client, u8 command, u8 length, const u8 *values);

// 这些是smbus协议的常用函数, 方便兼容smbus协议的client使用.

// smbus协议是i2c协议的一个子集, 常见的i2cslave器件的寄存器读写都符合smbus协议,

// 这样的话直接使用这些函数会比使用i2c_transfer方便很多.

// smbus协议请参考内核文档android/kernel/Documentation/i2c/smbus-protocol



关于I2C框架的使用, 内核有相关的文档:

android/kernel/Documentation/i2c (文档)


你可能感兴趣的:(I2C学习笔记一)