I2C/SMBus 配置及使用说明
更新时间: 2026/01/13
在Gitcode上查看源码

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 部分添加如下配置:

json
{
    "Objects": {
        "I2c_9": {
            "Id": 9,
            "SlaveAddr": 32
        }
    }
}

配置说明

字段名类型说明
IdU8I2C 总线 ID,必须与总线对象名称中的数字一致
SlaveAddrU8I2C/SMBus 切换到从模式的地址,JSON 配置为十进制格式

配置要点

  1. SlaveAddr 的确定SlaveAddr 是 BMC 作为从设备时的 I2C 地址,通常由硬件设计确定。需要查阅硬件原理图或硬件规格书获取该地址值。
  2. 地址格式:配置时使用十进制格式,例如地址 0x20 应配置为 32
  3. 唯一性:同一 I2C 总线上不能有地址冲突,确保 SlaveAddr 与总线上其他设备的地址不冲突。

注意事项SlaveAddr 配置必须正确,否则使用接口会出现异常。

I2C/SMBus 读写接口及示例

I2C/SMBus 读写接口为器件的 bmc.kepler.Chip.BlockIO,方法名为 WriteReadByProtocol。该接口支持通过指定协议类型进行设备读写操作。

接口说明

WriteReadByProtocol

通过指定物理介质和协议的方式对设备进行写入和读取访问。

接口路径/bmc/kepler/Chip/<Chip对象名>

接口名称bmc.kepler.Chip.BlockIO

方法名WriteReadByProtocol

参数

参数名类型说明
InDataU8[]写入的数据内容,字节数组格式
ReadLengthU32读取的数据长度(字节数)
ProtocolU8物理介质和协议类型,当前仅支持 0x02(SMBus/I2C)

返回值

返回值名类型说明
OutDataU8[]读取的数据内容,字节数组格式

使用示例

示例 1:通过 busctl 命令调用接口

假设需要访问的 Chip 对象名为 Chip_Example_0101,执行 SMBus 读写操作:

写入并读取数据

bash
# 写入数据 [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

返回示例

bash
ay 4 0x10 0x20 0x30 0x40

表示读取到 4 字节数据:[0x10, 0x20, 0x30, 0x40]

示例 2:在代码中调用接口

在 Lua 代码中调用接口的示例:

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 对象在资源树中的完整路径。可通过以下方式查找:

  1. 查看资源树结构

    bash
    busctl --user tree bmc.kepler.hwproxy
  2. 查找特定 Chip 对象

    bash
    busctl --user tree bmc.kepler.hwproxy | grep -i "chip"
  3. 查看 Chip 对象详细信息

    bash
    busctl --user introspect bmc.kepler.hwproxy /bmc/kepler/Chip/Complex/Chip_Example_0101

常见问题

1. 接口调用失败,返回错误

可能原因

  • SlaveAddr 配置不正确
  • 硬件不支持主从切换功能
  • I2C 总线未正确初始化
  • Chip 对象路径不正确

解决方法

  1. 检查 SR 配置中的 SlaveAddr 是否正确
  2. 确认硬件是否支持 I2C/SMBus 主从切换
  3. 检查 I2C 总线对象是否已正确加载
  4. 验证 Chip 对象路径是否正确

2. 读取数据为空或异常

可能原因

  • ReadLength 参数设置过大或过小
  • 写入的 InData 不符合设备协议要求
  • 设备未响应或通信异常

解决方法

  1. 根据设备规格调整 ReadLength 参数
  2. 检查 InData 是否符合 SMBus 协议格式
  3. 使用示波器或逻辑分析仪检查 I2C 总线信号

3. 配置后接口仍不可用

可能原因

  • SR 文件未正确加载
  • 配置位置不正确

解决方法

  1. 检查 SR 文件是否在正确的目录下
  2. 确认配置格式是否正确(JSON 格式)

注意事项

  1. 硬件兼容性:使用前需确认硬件支持 I2C/SMBus 主从切换功能
  2. 地址冲突:确保 SlaveAddr 与总线上其他设备地址不冲突
  3. 协议格式InData 需要符合 SMBus 协议的数据格式要求
  4. 错误处理:建议在代码中添加错误处理和重试机制