Accessor/Scanner获取value失败

问题描述

Accessor/Scanner获取value失败,通过mdbctl读取Smc对应偏移可以读取成功

环境信息

  • 操作系统:[Ubuntu 24.04]

  • 软件版本:[OpenUBMC2509]

重现步骤

在配置风扇在位寄存器和转速寄存器时,遇到Accessor/Scanner获取值失败,失败信息为opcode不支持。但是操作Smc命令字直接读取对应偏移是可以正常读取的。

SMC命令字对比是一致的,寄存器的配置也是一样的。

如果将Scanner的type修改成1(块读),就可以正常获取到数值,但是此时也无法使用mask掩码操作。

对照后还有两个区别:
1、偏移地址 402656512,读多个风扇转速,这个地址不支持。


2、我没有进行汇聚扫描相关配置。

期望结果

实现Accessor/Scanner获取配置为位读时成功获取数据

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

Accessor/Scanner 配置失败问题分析与解决方案


:puzzle_piece: 问题概述

在当前环境中,ScannerAccessor 组件在读取硬件寄存器时出现 **“opcode not supported” 错误 **(SMC completion code: 1),无法正常获取 Value。然而,通过 call Smc_xxx BlockIO Read 命令直接访问相同的 SMC 偏移地址,却能成功读取数据,表明底层硬件通信功能正常。

此外,将 ScannerType 从 **位读 **(Type=0) 改为 **块读 **(Type=1) 后,可正常获取数据,但失去了 Mask 掩码功能,无法提取特定位字段。


:magnifying_glass_tilted_left: 问题定位分析

:white_check_mark: 环境信息

  • 操作系统: Ubuntu 24.04
  • BMC 软件版本: OpenUBMC2509
  • 目标设备: Smc_FanBoardSMC_010103
  • I2C 总线: I2c_4
  • 故障对象示例:
    Scanner_Smc_FanBoardSMC_Fan1RSpeed_010103
      Chip = "Smc_FanBoardSMC_010103"
      Offset = 402657025
      Size = 4
      Type = 0 (位读)
      Mask = 65535
    

:pushpin: 核心矛盾点

操作方式 是否成功 结果
call Smc_FanBoardSMC BlockIO Read :white_check_mark: 成功 返回 [144, 66, 236, 49]
Scanner + Type=0 (位读) :cross_mark: 失败 opcode not supported, SMC completion code: 1
Scanner + Type=1 (块读) :white_check_mark: 成功 Status=0, Value=6016

:warning: 关键问题:相同 Offset 和 Size 配置下,Scanner 位读模式触发了不支持的操作码,而块读和手动调用成功。


:magnifying_glass_tilted_right: 根本原因分析

根据提供的知识库和实际行为,可总结以下几点根本原因:

:small_blue_diamond: 1. SMC 芯片不支持“位读”操作(Type=0)

  • Type=0 表示使用 **位读模式 **(bit-level read),需要 SMC 实现特定的“位操作指令”。
  • SMC_FanBoardSMC_010103 不支持该操作码,因此当 Scanner 发起 Type=0 请求时,芯片返回 completion code: 1(不支持指令)。
  • call Smc_xxx BlockIO Read 使用的是 原生块读接口,绕过了 Scanner 的“位读语义”,直接执行底层 SMC 块访问,因此成功。
  • 结论Smc_FanBoardSMC 硬件/固件层面 不支持位读操作,只支持块读(Type=1)。

:small_blue_diamond: 2. Scanner 的 Type=0 触发了错误的 SMC 子命令

  • 根据 CSR 配置文档 和 知识图谱中 Type 属性定义:

    Type=0: 位读/写;Type=1: 块读/写

    BlockIO 接口支持块读写,而位操作需额外指令封装。

  • Type=0 时,Scanner 框架尝试调用 非 BlockIO 的、更复杂的位操作接口(可能包含 bit-mask & extract 操作),这在 SMC 层未实现。
  • Type=1 直接使用 BlockIO,与手动调用一致,故无问题。

:small_blue_diamond: 3. 多风扇聚合读取偏移不兼容

  • 你尝试访问偏移 402656512(0x18000000),用于一次读取多个风扇速度。
  • 该偏移报错 opcode not supported,但手动读取同一地址返回 [36,24,0,0,...] 成功。
  • 表明:
    • 该 SMC 支持从该地址 块读数据
    • 但不支持通过位读语义访问它 —— 因为 Scanner 可能试图执行位解析或使用非标准封装。

:small_blue_diamond: 4. 未启用 Aggregate 扫描

  • 当前你使用的是 独立 Scanner 对象扫描单个 Offset
  • 成功读取多风扇值(如 402656512)应配合 Scanner.Aggregate 汇聚扫描机制
  • 若未配置 Aggregate,Scanner 框架将无法正确处理“位域抽取”逻辑,即使 Type=1 成功读出原始数据,也无法自动 decode 出单个风扇值。

:brick: 相关知识支持(来自 Context)

实体 关联说明
Smc_FanBoardSMC_0101 处理风扇速度监控的 SMC 模块,通过 I2C 通信,存在 I2C Read Fail 问题
Scanner 周期性扫描硬件,Type=0 为位读,Type=1 为块读。
Type 属性 在 Scanner 中用于指定读取方式。文档明确说明:位读需器件支持,否则无效
Accessor vs Scanner Accessor 用于按需读写,Scanner 用于周期监控。两者均依赖 Chip 的 SMC 操作支持。
BMC.Error.Unknown 多次出现在 Smc_FanBoardSMC 访问失败中,常由 I2C 读失败或 opcode 不支持引起。

