4. I2C 时钟频率概念:标准模式、快速模式、高速模式与超快速模式
I2C 总线是一种同步、多主从的串行通信协议,其通信速率由 SCL(串行时钟线) 的频率决定。时钟频率不仅影响数据传输的吞吐量,还直接关系到总线的电气特性、上拉电阻选择以及从设备的兼容性。Linux 内核 I2C 子系统通过 struct i2c_bus_recovery_info 和时钟拉伸(Clock Stretching)机制来适配不同频率下的时序要求。
根据 I2C 总线规范,定义了四种主要的操作模式,每种模式对应不同的时钟频率范围和工作条件:
| 模式 | 最大时钟频率 | 总线电容限制 | 驱动电流要求 | 典型应用场景 |
|---|---|---|---|---|
| 标准模式 (Standard-mode, Sm) | 100 kHz | 400 pF | 3 mA | 低速传感器、EEPROM、RTC |
| 快速模式 (Fast-mode, Fm) | 400 kHz | 400 pF | 6 mA | 音频编解码器、温度传感器、LCD 控制器 |
| 高速模式 (High-speed mode, Hs-mode) | 3.4 MHz | 100 pF | 20 mA | 高分辨率图像传感器、高速 ADC/DAC |
| 超快速模式 (Ultra Fast-mode, UFm) | 5 MHz | 100 pF | 30 mA | 单线单向传输、电源管理总线(PMBus) |
struct i2c_adapter 的 class 字段和 struct i2c_timings 结构体进行配置。对于高速模式,控制器必须支持 I2C_FUNC_10BIT_ADDR 和 I2C_FUNC_PROTOCOL_MANGLING 功能标志。
4.1 标准模式(100 kHz)
标准模式是 I2C 总线最基本的操作模式,所有兼容 I2C 的设备都必须支持此模式。其时钟频率为 0 Hz 至 100 kHz,上升时间(tr)最大为 1000 ns,下降时间(tf)最大为 300 ns。
- 时序参数: SCL 低电平时间(tLOW)≥ 4.7 μs,高电平时间(tHIGH)≥ 4.0 μs。
- 上拉电阻: 在 5V 供电下,典型上拉电阻值为 4.7 kΩ 至 10 kΩ。
- Linux 驱动适配: 标准模式下,内核通常使用
i2c_default_probe进行设备探测,无需特殊时序配置。
static const struct imx_i2c_hwdata imx1_i2c_hwdata = {
.devtype = IMX1_I2C,
.regshift = 0,
.clk_div = imx1_i2c_clk_div,
.ndivs = ARRAY_SIZE(imx1_i2c_clk_div),
.have_dynamic_speed_update = false,
.have_runtime_pm = false,
.have_clk_div_100khz = 0x21, // 标准模式分频值
};
4.2 快速模式(400 kHz)
快速模式将时钟频率提升至 400 kHz,是当前嵌入式系统中最常用的模式。与标准模式相比,快速模式对时序要求更严格:上升时间(tr)最大为 300 ns,下降时间(tf)最大为 300 ns。
- 时序参数: tLOW ≥ 1.3 μs,tHIGH ≥ 0.6 μs。
- 上拉电阻: 通常需要更小的上拉电阻(1.5 kΩ 至 2.2 kΩ)以加快上升沿。
- 兼容性: 快速模式设备可以工作在标准模式,但反之不成立。
i2c_check_functionality 检查适配器是否支持快速模式。
4.3 高速模式(3.4 MHz)
高速模式(Hs-mode)是 I2C 规范中用于高吞吐量场景的增强模式,时钟频率可达 3.4 MHz。该模式引入了 主从握手协议 和 电流源上拉 机制,以克服高频率下的信号完整性问题。
| 特性 | 标准/快速模式 | 高速模式 |
|---|---|---|
| 起始条件 | SDA 下降沿,SCL 高电平 | 主设备发送 Hs 主码(00001XXX) |
| 上拉方式 | 电阻上拉 | 电流源上拉(典型 20 mA) |
| 从设备寻址 | 7 位或 10 位地址 | 8 位 Hs 主码 + 7 位地址 |
| 总线电容 | ≤ 400 pF | ≤ 100 pF |
| Linux 支持 | 通用 I2C 适配器 | 需专用控制器(如 i2c-omap, i2c-s3c2410) |
4.4 超快速模式(5 MHz)
超快速模式(UFm)是 I2C 总线规范中定义的最新单向传输模式,时钟频率高达 5 MHz。与前三者不同,UFm 是 单工通信,仅支持主设备向从设备发送数据,不支持从设备回传 ACK 或数据。
- 单向性: 只有 SDA 线用于数据发送,SCL 仍由主设备驱动。
- 无 ACK: 从设备不产生应答信号,主设备连续发送数据。
- 应用场景: 主要用于 PMBus、LED 驱动器、电源管理芯片等不需要回读的场景。
- Linux 支持: 内核中通过
I2C_FUNC_PROTOCOL_MANGLING标志支持 UFm 传输,但需要控制器硬件支持 5 MHz 时钟。
// 超快速模式传输:主设备连续写入 4 字节
i2c_msg msg;
msg.addr = 0x50; // 从设备地址
msg.flags = 0; // 写操作,无 ACK
msg.len = 4;
msg.buf = data_buffer;
// 调用 i2c_transfer 发送
ret = i2c_transfer(adapter, &msg, 1);
if (ret < 0)
dev_err(&adapter->dev, "UFm transfer failed\n");
4.5 时钟频率与总线仲裁的关系
时钟频率直接影响 I2C 总线的 仲裁过程。在多主设备系统中,仲裁发生在 SDA 线上:当多个主设备同时尝试驱动总线时,输出低电平的设备会赢得仲裁。时钟频率越高,仲裁窗口越短,对主设备的同步要求越严格。
4.6 时钟拉伸(Clock Stretching)与频率适配
时钟拉伸是从设备控制总线速率的一种机制:从设备在需要处理数据时,可以拉低 SCL 线,强制主设备进入等待状态。在高速模式下,时钟拉伸的实现更加复杂,因为 SCL 的上升/下降时间极短。
- 标准/快速模式: 从设备可以在任意 SCL 低电平期间拉伸时钟,主设备通过
i2c_adapter的timeout字段设置等待超时。 - 高速模式: 时钟拉伸仅在 Hs 模式切换后的第一个字节内允许,后续传输中从设备不得拉伸时钟。
- Linux 内核处理: 驱动中通过
i2c_check_clock_stretching函数检测从设备是否支持拉伸,并调整超时时间。
struct i2c_adapter 的 timeout 设置为 msecs_to_jiffies(100)(100 ms),以兼容低速从设备的时钟拉伸需求。对于高速模式,可适当缩短超时至 10 ms。