关于SMC命令字的理解和疑问

1. SMC命令字定义


opcode也就是csr配置中的Offset,由Function,Command,MS,RW四个组成。

M就是multiple,表示多个读取;S是single,表示单个读取;RW很好理解,读和写
M=0,S=1
R=1,W=0

        "Accessor_ShortPushButton": {
            "Chip": "#/Smc_ExpBoardSMC",
            "Offset": 134224384,
            "Size": 1,
            "Mask": 1,
            "Type": 0,
            "Value": 0
        },
        "Accessor_LongPushButton": {
            "Chip": "#/Smc_ExpBoardSMC",
            "Offset": 134224384,
            "Size": 1,
            "Mask": 2,
            "Type": 0,
            "Value": 0
        },

2. SMC命令调试

例如
短按 mdbctl call Smc_ExpBoardSMC_0101 bmc.kepler.Chip.BlockIO Write 0 0x8001a00 1 0x01
长按 mdbctl call Smc_ExpBoardSMC_0101 bmc.kepler.Chip.BitIO Write 0 0x8001a00 1 2 1 0x01
其实这里最好用BitIO的方法,和csr中的Type要对应起来,否则可能出现我在这篇帖子中遇到的问题 强制重启SMC命令定制 - 交流互助区 - openUBMC 论坛
Type = 0对应BitIO,1对应BlockIO。

接口中使用的参数参考文档中BlockIO和BitIO的说明 简介 | 文档中心 | openUBMC

3.SMC命令字转换工具

这边写了个简单的小工具,Linux环境中使用,压缩包里有工具和源码,有问题的话大家自己改一下。
smc_tool.zip (3.9 KB)


去算offset的时候后面的4个参数都是十六进制数,可以加上0x也可以不加。

4.疑问

  1. 关于MS,这里的多个和单个是指什么?好像和read,write后面跟的读取/写入个数没关系
  2. 读上下电状态在csr中的offset是469765888(0x1c000f00),算出来就是7 3 1 1。以前好像有看到个文章说MS和RW应该是对应起来的,要么0 1,要么1 0,不会有1 1的情况,并且在印象里v2中xml在这个命令字的注释上面好像写的也是7 3 0 1即0x1c000d00,但实际配置的offset却是0x1c000f00,请问这个是为什么呢?
  3. BitIO write的参数问题,有一个写入长度Length,但是实际InData数组的第一个数据好像还得指定长度,后面的才是实际写入数据。这两个长度是重复了吗?还是我对第一个Length的理解不对?
6 个赞
  1. SMC 协议中,Opcode 中的 MS 字段是一个控制位,用于区分读取模式。
  • MS = 0:表示多个设备读取(Multiple Read),即一次读取操作会涉及多个设备或部件。
  • MS = 1:表示单个设备读取(Single Read),即一次读取操作仅针对一个设备或部件。
  1. InData数组的第一个数据是在使用busctl时代表数组的的数据长度,前面的Length代表实际要根据后面的数据写入多少位
4 个赞

SMC协议关于M/S定义

协议定义了位读,块读,位写、块写4种操作模式
位读:M/S=1;RW=1;Param=要读取的设备/对象序号; 返回单个对象的数据
块读:M/S=0;RW=1;Param=0;返回该命令所有数据
位写:M/S=1;RW=0;Param=要读取的设备/对象序号
块写:M/S=0;RW=0;Param=0
由于逻辑资源限制,当前逻辑只实现块读和块写操作,BMC的驱动层会将BMC下发的位操作转换为快操作

M/S的典型应用场景:
M: 按块读取,一次读取多个字节
S: 单个读写,一次读或写1个字节
典型应用场景:SMC读取命令MS=0,即推荐块读;SMC写入命令MS=1,即推荐位写。

4 个赞

通过AI把你的工具转换成了Python脚本,就不限平台了 :grin:

import sys

def main():
    if len(sys.argv) < 2 or len(sys.argv) > 6:
        print("使用方法:smc_tool [Func] [Cmd] [M/S] [R/W] [Parameter]")
        print("例如:smc_tool 7 3 0 1 0")
        print("以上参数均为十六进制数,也可以反推smc命令的offset")
        print("例如:smc_tool 469765376 或 smc_tool 0x1c000d00")
        print("位布局:Func(6位) | Command(16位) | MS(1位) | RW(1位) | Parameter(8位)")
        return -1

    if len(sys.argv) == 2:
        input_str = sys.argv[1]
        hex_num = int(input_str, 0)  # 自动识别进制

        print(f"Func     : {(hex_num >> 26) & 0b111111:x}")
        print(f"Command  : {(hex_num >> 10) & 0xffff:x}")
        print(f"M/S      : {(hex_num >> 9) & 0b1:x}")
        print(f"R/W      : {(hex_num >> 8) & 0b1:x}")
        print(f"Parameter: {hex_num & 0xff:x}")

    elif len(sys.argv) == 6:
        try:
            nums = [int(arg, 16) for arg in sys.argv[1:]]
            for num in nums:
                print(f"{num:02x} ", end="")

            result = (
                (nums[0] & 0b111111) << 26 |
                (nums[1] & 0xffff) << 10 |
                (nums[2] & 0b1) << 9 |
                (nums[3] & 0b1) << 8 |
                (nums[4] & 0xff)
            )
            print(f"\n转换结果为:\n{result} \n或 \n0x{result:x}")

        except ValueError:
            print("\n参数解析错误")
            return -1

    else:
        print("参数错误")
        return -1

if __name__ == "__main__":
    main()


8 个赞