瑞芯微RK3568芯片是一款定位中高端的通用型SOC,采用22nm制程工艺,搭载一颗四核Cortex-A55处理器和Mali G52 2EE 图形处理器。RK3568 支持4K 解码和 1080P 编码,支持SATA/PCIE/USB3.0 外围接口。RK3568内置独立NPU,可用于轻量级人工智能应用。RK3568 支持安卓 11 和 linux 系统,主要面向物联网网关、NVR 存储、工控平板、工业检测、工控盒、卡拉 OK、云终端、车载中控等行业。
【公众号】迅为电子
【粉丝群】258811263(加群获取驱动文档+例程)
【视频观看】嵌入式学习之Linux驱动(第十五篇 I2C_全新升级)_基于RK3568
【购买链接】迅为RK3568开发板瑞芯微Linux安卓鸿蒙ARM核心板人工智能AI主板
第183章 SMBus总线介绍
183.1 什么是SMBus总线?
SMBus(System Management Bus)是由Intel在1995年发布的一种基于I2C总线的串行总线协议。它最初被设计用于在电脑系统内部连接智能电池和其他系统管理设备。
SMBus与I2C总线非常相似,它们都采用两线式串行通信。SMBus使用SMBDAT和SMBCLK作为数据线和时钟线,与I2C的SDA和SCL很相似,如下图所示:
SMBus的主要特点如下所示:
电气特性:
(1)采用开漏输出,需要外部上拉电阻
(2)电压范围:0V到5.5V
(3)最大时钟频率:100kHz
通信协议:
(1)主从式通信,一个主设备控制多个从设备
(2)地址空间:7位或10位
(3)支持读/写操作
(4)支持块传输和字节传输
(5)支持多种事务类型,如快速命令、写字节、读字节等
功能特性:
(1)简单、低成本、低功耗
(2)面向系统管理应用,如电源管理、温度监控等
(3)与I2C高度兼容,可以复用I2C硬件
时序特性:
(1)Start和Stop条件与I2C相同
(2)地址和数据传输时序也与I2C相似
(3)但有一些特殊的时序,如快速命令、块传输等
183.2 SMBus和I2C的区别
(1)速度范围:
I2C支持从10kHz到3.4MHz不等的速度范围,覆盖了更广泛的应用场景。
SMBus则只支持10kHz到100kHz的速度范围,主要面向低速的系统管理应用场景。
(2)ACK应答:
I2C不强制从机发送ACK应答,这样可以提高灵活性。但如果从机没有应答,主机可能会产生错误。
SMBus要求从机必须发送ACK应答,这可以确保主机能够检测到从机是否存在,避免误操作。
(3)时间限制:
SMBus规定,从机不能将SCL线拉低超过35ms,否则会复位正在进行的通信。
I2C没有这样的时间限制,主机和从机可以自主控制SCL线的状态。
(4)其他区别:
SMBus有一些专门为系统管理设计的命令和事务类型,如快速命令、块传输等。
SMBus的地址空间相比I2C更小,只支持7位或10位地址。
SMBus在电气特性上也有一些差异,如电压范围等。
183.3 SMBus总线软件实现
在Linux内核中,I2C和SMBus是共用的总线架构,通过i2c-core子系统进行管理和抽象,在i2c.h头文件中定义了i2c_algorithm结构体中,具体内容如下所示:
struct i2c_algorithm {
/* 如果 I2C 适配器算法无法执行 I2C 级别的访问,则应将 master_xfer 设置为 NULL。
如果 I2C 适配器算法可以执行 SMBus 访问,则应设置 smbus_xfer。
如果设置为 NULL,则将使用通用的 I2C 消息来模拟 SMBus 协议 */
/* master_xfer 函数应该返回成功处理的消息数量,或者在出现错误时返回一个负值 */
int (*master_xfer)(struct i2c_adapter *adap, struct i2c_msg *msgs,
int num);
/* 用于执行 SMBus 传输操作的函数指针
adap: I2C 适配器
addr: 从设备地址
flags: 传输标志
read_write: 读/写标志
command: SMBus 命令码
size: 传输数据的大小
data: 用于存储传输数据的联合体 */
int (*smbus_xfer) (struct i2c_adapter *adap, u16 addr,
unsigned short flags, char read_write,
u8 command, int size, union i2c_smbus_data *data);
/* 用于确定适配器支持的功能的函数指针 */
u32 (*functionality) (struct i2c_adapter *);
#if IS_ENABLED(CONFIG_I2C_SLAVE)
/* 用于注册和注销从设备的函数指针 */
int (*reg_slave)(struct i2c_client *client);
int (*unreg_slave)(struct i2c_client *client);
#endif
};
其中smbus_xfer函数用于实现SMBus特有的一些操作,如快速命令、写字节、读字节等。
当I2C控制器工作在SMBus模式时,会通过smbus_xfer函数来执行SMBus的特殊事务。
183.4 SMBus总线API函数
函数1:i2c_smbus_read_byte(const struct i2c_client *client)
函数原型: s32 i2c_smbus_read_byte(const struct i2c_client *client)
功能: 从当前位置读取一个字节的数据,不设置地址
参数: client - I2C设备的客户端结构体
返回值: 读取到的数据,失败返回负数
函数2:i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
函数原型: s32 i2c_smbus_write_byte(const struct i2c_client *client, u8 value)
功能: 向当前位置写入一个字节的数据,不设置地址
参数: client - I2C设备的客户端结构体, value - 要写入的数据
返回值: 成功返回0,失败返回负数
函数3:i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)
函数原型: s32 i2c_smbus_read_byte_data(const struct i2c_client *client, u8 command)
功能: 读取指定地址的一个字节的数据
参数: client - I2C设备的客户端结构体, command - 要读取的地址
返回值: 读取到的数据,失败返回负数
函数4:i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, u8 value)
函数原型: s32 i2c_smbus_write_byte_data(const struct i2c_client *client, u8 command, u8 value)
功能: 向指定地址写入一个字节的数据
参数: client - I2C设备的客户端结构体, command - 要写入的地址, value - 要写入的数据
返回值: 成功返回0,失败返回负数
上述4个函数是smbus总线通信的常用数据接收和发送函数,而在前面的章节中已经编写了I2C总线的通信驱动,如果要使用smbus总线进行通信,只需要将前面编写的驱动函数中的i2c_transfer函数根据功能替换为上面四个函数即可。