【待评审】通过CPLD来切换I2C通道切换,虚拟I2CMux的功能

当前我们在适配硬盘背板+NVME盘,硬件拓扑如下:

        I2C11 –> PCA9545 ( chan2 ) –----写CPLD寄存器:值:1 切换---- > NVME0  (VPD地址0xA6)    
                                  –----写CPLD寄存器:值:2 切换---- > NVME1  (VPD地址0xA6)  
                                  ... ....
                                  –----写CPLD寄存器:值:3 切换---- > NVME7  (VPD地址0xA6)                           


OpenUBMC怎么配置sr文件,我当前参考这样配置不可以

   "Smc_BP_Switch": {
      "Buses": [
        "I2cMux_SMC_PCA1",
        "I2cMux_SMC_PCA2",
        "I2cMux_SMC_PCA3",
        "I2cMux_SMC_PCA4",
        "I2cMux_SMC_PCA5",
        "I2cMux_SMC_PCA6",
        "I2cMux_SMC_PCA7",
        "I2cMux_SMC_PCA8"
      ]
    },


手动拼接I2C命令,可以读VPD信息

/data # ./i2ctool64
==============================================================================
                                  i2ctool help
==============================================================================
1   read i2c     e.g. i2ctool 1 busid read_len cmd_data_len slave_addr
                 data1 data2 ...dataN (read_len<=32,cmd_data_len<=6)
2   write i2c    e.g. i2ctool 2 busid write_len slave_addr
                 data1 data2 ...dataN (write_len<=32)
==============================================================================
Uasge:i2ctool <option> <param...>




~ /data # ./i2ctool64 2 11 1 0xE0 0x02; ./i2ctool64 2 11 2 0x66 0x0C 0x02; ./i2ctool64 1 11 32 1 0xA6 0x00
********************************
     i2c read data is
********************************
0x01  0x00  0x00  0x00
0x01  0x0f  0x00  0xef
0x01  0x0e  0x19  0xc8
0x4a  0x44  0x20  0x43
0x6c  0x6f  0x75  0x64
0xd8  0x4a  0x36  0x35
0x31  0x31  0x00  0x00
0x00  0x00  0x00  0x00

  • 评审点:新增通过CPLD来切换I2C通道切换,虚拟I2CMux的功能

结论:考虑通过JtagSwitch/JtagMux实现
我如下配置:
“I2cMux_1”: {

“Chips”: [

"Lm75_BP",

"Eeprom_SEU",

"Chip_SEU_CPLD",

"JtagSwitch_BP_I2C_SW"

]

},
“JtagSwitch_BP_I2C_SW”: {
“Buses”: [

"JtagMux_JtagSwitch_BP_1",

"JtagMux_JtagSwitch_BP_2",

"JtagMux_JtagSwitch_BP_3",

"JtagMux_JtagSwitch_BP_4",

"JtagMux_JtagSwitch_BP_5",

"JtagMux_JtagSwitch_BP_6",

"JtagMux_JtagSwitch_BP_7",

"JtagMux_JtagSwitch_BP_8"

]

},
但是报错:感觉像是这条路锁死了,卡了30s,然后报错
~ ~ # mdbctl call Chip_Virtual_SSD_01010201 bmc.kepler.Chip.BlockIO Read 0 0x0 32
org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken

一键日志收集:
KunLunG6580V3_20260901-1646.tar.gz (9.3 MB)

从日志(LogDump\hw_stream.log/LogDump\framework.log)来看器件访问超时了,

2026-09-01 15:53:38.662334 hwproxy ERROR: hw_wait_access.lua(83): chip: block_read on the bus: Chip_Virtual_SSD_01010202 executed func_name:I2c_11 times out
2026-09-01 14:52:54.734664 storage ERROR: vpd_connector.lua(177): get header data failed from NVMe1, ret is BMC.Error.Unknow: ./opt/bmc/libmc/lualib/mc/context.lua:203: ./opt/bmc/libmc/lualib/sd_bus/object.lua:317: ./opt/bmc/apps/hwproxy/lualib/hwproxy_objects/app_bus.lua:104: ./opt/bmc/apps/hwproxy/lualib/hw_utils/hw_wait_access.lua:101: chip: Chip_Virtual_SSD_01010202, bus: I2c_11, read failed: i2c.lua:120: response error, i2c read fail, ret: 5, input:{"mask":4294967295,"len":8,"offsetWidth":1,"addrWidth":1,"has_error":false,"offset":0,"is_trace":false,"rw_type":1,"type":1,"name":"Chip_Virtual_SSD_01010202","requestor":"bmc.kepler.storage","addr":166,"bus_type":0}

1、确认下硬件拓扑是否符合预期(AppDump\hwproxy\topology.txt)

