前面几篇文章,我们简单聊了 I2C 的通信机制,也聊了为什么 I2C 总线需要上拉电阻。
但在看 Linux I2C 驱动时,很多新手又会遇到一个新名词:SMBus。
比如内核里经常能看到这些接口:
i2c_smbus_read_byte_data()i2c_smbus_write_byte_data()i2c_smbus_read_word_data()
这时候就容易懵:
我不是在学 I2C 吗?怎么突然冒出来一个 SMBus?SMBus 和 I2C 是一个东西吗?I2C 设备能不能用 SMBus 接口访问?
今天就简单捋一捋它们之间的关系。
1. 先说结论
一句话总结:
SMBus 是基于 I2C 发展出来的一套系统管理总线规范,可以理解为 I2C 的“专用化、标准化子集”。
也就是说,SMBus 不是凭空冒出来的新总线,它和 I2C 关系非常近。
它复用了 I2C 的很多基础机制,比如:
SDA / SCL 两根线;起始信号 Start;停止信号Stop;ACK / NACK 应答;高位在前传输;主从设备通信模型。
所以,从底层通信形式看,SMBus 很像 I2C。
但 SMBus 又不是完全等于 I2C。
I2C 更像一个通用通信协议,灵活性很高;SMBus 则是在 I2C 基础上加了一些限制和标准流程,主要服务于系统管理场景。
简单类比一下:
I2C像普通公路,什么车都能跑;SMBus 像基于公路规划出来的通勤专用道,规则更明确,限制也更多。
所以可以粗略理解为:SMBus ⊂ I2C

