I2C(Inter Integrated Circuit,内部集成电路)总线
SDA/SCL
利用 I2C 接口在设备之间进行连接使用的两根线是 SDA(串行数据)和 SCL(串行时钟),它们都是开漏,通过一个上拉电阻接到正电源,因此在不使用的时候扔保持高电平。使用 I2C 总线进行通信的设备驱动这两根线变为低电平,在不使用的时候就让它们保持高电平。
I2c的地址格式
七位地址格式:一个地址字节由7个地址位和1个指示位组成。指示位是0表示一个写操作,是1就要求从机将数据发送回主机
十位地址格式:
i2c_adapter
i2c适配器, 即封装了i2c控制器的"控制信息"
struct i2c_adapter {
struct module *owner; // 所有者
unsigned int id;
unsigned int class; // 该适配器支持的从设备的类型
const struct i2c_algorithm *algo; // 该适配器与从设备的通信算法
void *algo_data;
/* data fields that are valid for all devices */
struct rt_mutex bus_lock;
int timeout; // 超时时间
int retries;
struct device dev; // 该适配器设备对应的device
int nr; // 适配器的编号
char name[48]; // 适配器的名字
struct completion dev_released;
struct list_head userspace_clients; // 用来挂接与适配器匹配成功的从设备i2c_client的一个链表头
};
i2c_algorithm
i2c算法,适配器的通信算法,在构建i2c_adapter结构体变量的时候会去填充这个元素
i2c_client
描述一个i2c次设备,包括i2c_adapter 、i2c_driver ..
struct i2c_client { // 用来描述一个i2c次设备
unsigned short flags; // 描述i2c次设备特性的标志位
unsigned short addr; // i2c 次设备的地址
char name[I2C_NAME_SIZE]; // i2c次设备的名字
struct i2c_adapter *adapter; // 指向与次设备匹配成功的适配器
struct i2c_driver *driver; // 指向与次设备匹配成功的设备驱动
struct device dev; // 该次设备对应的device
int irq; // 次设备的中断引脚
struct list_head detected; // 作为一个链表节点挂接到与他匹配成功的i2c_driver 相应的链表头上
};
i2c_driver
i2c设备驱动
struct i2c_driver { // 代表一个i2c设备驱动
unsigned int class; // i2c设备驱动所支持的i2c设备的类型
/* Notifies the driver that a new bus has appeared or is about to be
* removed. You should avoid using this if you can, it will probably
* be removed in a near future.
*/
int (*attach_adapter)(struct i2c_adapter *); // 用来匹配适配器的函数 adapter
int (*detach_adapter)(struct i2c_adapter *);
/* Standard driver model interfaces */
int (*probe)(struct i2c_client *, const struct i2c_device_id *); // 设备驱动层的probe函数
int (*remove)(struct i2c_client *); // 设备驱动层卸载函数
/* driver model interfaces that don't relate to enumeration */
void (*shutdown)(struct i2c_client *);
int (*suspend)(struct i2c_client *, pm_message_t mesg);
int (*resume)(struct i2c_client *);
/* Alert callback, for example for the SMBus alert protocol.
* The format and meaning of the data value depends on the protocol.
* For the SMBus alert protocol, there is a single bit of data passed
* as the alert response's low bit ("event flag").
*/
void (*alert)(struct i2c_client *, unsigned int data);
/* a ioctl like command that can be used to perform specific functions
* with the device.
*/
int (*command)(struct i2c_client *client, unsigned int cmd, void *arg);
struct device_driver driver; // 该i2c设备驱动所对应的device_driver
const struct i2c_device_id *id_table; // 设备驱动层用来匹配设备的id_table
/* Device detection callback for automatic device creation */
int (*detect)(struct i2c_client *, struct i2c_board_info *);
const unsigned short *address_list; // 该设备驱动支持的所有次设备的地址数组
struct list_head clients; // 用来挂接与该i2c_driver匹配成功的i2c_client (次设备)的一个链表头
};
i2c_board_info
板级i2c设备信息
struct i2c_board_info { // 这个结构体是用来描述板子上的一个i2c设备的信息
char type[I2C_NAME_SIZE]; // i2c 设备的名字,用来初始化i2c_client.name
unsigned short flags; // 用来初始化i2c_client.flags
unsigned short addr; // 用来初始化 i2c_client.addr
void *platform_data; // 用来初始化 i2c_client.dev.platform_data
struct dev_archdata *archdata; // 用来初始化i2c_client.dev.archdata
#ifdef CONFIG_OF
struct device_node *of_node;
#endif
int irq; // 用来初始化i2c_client.irq
};
struct i2c_devinfo {
struct list_head list; // 作为一个链表节点挂接到__i2c_board_list 链表上去
int busnum; // 适配器的编号
struct i2c_board_info board_info; // 内置的i2c_board_info 结构体
};
i2c_msg
表示一个通信周期的数据相关的结构体
struct i2c_msg {
__u16 addr; /* slave address 设备地址 */
__u16 flags; /* 本次消息的标志位,就是下面的这些 */
#define I2C_M_TEN 0x0010 /* 设置了这个标志位表示从设备的地址是10bit */
#define I2C_M_RD 0x0001 /* 设置了这个标志位表示本次通信i2c控制器是处于接收方,否则就是发送方 */
#define I2C_M_NOSTART 0x4000
#define I2C_M_REV_DIR_ADDR 0x2000 /* 设置这个标志位表示需要将读写标志位反转过来 */
#define I2C_M_IGNORE_NAK 0x1000 /* 设置这个标志意味当前i2c_msg忽略I2C器件的ack和nack信号 */
#define I2C_M_NO_RD_ACK 0x0800 /* 设置这个标志位表示在读操作中主机不用ACK */
#define I2C_M_RECV_LEN 0x0400
__u16 len; /* 数据长度 */
__u8 *buf; /* 数据缓冲区指针 */
};