PCA9545通道切换方法求助

目前在调试板卡,板子上有一个PCA9545。现在需要切换PCA9545,使用mdbctl call I2c_6 bmc.kepler.Bus.BlockIO Write方式切换没有效果,bus_tool中的i2ctransfer配置又会报错,请问有其他方式进行通道选择,然后通过i2cdetect扫描PCA9545指定通道下挂载的器件地址吗?

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

:white_check_mark: 总结:推荐操作步骤

步骤 操作
1 使用 i2cdetect -y 6 确认 PCA9545 地址为 0x70
2 使用 i2ctransfer 写入控制字切换通道(如 0x08
3 再次 i2cdetect 扫描,确认目标设备出现在总线上
4 若成功,说明硬件正常;若失败,检查硬件连接与电源
5 长期方案:完善 CSR 配置,确保 I2cMux 正确挂载在 Pca9545
6 使用 bmc.kepler.Bus.BlockIO.Write 时,确保传入合法 JSON 参数

如仍存在问题,请收集 BMC 一键日志 并联系 PAE 或开发专家进一步分析。

点击此处查看详细分析解答

PCA9545通道切换方法解析与调试指南

针对您在调试过程中遇到的 PCA9545 通道切换问题,以下基于系统架构和已知信息,提供完整的解决方案和建议。


:wrench: 一、PCA9545 通道切换原理

1. 硬件机制

  • PCA9545 是一款 4 通道 I²C 多路复用器(I2C Mux),通过向其控制寄存器写入一个字节数据(通常是 0x01 ~ 0x08)来选择激活其中一个通道(Channel 0 ~ 3)。
  • 每个通道连接不同的 I²C 从设备(如 EEPROM、温度传感器等),实现 I²C 总线扩展。

2. 总线拓扑关系

根据上下文:

  • PCA9545 挂载在某个 I²C 主总线下(例如 I2C_6I2C_2)。
  • 它扩展出多个子通道,例如:
    • I2cMux_pca9545_i2c6_chan1 → 对应 Channel 1
    • I2cMux_9545Chan3 → 对应 Channel 3(用于连接 Pca9555_IEUChip_MCU

:white_check_mark: 要访问特定通道下的设备,必须先切换到对应通道,再执行后续读写操作。


:hammer_and_wrench: 二、正确切换 PCA9545 通道的方法

方法一:使用 i2ctransfer 工具(推荐调试用)

这是最底层、直接对接硬件的方式,常用于验证设备连接。

示例命令(切换到 Channel 3)

i2ctransfer -f -y 6 w2@0x70 0x08 0x08
  • -f:强制访问(忽略警告)
  • -y:自动确认
  • 6:I2C 总线编号(即 I2C_6
  • w2:写 2 个字节
  • @0x70:PCA9545 的 I2C 地址(需确认实际地址是否为此值)
  • 0x08:第一个字节是寄存器地址(一般为 0,可省略或设为 0)
  • 第二个 0x08:要写入的数据,表示启用 Channel 3(bit3=1)

:light_bulb: 注意:

  • 如果控制寄存器地址不为 0,需调整第一个数据字节。
  • 常见的通道选择码:
    • Channel 0 → 0x01
    • Channel 1 → 0x02
    • Channel 2 → 0x04
    • Channel 3 → 0x08

切换后扫描设备

i2cdetect -y 6

此时应能看到该通道下挂载的设备(如 0x20Pca9555_IEU)。

:warning: 说明:i2cdetect 是通过 busybox 提供的工具,可在 BMC 上运行检测。


方法二:通过 D-Bus 接口调用 bmc.kepler.Bus.BlockIO

您提到使用如下命令无效:

mdbctl call I2c_6 bmc.kepler.Bus.BlockIO Write ...

:white_check_mark: 正确用法示例

bmc.kepler.Bus.BlockIO.Write 接口的参数应为结构化输入(JSON 或二进制),而非随意传参。

参考格式如下:

mdbctl call I2c_6 bmc.kepler.Bus.BlockIO Write \
  '{
    "name": "Pca9545",
    "addr": 0x70,
    "addrWidth": 1,
    "offset": 0,
    "offsetWidth": 1,
    "data": [0x08],
    "len": 1
  }'
  • addr: PCA9545 的实际 I2C 地址(需确认)
  • offset: 控制寄存器地址(通常为 0)
  • data: 要写入的通道选择值(如 0x08 表示 Channel 3)

:pushpin: 错误提示报错可能原因:

  • 参数格式错误(非 JSON 结构)
  • addroffset 位宽设置错误(addrWidth 应为 1 字节)
  • 没有权限或服务未启动(确保 bmc.kepler.hwproxy 正常运行)

方法三:使用 mdbctl 直接操作 Chip 对象(高级方式)

如果 PCA9545 已注册为 D-Bus 上的 Chip 对象(例如 Chip_I2c_0101010302),可通过更高级接口访问:

mdbctl call Chip_I2c_0101010302 bmc.kepler.Chip.BlockIO Write 0 0x70 0 1 8

参考命令:mdbctl call Chip_I2c_0101010302 bmc.kepler.Chip.BlockIO Read 0 0 512
表明该接口支持块读取,也可用于写入控制寄存器。


:pushpin: 三、定位 i2ctransfer 报错原因

常见错误及解决方法:

错误现象 可能原因 解决方案
Error: Transaction failed I2C 地址错误或设备未响应 使用 i2cdetect -l 查看总线,i2cdetect -y 6 扫描设备是否存在 0x70
Invalid argument 参数格式错误 确保命令格式为 wN@addr data...
无法写入寄存器 寄存器地址不对 检查 PCA9545 手册,是否需要先写寄存器地址再写数据
切换后无设备响应 电源未上电或硬件故障 检查目标通道设备供电状态

:white_check_mark: 四、完整调试流程建议

# 1. 确认 I2C 总线存在
i2cdetect -l

# 2. 扫描 I2C_6 上所有设备(切换前)
i2cdetect -y 6

# 3. 切换 PCA9545 到 Channel 3
i2ctransfer -f -y 6 w2@0x70 0x00 0x08

# 4. 再次扫描,查看目标设备是否出现
i2cdetect -y 6

# 5. 若目标设备在地址 0x20,读取其数据验证
i2ctransfer -f -y 6 r2@0x20

:repeat_button: 注意:每次切换通道后,需重新扫描才能看到新通道的设备。


:puzzle_piece: 五、CSR 配置注意事项(长期解决方案)

如果您希望 BMC 自动管理通道切换,应在 CSR(Configuration and Status Register) 中正确定义:

  1. 定义 PCA9545 设备对象

    {
      "Pca9545": {
        "Address": 0x70,
        "AddrWidth": 1,
        "OffsetWidth": 1,
        "WriteTmout": 100,
        "ReadTmout": 100
      }
    }
    
  2. 配置 I2cMux 通道对象(如下属通道):

    • I2cMux_9545Chan3 必须声明属于 Pca9545
    • 使用 ChannelId 明确指定通道编号(0~3
  3. 总线层级结构正确

    • 根据文档要求:I2cMux 必须挂载在 Pca9545
    • 避免重复挂载或跨节点引用

参考文档:CSR配置字典之ManagementTopology 明确指出:

  • Chip(如 Pca9545)可以扩展出新的总线
  • I2cMux 对象必须放在 Pca9545 下

:red_exclamation_mark: 六、其他注意事项

  1. 最大通道数限制

    • BMC 不支持超过 8 个通道的复用器
    • 若尝试配置 ChannelId > 7,系统会在切换时抛错(见社区问答记录)。
    • PCA9545 仅支持 4 通道,无需担心此问题。
  2. 仿真环境差异

    • 在 QEMU 仿真环境中,PCA9545 可能被 CPLD 模拟,协议交互需一致。
    • 如论坛提问所述:“BMC 如何实现超过 8 路切换”?→ 当前 BMC 不支持 >8
  3. 自动发现失败原因

    • 若 BMC 重启后无法识别多通道设备,可能是:
      • CSR 配置路径错误(应将 I2cMux_* 放在 EXU 层级而非 SEU)
      • 缺少 Scanner 对象周期性探测设备

:white_check_mark: 总结:推荐操作步骤

步骤 操作
1 使用 i2cdetect -y 6 确认 PCA9545 地址为 0x70
2 使用 i2ctransfer 写入控制字切换通道(如 0x08
3 再次 i2cdetect 扫描,确认目标设备出现在总线上
4 若成功,说明硬件正常;若失败,检查硬件连接与电源
5 长期方案:完善 CSR 配置,确保 I2cMux 正确挂载在 Pca9545
6 使用 bmc.kepler.Bus.BlockIO.Write 时,确保传入合法 JSON 参数

如仍存在问题,请收集 BMC 一键日志 并联系 PAE 或开发专家进一步分析。


:white_check_mark: 最终建议:优先使用 i2ctransfer 验证硬件连通性,成功后再排查 D-Bus 接口调用问题。

相关链接:

  1. 关于CPLD模拟PCA9545的一些问题
  2. NVMe盘适配遇到问题
  3. MCTP over SMBus主从切换情况下无法建立通信链路
  4. 总线测试方法:pca9545 channe和jtag
  5. CSR配置字典之I2cMux类 | 文档中心 | openUBMC

1、使用i2ctransfer 6 w1@0x70 0x01切换到通道0
2、然后使用i2ctransfer 6 r1@0x70确认切换是否成功
3、使用i2cdetect 6扫描地址
4、再次使用i2ctransfer 6 r1@0x70确认通道是否被其他程序切换

我们这个工具同样的操作会报错。通过i2cdetect 6确实能扫描到0x70这个地址,但是使用i2ctransfer 6 r1@0x70会报错

popen result is empty or read error.
: Success
read data from i2c bus 6 address 0x70 failed.
Error: Sending messages failed: Success

不管读写都是同样的错误

这个工具只能在装备包或者debug包上面使用,上网包是不行的,另外需要telnet登录使用,不要用ssh

我用的就是debug包,通过busybox telnet到本地操作的

telnet登录后执行mdbctl call I2c_6 bmc.kepler.Bus.BlockIO Read 0 0xE1 1看看结果

找不到mdbctl命令

他的抛错是什么,可以截图看看吗?是mdbctl没有还是mdbctl命令执行失败?

telnet进去后mdbctl会显示找不到命令。busctl可以用,但是不能设置为–user,否则也会报错

/bin/bash: mdbctl: not found

busctl --user list错误

Failed to set bus address: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined (consider using --machine=<user>@.host --user to connect to bus of other user)

mdbctl命令执行的问题需要先执行source /etc/profile

用这个可以正常使用

现在可以了,感谢