如何通过设备树手动进行i2c通信

问题描述

最近在适配景嘉微JY1032 GPU,带外通过i2c进行通信,通信分为block write和block read,具体如下:
发送请求:


读取信息:

我尝试调用设备树的write和read方法进行通信,但是通信失败

image

Chip对象配置如下:

        "Chip_McuChip": {
            "Address": 102,
            "AddrWidth": 1,
            "OffsetWidth": 1,
            "WriteTmout": 100,
            "ReadTmout": 100,
            "HealthStatus": 0
        },

请问如何正确使用设备树方法进行i2c通信

环境信息

  • 操作系统:Kylin v2403

  • 软件版本:2512

  • 硬件配置:

期望结果

通信正常

实际结果

通信失败

答案内容由AI生成,仅供参考:

总结建议

  1. 放弃 WriteRead 方法:对于景嘉微JY1032这类需要发送完整协议帧的复杂设备,必须使用 ComboWriteRead 方法
  2. 正确构造发送数据:将 Block Write 协议的整个帧(Command Code + Byte Count + Request Data)作为 ComboWriteRead 的写入参数。
  3. 确保Chip对象配置正确Address 配置已正确(左移后为0x66),但 AddrWidthOffsetWidth 应设为1以适配底层协议处理。
  4. 排查底层Hisport驱动错误:错误码320表明Hisport驱动层面出现问题,需要进一步检查Hisport总线状态和相关日志。
点击此处查看详细分析解答

您好,根据您提供的问题描述和上下文信息,我来分析如何正确使用设备树方法进行I2C通信,并解释当前通信失败的可能原因。

问题原因分析

您遇到的通信失败,主要源于协议栈与底层通信接口不匹配

  1. 协议帧格式不匹配:景嘉微JY1032 GPU的通信协议是自定义的Block Write/Read协议。其请求帧结构为 [Command Code] [Byte Count] [Request Data Structure...],其中Request Data Structure内部包含了 LUN, arg, opcode, offset, length, data 等特定字段。您直接调用 bmc.kepler.Chip.BlockIOWrite 方法,该方法通常期望发送的数据格式是 [offset] [data...](偏移量+数据),这与您GPU要求的复杂请求帧结构不一致。
  2. 底层通信方法选择错误:您使用的 busctl call ... WriteRead 是独立的读写操作,适合简单的寄存器访问。对于需要先写入完整请求帧再读取完整响应帧的复合操作,应使用 ComboWriteRead 方法,该方法在一个事务中完成写和读,能更好地处理您这种自定义协议。
  3. Chip对象配置可能不准确:您配置的 Chip_McuChip 中,Address102(0x66),AddrWidthOffsetWidth 均为 1。但您的协议要求发送 Command CodeByte Count 等,这超过了简单的1字节偏移量寻址,可能需要底层驱动支持SMBus Block协议。
  4. 底层Hisport驱动错误:错误日志 ioctl(HISPORT_CMD_READ) failed: Unknown error 320 表明,在最后尝试通过Hisport硬件驱动读取数据时失败。这可能是由上述的协议帧格式错误、总线堵塞、或该Hisport总线/设备本身存在问题导致的。

正确使用设备树方法进行I2C通信的步骤

1. 检查并修正Chip对象配置

您的CSR配置需要根据实际协议进行调整。考虑到协议需要发送 Command CodeByte Count强烈建议AddrWidthOffsetWidth 设置为支持Block协议的值。

根据OpenUBMC的常见实践和I2C/SMBus配置说明,正确的配置方式应为:

  • Address:设备的7位I2C地址。根据您提供的信息,地址是0x66(十进制102)。
  • AddrWidthOffsetWidth:对于需要发送自定义命令码的Block协议,OffsetWidth 应设置为适合发送整个请求帧的大小,或使用更高级的接口。在您的场景中,建议改为如下配置,以使底层能够正确处理Block Write/Read:
"Chip_McuChip": {
    "Address": 102,
    "AddrWidth": 1,
    "OffsetWidth": 1,  // 注意:对于复杂协议,OffsetWidth=1可能不足以描述所有场景,可能需要调整或使用特定方法
    "WriteTmout": 100,
    "ReadTmout": 100,
    "HealthStatus": 0
}

