I2C/SMBus 配置及使用说明
概述
I2C/SMBus 功能支持通过主从切换方式访问硬件设备。当硬件设备需要通过 I2C 总线以 SMBus 协议进行通信,且需要 BMC 作为从设备(Slave)响应时,可使用此功能。本文档介绍如何在 SR 配置中启用 I2C/SMBus 功能,以及如何使用相关接口进行设备读写操作。
重要提示:硬件需要支持使用 I2C/SMBus 主从切换方式进行访问请求,否则读写硬件会产生报错。
使用场景
I2C/SMBus 主从切换功能适用于以下场景:
- 硬件设备需要通过 SMBus 协议与 BMC 进行双向通信
- BMC 需要作为从设备响应外部主设备的访问请求
- 需要实现 SMBus over I2C 的通信方式
SR 配置
I2C/SMBus 功能启用需要在 SR 配置中指定总线的从地址,因此需要确认器件位于哪路 I2C 总线上。
配置位置
I2C 总线配置位于 SR 文件的 Objects 部分,与 I2C 总线对象一起配置。配置的 SR 文件通常位于板卡对应的 CSR 目录下,例如 root.sr 或扩展板卡的 SR 文件。
配置示例
以 I2c_9 为例,在 SR 文件的 Objects 部分添加如下配置:
{
"Objects": {
"I2c_9": {
"Id": 9,
"SlaveAddr": 32
}
}
}配置说明
| 字段名 | 类型 | 说明 |
|---|---|---|
Id | U8 | I2C 总线 ID,必须与总线对象名称中的数字一致 |
SlaveAddr | U8 | I2C/SMBus 切换到从模式的地址,JSON 配置为十进制格式 |
配置要点:
- SlaveAddr 的确定:
SlaveAddr是 BMC 作为从设备时的 I2C 地址,通常由硬件设计确定。需要查阅硬件原理图或硬件规格书获取该地址值。 - 地址格式:配置时使用十进制格式,例如地址
0x20应配置为32。 - 唯一性:同一 I2C 总线上不能有地址冲突,确保
SlaveAddr与总线上其他设备的地址不冲突。
注意事项:SlaveAddr 配置必须正确,否则使用接口会出现异常。
I2C/SMBus 读写接口及示例
I2C/SMBus 读写接口为器件的 bmc.kepler.Chip.BlockIO,方法名为 WriteReadByProtocol。该接口支持通过指定协议类型进行设备读写操作。
接口说明
WriteReadByProtocol
通过指定物理介质和协议的方式对设备进行写入和读取访问。
接口路径:/bmc/kepler/Chip/<Chip对象名>
接口名称:bmc.kepler.Chip.BlockIO
方法名:WriteReadByProtocol
参数
| 参数名 | 类型 | 说明 |
|---|---|---|
InData | U8[] | 写入的数据内容,字节数组格式 |
ReadLength | U32 | 读取的数据长度(字节数) |
Protocol | U8 | 物理介质和协议类型,当前仅支持 0x02(SMBus/I2C) |
返回值
| 返回值名 | 类型 | 说明 |
|---|---|---|
OutData | U8[] | 读取的数据内容,字节数组格式 |
使用示例
示例 1:通过 busctl 命令调用接口
假设需要访问的 Chip 对象名为 Chip_Example_0101,执行 SMBus 读写操作:
写入并读取数据:
# 写入数据 [0x01, 0x02, 0x03],读取 4 字节数据
busctl --user call bmc.kepler.hwproxy \
/bmc/kepler/Chip/Complex/Chip_Example_0101 \
bmc.kepler.Chip.BlockIO \
WriteReadByProtocol \
a{ss}ayuy 0 3 0x01 0x02 0x03 4 0x02参数说明:
a{ss}ayuy:D-Bus 类型签名a{ss}:字典类型(第一个参数,通常为 0)ay:字节数组(InData)u:无符号整数(ReadLength)y:无符号整数(Protocol)
0:字典参数(通常为 0)3:InData 数组长度0x01 0x02 0x03:InData 数据内容4:ReadLength,读取 4 字节0x02:Protocol 参数,表示 SMBus/I2C
返回示例:
ay 4 0x10 0x20 0x30 0x40表示读取到 4 字节数据:[0x10, 0x20, 0x30, 0x40]
示例 2:在代码中调用接口
在 Lua 代码中调用接口的示例:
local client = require 'your_component.client'
local context = require 'mc.context'
-- 获取 Chip 对象
local chip_obj = client:GetChipChipObject("Chip_Example_0101")
if not chip_obj then
log:error("Failed to get chip object")
return
end
-- 准备写入数据
local in_data = {0x01, 0x02, 0x03}
local read_length = 4
local protocol = 0x02 -- SMBus/I2C
-- 调用接口
local ok, result = pcall(function()
return chip_obj:WriteReadByProtocol_PACKED(
context.new(),
in_data,
read_length,
protocol
):unpack()
end)
if ok and result then
log:notice("Read data: %s", table.concat(result, ", "))
else
log:error("WriteReadByProtocol failed: %s", result)
end查找 Chip 对象路径
在使用接口前,需要确定 Chip 对象在资源树中的完整路径。可通过以下方式查找:
查看资源树结构:
bashbusctl --user tree bmc.kepler.hwproxy查找特定 Chip 对象:
bashbusctl --user tree bmc.kepler.hwproxy | grep -i "chip"查看 Chip 对象详细信息:
bashbusctl --user introspect bmc.kepler.hwproxy /bmc/kepler/Chip/Complex/Chip_Example_0101
常见问题
1. 接口调用失败,返回错误
可能原因:
SlaveAddr配置不正确- 硬件不支持主从切换功能
- I2C 总线未正确初始化
- Chip 对象路径不正确
解决方法:
- 检查 SR 配置中的
SlaveAddr是否正确 - 确认硬件是否支持 I2C/SMBus 主从切换
- 检查 I2C 总线对象是否已正确加载
- 验证 Chip 对象路径是否正确
2. 读取数据为空或异常
可能原因:
ReadLength参数设置过大或过小- 写入的
InData不符合设备协议要求 - 设备未响应或通信异常
解决方法:
- 根据设备规格调整
ReadLength参数 - 检查
InData是否符合 SMBus 协议格式 - 使用示波器或逻辑分析仪检查 I2C 总线信号
3. 配置后接口仍不可用
可能原因:
- SR 文件未正确加载
- 配置位置不正确
解决方法:
- 检查 SR 文件是否在正确的目录下
- 确认配置格式是否正确(JSON 格式)
注意事项
- 硬件兼容性:使用前需确认硬件支持 I2C/SMBus 主从切换功能
- 地址冲突:确保
SlaveAddr与总线上其他设备地址不冲突 - 协议格式:
InData需要符合 SMBus 协议的数据格式要求 - 错误处理:建议在代码中添加错误处理和重试机制