[TOC] 前言:目前总线接口仅在I2C支持,其他总线不支持此功能。接口功能和i2ctool类似,可以参照i2ctool使用。
1 找到想要访问的I2C总线
和i2ctool一样,使用总线读写接口前需要知道总线的id,总线上硬件的地址、偏移宽度等。这些信息均可通过csr配置获取。 I2c对象后面的数字就是对应的id,如果你清楚总线的id和要访问的硬件地址,那么可以跳过第一步。
首先,需要知道要访问的器件的名字是什么,比如Eeprom_NIC_010109,根据对象名,可以找到对应的器件位于Position为010109的csr内,通过《对象来源查找方法》文档可以找到对象位于哪份csr内。 比如,Eeprom_NIC_010109的配置如下:
"Eeprom_NIC": {
"OffsetWidth": 2,
"AddrWidth": 1,
"Address": 174,
"WriteTmout": 100,
"ReadTmout": 100,
"RwBlockSize": 32,
"WriteInterval": 20,
"HealthStatus": 0
}然后看硬件拓扑,确定器件在哪个I2C下,这可以通过一键收集日志的AppDump/hwproxy/topology.txt查到 注:硬件代理会将同一总线下同一地址的器件进行合并,避免无意义的内存消耗,此处的Eeprom_3_9_0101就是Eeprom_NIC_010109。 由图可知,Eeprom_NIC_010109挂在I2C_7下,通过9545分路挂在通道0下。
当然,也可以通过CSR逐级往上查找,在一键收集的日志,里AppDump/hwdiscovery/文件夹下存放着所有加载的csr,并以连接器的名字对csr重命名,一键收集的日志会打印连接器对应的csr文件名。 根据《通过对象查找来自哪份sr》文档查找对应的csr和连接器,再通过同样的方式找到连接器所在的csr和对应的上级连接器,以此循环找到root.sr
以Eeprom_NIC_010109为例,Eeprom_NIC_010109对象Position为010109,在framework.log里搜索,知道连接器是Connector_LOM_1_0101,打开sr文件,找到Eeprom_NIC对象以及所在的总线,
"I2cMux_pca9545_chan1": {
"Chips": [
"Eeprom_NIC",
"Pca9555_1",
"Lm75_1"
]
}Connector_LOM_1_0101对象的Position是0101,对应上级连接器Connector_EXU_1_01,在sr内找到Connector_LOM_1对象,知道Connector_LOM_1对象牵引下去的总线有"I2c_2"和"I2cMux_Pca9545_i2c7_chip_1",按顺序映射得知Connector_LOM_1_0101.sr内的I2cMux_pca9545_chan1总线对应I2cMux_Pca9545_i2c7_chip_1,在Connector_EXU_1_01.sr内全局搜索I2cMux_Pca9545_i2c7_chip_1,知道这条总线是通过Pca9545_i2c7_chip分路出的两路总线之一,向上查询Pca9545_i2c7_chip挂于I2c_7总线下,通过同样的方法找到Connector_EXU_1_01定义于root.sr内。 在root.sr找到Connector_EXU_1对象,映射得知I2c_7实际对应root.sr的I2c_7(因为sr牵引下去的总线可能会更名,因此往上一路找到root.sr定义的总线更为准确) 由此,我们得知Eeprom_NIC_010109挂在I2c_7总线下,通过9545分路挂在通道0下。
2 如何使用总线读写接口
2.1 总线读写接口调用格式
| 操作 | 命令 | 说明 |
|---|---|---|
| I2c写 | busctl --user call bmc.kepler.hwproxy /bmc/kepler/Bus/I2c/I2c_<id> bmc.kepler.Bus.BlockIO Write a{ss}yay 0 <addr> <write len> <data1> <data2> ... | 对I2c_i下挂载的硬件写入数据,addr对应硬件在csr配置里的Address,write_len是要写入的数据的长度,前几个字节的data一般为偏移,根据器件配置的Offsetwidth可以确定需要有几个字节存放偏移。 |
| I2c读 | busctl --user call bmc.kepler.hwproxy /bmc/kepler/Bus/I2c/I2c_<id> bmc.kepler.Bus.BlockIO WriteRead a{ss}yayy 0 <addr> <write len> <data1> <data2> ... <read len> | 对I2c_i下挂载的硬件读取数据,addr对应硬件在csr配置里的Address,write_len是要写入的数据的长度,前几个字节的data一般为偏移,根据器件配置的Offsetwidth可以确定需要有几个字节存放偏移,read_len是要读取的数据的长度。 |
| 注: | ||
| 1、如果要对需要切通道的chip进行读写,需要保证两条命令没有间隔,连续输入,不然可能会被代理自身的轮询打断,将通道切到错误的地方,导致读写失败。 | ||
| 2、需要切通道操作的请使用busctl连着发(参考下文的9545连续读写的命令),mdbctl暂不支持一行里集成多条命令。 |
2.2 总线读写样例
首先找到资源树上的I2c对象,根据需要调用接口,目前支持Write、Read、WriteRead接口。
调用Write接口向总线写数据,如向I2c_7的Pca9545器件发送命令切通道,命令为:
~ # busctl --user call bmc.kepler.hwproxy /bmc/kepler/Bus/I2c/I2c_7 bmc.kepler.Bus.BlockIO Write a{ss}yay 0 0xe0 2 0x00 0x01;再次调用WriteRead接口向总线从Eeprom对应偏移读取数据,命令为:
busctl --user call bmc.kepler.hwproxy /bmc/kepler/Bus/I2c/I2c_7 bmc.kepler.Bus.BlockIO WriteRead a{ss}yayy 0 0xae 2 0x00 0x05 10读取出Eeprom的数据,第一个数字10代表读取出了10个字节:
ay 10 0 0 0 90 165 90 165 2 16 0此命令需要切9545通道,因此建议使用如下方式命令,尽量保证连贯,但就算这样也不能保证这两条命令连续执行,可能会因代理自身的轮询打断,将通道切到错误的地方,导致读写失败,失败后重试即可。
busctl --user call bmc.kepler.hwproxy /bmc/kepler/Bus/I2c/I2c_7 bmc.kepler.Bus.BlockIO Write a{ss}yay 0 0xe0 2 0x00 0x01;busctl --user call bmc.kepler.hwproxy /bmc/kepler/Bus/I2c/I2c_7 bmc.kepler.Bus.BlockIO WriteRead a{ss}yayy 0 0xae 3 0x00 0x05 10通过命令直接从Eeprom读取,结果和总线读写一致。
busctl --user call bmc.kepler.hwproxy /bmc/kepler/Chip/Eeprom/Eeprom_NIC_010109 bmc.kepler.Chip.BlockIO Read a{ss}uu 0 5 10
ay 10 0 0 0 90 165 90 165 3 16 0