I2C
概述
Linux I2C 编程接口支持主机端(Master)和从机端(Slave)之间的总线交互。编程接口围绕两种驱动程序和两种设备结构构建。
I2C“适配器驱动程序”将控制器硬件抽象化。它通常绑定到一个物理设备(可能是 PCI 设备或 platform_device)并通过 struct i2c_adapter 表示每个 I2C 总线段。连接在每条 I2C 总线段上的 I2C 设备通过 struct i2c_client 表示,并绑定到一个 struct i2c_driver,该驱动程序遵循标准的 Linux 驱动模型。内核提供了各种函数以执行标准的 I2C 协议操作。
SMBus(System Management Bus)是 I2C 的一个同级协议。大多数 SMBus 系统也兼容 I2C。相比 I2C,SMBus 对电气特性要求更为严格,并标准化了一些协议消息和使用习惯。通常支持 I2C 的控制器也能执行大多数 SMBus 操作,但 SMBus 控制器未必支持所有 I2C 协议选项。Linux 内核提供了执行多种 SMBus 协议操作的接口,可以使用基础的 I2C 操作,也可以通过向不支持这些 I2C 操作的 i2c_adapter 发出 SMBus 命令。
Linux 内核中的 I2C 驱动框架如下:
关键特性
- 仅支持 HOST 模式
- 支持标准模式(100Kbit/s)和快速模式(400Kbit/s)
- 符合 Philips I2C 总线规范 版本
- 支持 7-bit 和 10-bit 寻址模式
- 支持 Start / Restart / Stop
- 16 字节 FIFO
- 单次传输长度 65535 字节
- 模块启用/禁用功能
- 可编程 SCL 时钟频率
- 8-bit 位宽数据访问
- 自动触发 Clock Stretching
运行原理
I2C 是一种双线双向串行总线,通过 SDA 和 SCL 两根线进行设备间的高效数据交换,适用于多个设备间的短距离通信。
- SDA 和 SCL 通过上拉电阻连接至正电源电压
- 当总线空闲时,两条线路均为高电平
- 连接到总线的设备输出端必须为 open-drain 或 open-collector,实现“线与”功能
I2C 支持以下速率:
- 标准模式:最高 100kbit/s
- 快速模式:最高 400kbit/s
- 高速模式:最高 3.4Mbit/s
I2C 数据传输格式
- 数据在 Master 和 Slave 之间通过 SDA 线逐字节传输
- 传输通过 SCL 线进行同步
- 每个数据字节长度为 8-bit, 字节数不受限制
- 每个字节后必须跟一个 ACK 位(应答位)
数据按 MSB(高位在前)顺序传输
- 若目标设备在操作前无法接收或发送完整字节,控制器将 SCL 拉低,进入等待状态
- 当设备准备好后,释放 SCL,总线继续传输
Start/Stop 信号
- 所有传输以 Start 信号开始,Stop 信号结束
- Start: 在 SCL 为高电平时,SDA 从高电平跳变为低电平
- Stop: 在 SCL 为高电平时,SDA 从低电平跳变为高电平
- Start 和 Stop 信号只能由 Host 发出
- 发出 Start 信号后,总线状态为 busy
- 发出 Stop 信号后,总线状态变为 idle
- 若 Host 发出 Start 后再次发出重复的 Start(Sr)而非 Stop,总线仍保持 busy 状态
I2C 7-bit 地址模式数据传输
Host 可以采用以下三种方式与 Slave 进行通信:
Host 向 Slave 发送多个字节
Host 接收 Slave 的多个字节
Host 使用 combine 模式读取 Slave 数据
API 说明
i2c/master_recv
/**
* i2c_master_recv - issue a single I2c message in master receive mode
* @client: Handle to slave device
* @buf: Where to store data read from slave
* @count: How many bytes to read, must be less than 64k since msg.len is u16
* Returns negative errno, or else the number of bytes read.
*/
static inline int i2c_master_recv(const struct i2c_client *client, char *buf, int count);
i2c/master_send
/**
* i2c_master_send - issue a single I2C message in master transmit mode
* @client: Handle to slave device
* @buf: Data that will be written to the slave
* @count: How many bytes to write, must be less than 64k since msg.len is u16
* Returns negative errno, or else the number of bytes written.
*/
static inline int i2c_master_send(const struct i2c_client *client, const char *buf, int count);
i2c_transfer
/**
* i2c_transfer - execute a single or combined I2C message
* @adap: Handle to I2C bus
* @msgs: One or more messages to execute before STOP is issued to terminate the
operation; each message begins with a START.
* @num: Number of messages to be executed.
* Returns negative errno, else the number of messages executed.
*/
int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
i2c_smbus_xfer
/**
* i2c_smbus_xfer - execute SMBus protocol operations
* @adapter: Handle to I2C bus
* @addr: Address of SMBus slave on that bus
* @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC)
* @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE
* @command: Byte interpreted by slave
* @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL
* @data: Data to be read or written
* Returns a negative errno code else zero on success.
*/
s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
unsigned short flags, char read_write,
u8 command, int protocol, union i2c_smbus_data *data);
i2c_smbus_read_byte、i2c_smbus_write_byte
/**
* i2c_smbus_read_byte - SMBus "receive byte" protocol
* @client: Handle to slave device
* Returns negative errno else the byte received from the device.
*/
s32 i2c_smbus_read_byte(const struct i2c_client *client);
/**
* i2c_smbus_write_byte - SMBus "send byte" protocol
* @client: Handle to slave device
* @value: Byte to be sent
* Returns negative errno else zero on success.
*/
s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value);
i2c_smbus_read_byte_data、i2c_smbus_write_byte_data
/**
* i2c_smbus_read_byte_data - SMBus "read byte" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
* Returns negative errno else a data byte received from the device.
*/
s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command);
/**
* i2c_smbus_write_byte_data - SMBus "write byte" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
* @value: Byte being written
* Returns negative errno else zero on success.
*/
s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, u8
value);
i2c_smbus_read_word_data、i2c_smbus_write_word_data
/**
* i2c_smbus_read_word_data - SMBus "read word" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
* Returns negative errno else a 16-bit unsigned "word" received from the
device.
*/
s32 i2c_smbus_read_word_data(const struct i2c_client *client, u8 command);
/**
* i2c_smbus_write_word_data - SMBus "write word" protocol
* @client: Handle to slave device
* @command: Byte interpreted by slave
* @value: 16-bit "word" being written
* Returns negative errno else zero on success.
*/
s32 i2c_smbus_write_word_data(const struct i2c_client *client, u8 command, u16
value);
i2c_smbus_read_i2c_block_data、i2c_smbus_write_i2c_block_data
/**
* i2c_smbus_read_i2c_block_data - read a block of bytes
* @client: Handle to slave device
* @command: Byte interpreted by slave
* @length: Number of bytes to read
* @values: Pointer to where read bytes will be stored
* Returns the number of bytes read or negative errno.
*/
s32 i2c_smbus_read_i2c_block_data(const struct i2c_client *client,
u8 command, u8 length, u8 *values);
/**
* i2c_smbus_write_i2c_block_data - write a block of bytes
* @client: Handle to slave device
* @command: Byte interpreted by slave
* @length: Number of bytes to write
* @values: Pointer to data to write
* Returns zero on success or negative errno.
*/
s32 i2c_smbus_write_i2c_block_data(const struct i2c_client *client,
u8 command, u8 length, const u8 *values);