:white_check_mark: 解决方案建议

:white_check_mark: 方案一:统一使用 Type=1(块读) + 聚合扫描(Aggregate)

:check_mark: 推荐做法,符合 SMC 实际能力。

:white_check_mark: 步骤如下:

  1. 配置 Scanner 使用 Type=1(块读)

    "Scanner_Fan1_RSpeed": {
        "Chip": "#/Smc_FanBoardSMC",
        "Offset": 402657025,
        "Size": 4,
        "Type": 1,
        "Period": 1000,
        "Debounce": "None"
    }
    
  2. 启用 Scanner.Aggregate 实现批量读取与解析

    • 将多个风扇速度寄存器集中在一块内存区域(如 402656512
    • 创建一个 Aggregate Scanner 读取整个 Block
    • 使用 AggregateOffset 提取各风扇值
    "Scanner_Aggregate_FanSpeeds": {
        "Chip": "#/Smc_FanBoardSMC",
        "Offset": 402656512,
        "Size": 16,
        "Type": 1,
        "Period": 1000,
        "AggregateStatus": true
    }
    
    "Scanner_Fan1_FSpeed": {
        "Chip": "#/Smc_FanBoardSMC",
        "AggregateOffset": 0,
        "Size": 2,
        "Type": 1
    }
    
    "Scanner_Fan1_RSpeed": {
        "Chip": "#/Smc_FanBoardSMC",
        "AggregateOffset": 2,
        "Size": 2,
        "Type": 1
    }
    
  3. 在应用层做位解析(若需掩码)

    • Aggregate 获取原始数据后,由上层逻辑(Redfish、WebUI)解析具体字段
    • 或通过 expr(...) 表达式进行 post-processing

:white_check_mark: 方案二:禁用 Mask,直接读取原始字段

若数据本身是完整整数(如 RPM),无需掩码,则可忽略 Mask 字段。

  • Type=1Mask 字段无效(见文档),无需设置
  • 读取原始 u16u32 数值即可
  • 适用于风扇速度、温度等连续型传感器

:white_check_mark: 方案三:自定义 Accessor 实现按需读 + 掩码处理

适用于不需要周期扫描的场景。

"Accessor_ReadFanSpeed": {
    "Chip": "#/Smc_FanBoardSMC",
    "Offset": 402657025,
    "Size": 4,
    "Type": 1,
    "Mask": 65535
}
  • 通过外部触发访问该值
  • 安全且可控,不占用周期扫描资源

:hammer_and_wrench: 临时缓解措施

  • 防抖优化:如文档所述,可配置 SuccessDebounceCountFailureDebounceCount,避免短暂错误导致误报。
  • Nominal Value 回退:配置 NominalValue 作为失效时默认值,保证系统可用性。
  • 监控 Status 字段:当 Status ≠ 0 时,表示值不可信,可用于告警判断。

:books: 配置最佳实践总结

项目 推荐配置
SMC 设备类型 优先使用块读(Type=1
批量读取 启用 Scanner.Aggregate
掩码需求 使用聚合读 + 上层表达式处理
周期性监控 使用 Scanner
写入/控制操作 使用 Accessor
Offset 编码 十进制(JSON 要求)
Size 设置 与数据类型一致(u8:1, u16:2, u32:4)

:white_check_mark: 结论与建议

:red_exclamation_mark: 根本原因Smc_FanBoardSMC 硬件/SMC 固件 不支持 Type=0 位读操作,导致 Scanner 在 Type=0 时返回 opcode not supported

:white_check_mark: 解决方案

  1. 统一使用 Type=1 + Scanner.Aggregate
  2. 放弃 Mask 在位读中的作用,改由上层逻辑处理
  3. 验证 SMC 是否真正支持“位操作”命令集,若不支持则不应使用 Type=0

:counterclockwise_arrows_button: 建议反馈至硬件团队

  • 明确 Smc_FanBoardSMC 是否支持 SMC 位操作(Type=0)
  • 若不支持,则所有相关 CSR 配置应强制使用 Type=1
  • 更新 CSR 模板,规避无效配置

:white_check_mark: 最终目标:实现稳定、高效的传感器数据采集,避免因配置不匹配引发通信失败。

相关链接:

  1. CPU出错录像测试方式求助
  2. 风扇型号信息是否有明确的定义标准或文档支撑信息查询和校验
  3. web上阈值传感器的读值概率性显示为空的问题
  4. scanner的值与smc的读值不同
  5. CSR配置字典之Accessor类 | 文档中心 | openUBMC

设置风扇转速Scanner type为1后,将转速Scanner.Value使用同步引用的方式传递给Fan对象后,会报error[emit signal: nesting is not allowed]。并且风扇类型识别会失败。


Smc位读的时候,offset会与上0xfffffc00再加上0x100,目的是将smc对应的整块数据取出来,再在代码里进行掩码运算,详细参考component_drivers的smc部分代码。AtomGit | GitCode - 全球开发者的开源社区,开源代码托管平台
smc报错opcode不支持可能是逻辑不支持这种位读的能力,可以看下两个环境的cpld版本是否一致。

1 个赞

你这里fan对象的csr配置是什么样的