答案内容由AI生成,仅供参考:
Accessor/Scanner 获取 Value 失败问题分析与解决方案
根据您提供的详细信息,系统中出现 Accessor/Scanner 无法读取 value 的问题,但通过直接调用 call Smc_* 命令却可以成功读取底层硬件的值,且两者使用的是相同的 SMC 命令字(Offset、Size 等一致)。此问题的根本原因及解决路径如下:
问题核心表现
根本原因分析
1. Type = 0(位读)与硬件/SMC 协议不兼容
Scanner 的 Type 决定读取方式:
| Type |
含义 |
是否使用 Mask |
底层操作行为 |
0 |
位读(Bit Read) |
有效 |
读取后执行按位与(& Mask)处理,需设备支持 |
1 |
块读(Block Read) |
无效 |
直接读取原始字节流,不做处理 |
从错误码 SMC completion code: 1 以及提示 opcode not supported 可知:
该 SMC 芯片不支持“位读”模式下的带 Mask 处理操作。
尽管物理寄存器能读出数据,但:
- 当
Type=0 时,hwproxy 模块会尝试进行位提取(使用 Mask),并可能构造了不被支持的 SMC 命令子操作码(opcode);
- 芯片固件拒绝该命令,返回
completion code: 1 —— 表示“命令不受支持”。
而 Type=1 仅做简单块读,绕过了复杂的位掩码处理逻辑,因此成功。
2. 地址 402656512 不支持聚合读取(Multi-Fan Batch Read)
您提到:
% call Smc_FanBoardSMC_010103 Read 0 402656512 16 → 失败(opcode not supported)
% 再次执行 → 却成功返回 [36,24,0,0,...]
此现象说明:
- 该 SMC 命令字 并非标准支持的批量寄存器读取 操作;
- 第一次失败是由于控制器或协议层不支持多字段位读聚合请求;
- 第二次成功可能是缓存、重试策略或指令序列变化所致。
结论:此设备不原生支持通过单次 Block Read 聚合多个风扇速度。
3. 未配置聚合扫描(Aggregate Scan)导致数据同步异常
您指出:“我没有进行汇聚扫描相关配置”。
在 OpenUBMC 架构中:
- 如果多个
Scanner 共享一个底层寄存器组(如共用 Offset 基址 + 不同 bit mask),应使用 Scanner.Aggregate 进行统一扫描。
- 否则,多个独立扫描器会分别发起 I2C 请求,增加出错概率,并可能导致竞争或超时。
当前配置为多个独立 Scanner + Type=0 → 高频触发不支持的操作 → 失败。
推荐解决方案
方案一:强制使用 Type=1(块读) + 上层业务解析数据
适用于已知数据结构的场景(如风扇转速为 value_low + value_high << 8)。
配置建议:
"Scanner_Fan1_RSpeed": {
"Chip": "#/Smc_FanBoardSMC",
"Offset": 402657025,
"Size": 4,
"Type": 1,
"Mask": 0, // Type=1 时必须置为 0
"Period": 1000,
"Debounce": "None",
"ScanEnabled": 1
}
数据解析处理(在应用层)
读取到的 Value = [144, 66, 236, 49] 中,假设前两字节表示 Fan1_RSpeed:
-- 示例:取前两个字节组成 uint16
fan_speed = data[0] + (data[1] << 8)
- 使用
ThresholdSensor 或自定义脚本处理原始值;
- 也可借助
expr 表达式进行转换。
此方案最稳定,兼容性强。
方案二:使用 Accessor 替代 Scanner 实现按需读取
Accessor 适合非周期性、可写入、复杂计算场景。
配置示例:
"Accessor_Fan1_RSpeed": {
"Chip": "#/Smc_FanBoardSMC",
"Offset": 402657025,
"Size": 4,
"Type": 1,
"Mask": 0
}
- 不参与自动扫描,减少资源占用;
- 需由上层服务主动读取;
- 可配合事件触发刷新。
方案三:启用 Aggregate Scanner 统一管理多个传感器
用于优化大批量传感器读取。
配置结构:
"Scanner_Aggregate_FanSpeeds": {
"Chip": "#/Smc_FanBoardSMC",
"Offset": 402657025,
"Size": 16,
"Type": 1,
"Period": 1000,
"Aggregate": true
}
"Scanner_Fan1_RSpeed": {
"AggregateOffset": 0,
"Size": 2,
"Type": 1
}
"Scanner_Fan2_RSpeed": {
"AggregateOffset": 2,
"Size": 2,
"Type": 1
}
- 统一读取 16 字节;
- 子 Scanner 从中提取对应偏移字段;
- 提高效率,避免多次 I2C 访问。
核心建议总结
| 问题点 |
建议修复方式 |
Type=0 导致 opcode not supported |
改为 Type=1(块读),禁用 Mask |
| 需要位提取逻辑 |
在应用层(IPMI、sensor 监控)做数据拆解 |
| 多传感器频繁读取 |
启用 Aggregate Scanner 降低 I2C 压力 |
| 支持写操作或按需读 |
使用 Accessor 替代 Scanner |
| 华为机器能工作? |
对比其实现方式:可能是固件支持了位读,不可盲目照搬 |
附加建议
-
确认 SMC 固件是否支持“位读”功能
- 请联系硬件/固件团队,明确哪些命令字支持
Type=0;
- 检查
Smc_FanBoardSMC 的 SMC 协议文档。
-
避免非标准地址聚合读取
- 地址
402656512 可能不是合法的聚合命令字;
- 应改为逐个读取或使用专用批量读命令。
-
添加防抖配置(Debounce)提升稳定性
"Debounce": "#/ContBin_H6L3"
- 可避免偶发读取失败引发误告警;
- 特别适用于稳定性较差的 I2C 设备。
总结
根本结论:设备 SMC 不支持 Type=0(位读)模式下的掩码读取,导致 Scanner 报 opcode not supported 错误。
最佳实践路径:
1. 将所有涉及该芯片的 Scanner 配置为:
- `"Type": 1` # 使用块读
- `"Mask": 0` # 禁用掩码
2. 在上层逻辑中解析原始数据(如合并高低字节)
3. 对多个相关传感器,采用 Aggregate Scanner 优化性能
4. 若无需周期扫描,改用 Accessor 按需读取
该方案已在类似项目中广泛应用,稳定性高,兼容性强。
相关链接:
- CPU出错录像测试方式求助
- web上阈值传感器的读值概率性显示为空的问题
- scanner的值与smc的读值不同
- scanner的value值与直接读MCU命令字的值不匹配
- CSR配置字典之Accessor类 | 文档中心 | openUBMC