但这句话也不能理解得太绝对,因为两者在电气特性、超时机制、命令格式等细节上还是有差异。
2. SMBus 为什么会诞生?
I2C 最早是为芯片之间的低速通信设计的,优点是简单、灵活、成本低。
但也正因为它太灵活,不同厂商在使用时可能会各玩各的。
比如:
通信速率怎么定?寄存器怎么访问?命令格式怎么设计?错误怎么处理?设备超时怎么办?
这些问题如果完全交给厂商自由发挥,普通传感器场景可能还能接受,但在 PC、服务器、电源管理、硬件监控这些场景中,就会比较麻烦。
因为系统管理类设备更强调:
兼容性;可靠性;低功耗;故障检测;标准命令格式。
比如温度传感器、电源芯片、电池管理芯片、风扇控制芯片,如果每个厂商都定义一套完全不同的通信方式,系统软件适配起来就会很痛苦。
所以,Intel 在 I2C 的基础上制定了 SMBus,也就是System Management Bus,系统管理总线。
它的目标很明确:给系统管理类外设制定一套更统一、更标准的通信规则。
3. SMBus 和 I2C 到底哪里像?
SMBus 和 I2C 最像的地方,是它们的底层通信方式。
两者都使用:
SDA:数据线;SCL:时钟线。
也都采用主从结构。主机发起通信,从设备根据地址响应。
一次典型通信过程依然是:
Start -> 地址 -> 读/写位 -> ACK -> 数据 -> ACK/NACK ->Stop
所以你会发现,很多 SMBus 设备挂在 I2C 控制器下面也能正常访问。
这也是为什么在 Linux 驱动里,我们经常直接通过 I2C adapter 去访问 SMBus 类设备。
从驱动开发角度看,很多时候你并不需要特别纠结“它到底是 I2C 还是 SMBus”,而是要看设备手册提供了什么访问方式。
4. SMBus 和 I2C 又有什么不同?
虽然 SMBus 基于 I2C,但它比 I2C 更“规矩”。I2C 更偏通用,很多地方可以由设备厂商自定义。
SMBus 则规定了更多标准操作,比如常见的:
Read Byte;WriteByte;Read ByteData;WriteByteData;Read WordData;WriteWordData;Block Read;BlockWrite。
这就是为什么 Linux 内核里会有一堆i2c_smbus_xxx()接口。
比如:
i2c_smbus_read_byte_data(client, reg);
它的含义一般是:向某个设备的某个寄存器地址读取 1 字节数据。
类似地:
i2c_smbus_write_byte_data(client, reg,val);
通常表示:向某个设备的某个寄存器地址写入 1 字节数据。
这些接口把常见的寄存器读写操作封装好了,用起来比手动组织i2c_msg更简单。
5. 为什么 Linux I2C 驱动里经常用 SMBus 接口?
这是很多初学者最容易疑惑的地方。
明明设备树里挂的是 I2C 设备,驱动里为什么调用的是i2c_smbus_read_xxx()?
原因很简单:Linux 内核里的 SMBus 接口,本质上是一组基于 I2C adapter 的便捷访问函数。
对于很多简单 I2C 外设,比如温度传感器、RTC、GPIO 扩展芯片、PMIC 的部分寄存器访问,通信格式通常就是:
写寄存器地址 -> 读/写寄存器数据
这种模式非常常见。
所以内核提供了 SMBus 风格的 API,让驱动开发者不用每次都手动构造struct i2c_msg。
比如普通 I2C 读写可能要自己组织 message:
structi2c_msg msgs[2];
而 SMBus 接口一行就能完成简单寄存器读写:
val= i2c_smbus_read_byte_data(client, reg);
所以很多时候,用 SMBus API 并不代表这个设备只能跑 SMBus,而是因为这个访问方式刚好满足需求。
这也是 Linux I2C 驱动里非常常见的写法。
6. SMBus 设备能不能接到 I2C 总线上?
一般来说,很多 SMBus 设备可以挂到 I2C 总线上使用。
原因是 SMBus 基于 I2C,底层时序和总线结构很接近。
但要注意:不是所有 I2C 设备都能无脑当 SMBus 设备用。
因为 SMBus 对通信速率、超时、命令格式、电气特性等有自己的要求。
有些 I2C 设备通信格式比较特殊,比如需要连续传输大量数据,或者使用不标准的寄存器访问流程,这时就不一定适合用 SMBus API。
所以工程上不要死记:
SMBus设备一定能接 I2C;I2C 设备一定能接 SMBus。
更稳妥的判断方式是:
看芯片手册;看 Linux 驱动已有实现;看控制器是否支持对应传输方式;看通信时序是否匹配。
7. 开发中怎么选择?
实际写驱动时,可以简单按这个原则来判断。
如果设备只是普通寄存器读写,比如:
读 1 字节寄存器;写 1 字节寄存器;读 2 字节状态值;写 2 字节配置值。
那可以优先考虑i2c_smbus_xxx()这类接口。比如:
ret= i2c_smbus_read_byte_data(client, reg);
如果设备通信流程比较复杂,比如:
一次传输多个 i2c_msg;需要 repeatedstart;需要读写大块数据;设备协议不是标准寄存器访问;需要精确控制传输过程。
那更适合直接使用:
i2c_transfer()
简单说就是:
简单寄存器访问:优先看 SMBus API;复杂 I2C 时序:使用 i2c_transfer()。最终依据:芯片手册定义的通信格式 + I2C adapter 支持的功能。
这也是 Linux 驱动里很常见的选择方式。
8. 工程上不要被名字绕晕
对刚入门 Linux I2C 驱动的人来说,SMBus 这个名字确实容易让人误解。
我一开始也容易想复杂:
这是另一套协议吗?是不是不能和 I2C 混用?为什么 I2C 驱动里全是 smbus 函数?
后面慢慢看驱动才发现,很多场景下可以先这样理解:SMBus 是 I2C 的标准化使用方式之一,而 Linux 里的 SMBus API 是一组常用 I2C 设备访问接口。
这样理解,基本就不会被名字卡住了。
当然,如果你做的是电源管理、电池管理、服务器管理类设备,那就需要更认真看 SMBus 规范和芯片手册,因为这些场景可能会用到 SMBus 的超时、PEC 校验、Block 传输等特性。
但如果只是普通嵌入式外设适配,先知道两者关系和 API 选择,基本就够用了。
9. 总结
I2C 和 SMBus 的关系可以这样理解:
I2C:通用两线制串行总线,灵活、应用广;
SMBus:基于 I2C 的系统管理总线,规则更标准,主要用于电源、温度、电池、硬件监控等场景;
Linux SMBus API:内核提供的一组便捷 I2C 访问接口,常用于简单寄存器读写。
开发中怎么选?
[ ]普通外设、特殊时序、大块数据传输:优先看 i2c_transfer()[ ]简单寄存器读写:可以优先用 i2c_smbus_xxx()[ ]电源管理、电池、温度监控类芯片:重点看芯片是否要求 SMBus 规范[ ]不确定时:先看芯片手册和已有内核驱动
一句话总结:
SMBus 不是 I2C 的对立面,而是基于 I2C 发展出来的标准化系统管理总线;在 Linux 驱动里,很多 SMBus API 本质上就是为了方便访问常见 I2C 外设。
理解到这一层,再看到i2c_smbus_read_byte_data()这类函数,就不会懵了。
(完)
下期继续聊:I2C子系统架构是怎么的?
本人专注Linux 嵌入式全栈开发,可提供从硬件方案评估与设计、Linux/AndroidBSP 适配、驱动开发、外设调试、系统移植到产品交付的全流程技术支持。
-
嵌入式
+关注
关注
5213文章
20855浏览量
339522 -
Linux
+关注
关注
88文章
11888浏览量
220163 -
I2C协议
+关注
关注
0文章
30浏览量
9375 -
SMBus协议
+关注
关注
0文章
4浏览量
1408
发布评论请先 登录
I2C总线协议及其应用
STM32学习之I2C协议(读写EEPROM)
嵌入式内核及驱动开发-09IIC子系统框架使用(I2C协议和时序,I2C驱动框架,I2C从设备驱动开发,MPU6050硬件连接
一文看懂I2C协议
I2C通信协议:了解I2C Primer、 PMBus和SMBus
使用I2C协议点亮OLED
驱动之路#42:I2C协议与SMBus协议是什么关系?
评论