I2c_11
├─VChip_I2c_11
└─Pca9545_i2c11_chip_0101
  ├─Channel_0
  │ ├─Pca9545_i2c11_01010E
  │ │ ├─Channel_2
  │ │ │ └─Lm75_SWITCH_01010E
  │ │ └─Channel_3
  │ │   └─Eeprom_SWITCH_01010E
  │ ├─Chip_Bpcpld_01010E
  │ └─Chip_Upgrade_01010E
  └─Channel_1
    ├─JtagSwitch_BP_I2C_SW_010102
    │ └─Channel_2
    │   └─Chip_Virtual_SSD_01010202
    ├─Lm75_BP_010102
    ├─Eeprom_SEU_010102
    └─Chip_SEU_CPLD_010102

2、确认下JtagSwitch_BP_I2C_SW_010102切换是否正常(AppDump\hwdiscovery\Connector_SEU_1_0101.sr):可以通过访问Accessor_JtagSwitch_I2C_SW、Chip_SEU_CPLD判断

{
        "JtagSwitch_BP_I2C_SW": {
            "Accessor": "#/Accessor_JtagSwitch_I2C_SW"
        },
        "Accessor_JtagSwitch_I2C_SW": {
            "Chip": "#/Chip_SEU_CPLD",
            "Offset": 12,
            "Size": 1,
            "Mask": 255,
            "Type": 0,
            "Period": 2000,
            "Debounce": "None",
            "Value": 0
        },
        "Chip_SEU_CPLD": {
            "OffsetWidth": 1,
            "AddrWidth": 1,
            "Address": 102,
            "WriteTmout": 100,
            "ReadTmout": 100,
            "HealthStatus": 0
        }
}

3、如果上述都正常,确认硬件规格(包括且不限于I2c 11是否被用于I2c、是否存在抢占、通道切换的时延等)

用JtagSwitch切换I2C这个有成功实践案例吗

有的,已经有多个使用案例和场景了,如例会交流所述,这个机制可以作为通用机制使用。

我们日志里面有sr配置:AppDump\hwdiscovery\Connector_SEU_1_0101.sr

能看出来我们配置的有问题吗;

当前发现我一旦配JtagSwitch,这个sr里面原有的Chip也不能用了,不配置的时候还能用

例如读CPLD寄存器

~ # source /etc/profile
~ ~ # mdbctl call Chip_SEU_CPLD_010102  bmc.kepler.Chip.BlockIO Read 0 0x0 1

s  --- 一直在卡这

org.freedesktop.DBus.Error.NoReply: Did not receive a reply. Possible causes include: the remote application did not send a reply, the message bus security policy blocked the reply, the reply timeout expired, or the network connection was broken.

~ ~ #

正常是

~ /var/log # mdbctl call Chip_SEU_CPLD_010102 bmc.kepler.Chip.BlockIO Read 0 0x0 1
[42]

配置看不出异常,可以结合实际的硬件链路判断下是否匹配。
从访问Chip_SEU_CPLD异常来看,问题应该出现在这里,可以提供下执行这个操作的日志。

我想到一个点,找你确认一下,我如果通过I2C写了CPLD寄存器之后,是不是这条BMC→bus→I2C设备会被锁住;如果会被锁;那么我觉得可能是这样的:

JtagSwitch 在社区的既有案例(天池 BCU/EXU/SEU/CLU 的 Accessor_JtagSwitch → Smc_ExpBoardSMC,用于 CPLD 固件升级的 JTAG 路由切换)全部是切换 JTAG 链路,被切换资源与寄存器所在总线互不重叠;本板卡是首个用它切 I2C 且寄存器与被切总线同路(均为 I2c_11)的场景,导致访问权重入。那么需求就变了,应该是:新增同总线内联执行的 CPLD 寄存器值型虚拟 I2C Mux,而非复用 JtagSwitch 机制。

如果上面分析成立,或许可以另外一个方案进行验证,去切换的时候不写这个地址,换个地址写,或者换个协议,应该就不会锁死了,这个可以下一步计划测一下

当前硬件代理的总线服务是独立的,每个器件的访问都是串行独占总线,没有总线锁定的概念。针对当前场景,可能涉及的一个问题:Chip_SEU_CPLD无法访问,是发生在完成Chip_Virtual_SSD_01010202的访问之前,还是之后。

应该都有可能,取决于那个流程跑的快了;读CPLD有一些在位信息的Accessor,BMC起来就会扫描;Chip_Virtual_SSD_01010202是在检测是硬盘在位开始读的

我今天试了一下,切换的Accessor改成另外一路I2C,可以发通。也就是 I2C 下面 挂 JtagSwitch (Swich的切换用的还是这路I2C)会死锁?

    "JtagSwitch_BP_I2C_SW": {
      "Accessor": "#/Accessor_JtagSwitch_I2C_SW"
    },
    "Accessor_JtagSwitch_I2C_SW": {
      "Chip": "#/Smc_ExpBoardSMC",     --- 其实我的硬盘背板没有SMC,我只是随便写个,让他来切换而已;不产生实际作用;(我提写死了通路是通的)
      "Offset": 469776897,
      "Size": 1,
      "Mask": 255,
      "Type": 0,
      "Value": 0
    },