目前在调试板卡,板子上有一个PCA9545。现在需要切换PCA9545,使用mdbctl call I2c_6 bmc.kepler.Bus.BlockIO Write方式切换没有效果,bus_tool中的i2ctransfer配置又会报错,请问有其他方式进行通道选择,然后通过i2cdetect扫描PCA9545指定通道下挂载的器件地址吗?
答案内容由AI生成,仅供参考:
总结:推荐操作步骤
| 步骤 | 操作 |
|---|---|
| 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 通道切换问题,以下基于系统架构和已知信息,提供完整的解决方案和建议。
一、PCA9545 通道切换原理
1. 硬件机制
- PCA9545 是一款 4 通道 I²C 多路复用器(I2C Mux),通过向其控制寄存器写入一个字节数据(通常是
0x01~0x08)来选择激活其中一个通道(Channel 0 ~ 3)。 - 每个通道连接不同的 I²C 从设备(如 EEPROM、温度传感器等),实现 I²C 总线扩展。
2. 总线拓扑关系
根据上下文:
PCA9545挂载在某个 I²C 主总线下(例如I2C_6或I2C_2)。- 它扩展出多个子通道,例如:
I2cMux_pca9545_i2c6_chan1→ 对应 Channel 1I2cMux_9545Chan3→ 对应 Channel 3(用于连接Pca9555_IEU和Chip_MCU)
要访问特定通道下的设备,必须先切换到对应通道,再执行后续读写操作。
二、正确切换 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)
注意:
- 如果控制寄存器地址不为 0,需调整第一个数据字节。
- 常见的通道选择码:
- Channel 0 →
0x01- Channel 1 →
0x02- Channel 2 →
0x04- Channel 3 →
0x08
切换后扫描设备
i2cdetect -y 6
此时应能看到该通道下挂载的设备(如 0x20 的 Pca9555_IEU)。
说明:
i2cdetect是通过busybox提供的工具,可在 BMC 上运行检测。
方法二:通过 D-Bus 接口调用 bmc.kepler.Bus.BlockIO
您提到使用如下命令无效:
mdbctl call I2c_6 bmc.kepler.Bus.BlockIO Write ...
正确用法示例
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)
错误提示报错可能原因:
- 参数格式错误(非 JSON 结构)
addr或offset位宽设置错误(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
表明该接口支持块读取,也可用于写入控制寄存器。
三、定位 i2ctransfer 报错原因
常见错误及解决方法:
| 错误现象 | 可能原因 | 解决方案 |
|---|---|---|
Error: Transaction failed |
I2C 地址错误或设备未响应 | 使用 i2cdetect -l 查看总线,i2cdetect -y 6 扫描设备是否存在 0x70 |
Invalid argument |
参数格式错误 | 确保命令格式为 wN@addr data... |
| 无法写入寄存器 | 寄存器地址不对 | 检查 PCA9545 手册,是否需要先写寄存器地址再写数据 |
| 切换后无设备响应 | 电源未上电或硬件故障 | 检查目标通道设备供电状态 |
四、完整调试流程建议
# 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
注意:每次切换通道后,需重新扫描才能看到新通道的设备。
五、CSR 配置注意事项(长期解决方案)
如果您希望 BMC 自动管理通道切换,应在 CSR(Configuration and Status Register) 中正确定义:
-
定义 PCA9545 设备对象:
{ "Pca9545": { "Address": 0x70, "AddrWidth": 1, "OffsetWidth": 1, "WriteTmout": 100, "ReadTmout": 100 } } -
配置 I2cMux 通道对象(如下属通道):
I2cMux_9545Chan3必须声明属于Pca9545- 使用
ChannelId明确指定通道编号(0~3)
-
总线层级结构正确:
- 根据文档要求:
I2cMux必须挂载在Pca9545下 - 避免重复挂载或跨节点引用
- 根据文档要求:
参考文档:
CSR配置字典之ManagementTopology明确指出:
- Chip(如 Pca9545)可以扩展出新的总线
- I2cMux 对象必须放在 Pca9545 下
六、其他注意事项
-
最大通道数限制:
- BMC 不支持超过 8 个通道的复用器。
- 若尝试配置
ChannelId > 7,系统会在切换时抛错(见社区问答记录)。 - PCA9545 仅支持 4 通道,无需担心此问题。
-
仿真环境差异:
- 在 QEMU 仿真环境中,PCA9545 可能被 CPLD 模拟,协议交互需一致。
- 如论坛提问所述:“BMC 如何实现超过 8 路切换”?→ 当前 BMC 不支持 >8。
-
自动发现失败原因:
- 若 BMC 重启后无法识别多通道设备,可能是:
- CSR 配置路径错误(应将
I2cMux_*放在 EXU 层级而非 SEU) - 缺少
Scanner对象周期性探测设备
- CSR 配置路径错误(应将
- 若 BMC 重启后无法识别多通道设备,可能是:
总结:推荐操作步骤
| 步骤 | 操作 |
|---|---|
| 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 或开发专家进一步分析。
最终建议:优先使用 i2ctransfer 验证硬件连通性,成功后再排查 D-Bus 接口调用问题。
相关链接:
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
用这个可以正常使用
现在可以了,感谢