重要说明:仅仅将 OffsetWidth 设为 1 并无法自动实现您所需的 [Command Code] [Byte Count] [Data...] 协议格式。底层 bmc.kepler.Chip.BlockIOWrite/Read 方法主要负责发送一个偏移量(offset)和一段数据,而不是复杂的自定义协议帧。

2. 使用正确的D-Bus接口和方法

对于景嘉微JY1032这种自定义的Block Write/Read协议,您应该使用 ComboWriteRead 方法

ComboWriteRead 方法允许您在一个调用中构造完整的发送数据并接收完整的回复帧,是处理自定义I2C协议的正确方式。

接口说明

  • Servicebmc.kepler.hwproxy
  • Object Path/bmc/kepler/Chip/Complex/Chip_McuChip_0101010902
  • Interfacebmc.kepler.Chip.BlockIO
  • MethodComboWriteRead
  • Method Signature (D-Bus类型): 通常为 (ayay),即两个字节数组:发送数据数组接收缓冲区长度
  • 返回值:通常是一个字节数组 ay,即 接收数据数组

使用 busctl 命令的调用示例

根据您的协议,一个Block Write请求的原始字节流应为:
[Command Code=0x20] [Byte Count=13] [Request Data Structure (13 bytes)]

那么,您需要将整个请求帧(包括Command Code)作为 ComboWriteRead 的写入数据参数传入。ComboWriteRead 方法会将这些数据原封不动地通过I2C总线发送出去,然后接收指定长度的回复。

构造发送数据(一个完整的Block Write帧):

  • Command Code: 0x20
  • Byte Count: 0x0D (十进制13, 表示后面有13个字节的数据帧)
  • Request Data Structure:
    • Byte 1 (LUN): 0x01 (第一帧)
    • Byte 2 (arg): 0x00 (示例)
    • Byte 3-4 (opcode): 0x00 0x03 (示例: 假设opcode为3)
    • Byte 5-8 (offset): 0x00 0x00 0x00 0x00 (示例: 从0开始)
    • Byte 9-12 (length): 0x00 0x00 0x00 0x20 (示例: 读取32字节)
    • Byte 13 (data): 0x00 (示例)

完整的发送数据(ay)
[0x20, 0x0D, 0x01, 0x00, 0x00, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x20, 0x00]

命令示例

busctl --user call bmc.kepler.hwproxy /bmc/kepler/Chip/Complex/Chip_McuChip_0101010902 bmc.kepler.Chip.BlockIO ComboWriteRead ayay 15 0x20 0x0D 0x01 0x00 0x00 0x03 0x00 0x00 0x00 0x00 0x00 0x00 0x00 0x20 0x00 32

命令参数解释

  • 15:发送的字节数组的长度。
  • 0x20 0x0D ... 0x00:完整的发送数据帧。
  • 32:期望接收的缓冲区长度(这里设为32,与M值一致)。

如果调用成功,您将收到一个字节数组 (ay),其内容即为GPU返回的 Read Response 帧,您可以按照协议解析其中的 error_code, opcode, total_length, length, data 等字段。

3. 检查Hisport驱动和总线状态

底层Hisport驱动返回错误320,表明在硬件层面通信已经失败。

  • 检查Hisport状态:确认Hisport总线Hisport_12是否正常工作,是否被其他任务占用。
  • 验证I2C地址:确认您的GPU设备的7位I2C地址确实是0x66。根据OpenUBMC的I2C地址配置规则,如果硬件使用7位地址,但在CSR中配置时,需要将7位地址左移一位(配置8位地址)。例如,设备7位地址为0x33,则应配置为0x66。您当前配置的Address: 1020x66已经正确执行了左移操作,因此地址配置没问题。
  • 硬件连接:确认Hisport总线与GPU设备之间的物理连接和电气特性是正常的。

总结建议

  1. 放弃 WriteRead 方法:对于景嘉微JY1032这类需要发送完整协议帧的复杂设备,必须使用 ComboWriteRead 方法
  2. 正确构造发送数据:将 Block Write 协议的整个帧(Command Code + Byte Count + Request Data)作为 ComboWriteRead 的写入参数。
  3. 确保Chip对象配置正确Address 配置已正确(左移后为0x66),但 AddrWidthOffsetWidth 应设为1以适配底层协议处理。
  4. 排查底层Hisport驱动错误:错误码320表明Hisport驱动层面出现问题,需要进一步检查Hisport总线状态和相关日志。