点击此处查看详细分析解答
DFT EEPROM 测试写入失败问题分析
根据提供的日志、配置信息和代码上下文,对 DFT EEPROM 测试中 I2C 写入失败的问题进行系统性分析。
问题现象
-
DFT 测试失败:
PSR eeprom self test 和 eeprom self test 均失败。
- 日志显示写入操作返回
BMC_Error_Unknown。
- 实际读取返回值为
nil 或非预期数据。
-
手动写入失败:
- 使用
i2ctool64 手动执行 I2C 写操作也报错 i2c write err。
- 读操作可以成功(返回 0x00 数据),但写入失败。
-
硬件差异:
- 主板和扩展板使用 16bit 地址位宽的 EEPROM。
- 其它板卡使用 8bit 位宽。
- 观察到 8bit 位宽设备测试通过,16bit 设备失败。
核心配置分析
EEPROM 配置片段
{
"Eeprom_BCU": {
"_OffsetWidth": 2,
"AddrWidth": 1,
"Address": 174,
"WriteTmout": 100,
"ReadTmout": 100,
"RwBlockSize": 32,
"WriteInterval": 20,
"HealthStatus": 0
}
}
虽然注释名为 _OffsetWidth,推测应为 OffsetWidth,且值为 2 表示偏移地址使用 16bit(2字节),这是关键点之一。
可能原因分析
1. AddrWidth 配置错误
当前配置 "AddrWidth": 1 表示使用 8bit 地址模式,但实际硬件为 16bit 位宽。
正确做法:对于支持 16bit 地址的 EEPROM,AddrWidth 应设置为 2。
影响说明:
- 当
AddrWidth=1 时,底层通信仅发送 1 字节地址。
- 真实设备等待 2 字节地址 → 导致识别错误或无响应。
- 读操作可能因设备默认状态返回 0,而写操作因指令错误而失败。
此错误完全符合“读可行、写失败”的表现。
2. I2C 工具参数错误
命令示例:
./i2ctool64 2 4 4 0xae 0x00 0x06 0x06
参数说明需核实,若未正确指定地址宽度,则无法完成 16bit 寻址。
多数底层驱动要求明确指定 Address Width 与 Offset Width,否则默认按 8bit 处理。
3. 底层驱动或封装未适配 16bit 模式
Lua 测试代码分析
local ok, ret = pcall(fruData.FruDev.Write, fruData.FruDev, context.get_context_or_default(),
EEPROM_SELFTEST_OFFSET, test_data)
此代码调用的是 FruDev.Write 方法,由 硬件代理(hwproxy) 处理。其行为依赖 CSR 配置中指定的 AddrWidth 和 OffsetWidth。
如果底层 hwproxy 或其 I2C 驱动未正确解析 AddrWidth=1(应为2),则不会生成正确的 I2C 数据包格式。
4. EEPROM 类型不匹配(Storagetype 限制)
文档指出:
StorageType="TianChi",而正常存储型应支持 EepromV2 或类似定义。
TianChi 架构有特殊限制。若 CSR 文件将 FRU 定义为非标准类型,可能导致写入路径被禁用或校验失败。
5. 写保护机制仍生效
尽管手动关闭写保护,但以下因素可能导致仍无法写入:
- 写保护通过 GPIO 或专用芯片控制,未正确释放。
- CSR 中缺少
EepromWp 或 StorageLockChip 配置项,导致写保护逻辑未触发。
- 写保护状态缓存未刷新。
根本原因归纳
| 因素 |
状态 |
是否导致失败 |
AddrWidth 设置错误(1 而非 2) |
存在 |
极可能主因 |
| 使用错误的 I2C 工具参数 |
存在 |
是 |
CSR 中 StorageType 不当 |
为 "TianChi" |
可能影响写权限 |
| 驱动不支持 16bit 地址模式 |
未知 |
潜在原因 |
| 写保护未彻底释放 |
存疑 |
可能叠加影响 |
解决方案建议
修改 CSR 配置
将 AddrWidth 改为 2,以匹配 16bit 地址宽度:
"Eeprom_BCU": {
"OffsetWidth": 2,
"AddrWidth": 2,
"Address": 174,
"WriteTmout": 100,
"ReadTmout": 100,
"RwBlockSize": 32,
"WriteInterval": 20,
"HealthStatus": 0
}
必须与实际 EEPROM 型号规格一致(如 24C256 支持 16bit 地址)。
确认和更新 StorageType
如果该设备不是天池平台组件,应避免使用 StorageType="TianChi"。
建议改为:
"StorageType": "EepromV2"
并在初始化中确保符合 FRU 写入规则。
使用正确的 I2C 测试命令
确保 i2ctool64 支持指定地址宽度。例如(假设工具支持):
# 指定 AddressWidth=2, OffsetWidth=2
./i2ctool64 write --bus=1 --addr=0xae --aw=2 --ow=2 --offset=0x0000 --data=0x06
或根据真实接口文档调整参数顺序。
验证写保护关闭流程
检查以下几点:
- 是否存在
EepromWp 控制对象?
- 是否在写入前调用
hwproxy 的写保护解除接口?
- 是否需要操作特定寄存器或 GPIO?
例如在代码中添加显式写保护控制:
-- 假设存在 WpControl 对象
fruData.EepromWp:Write(context, 0) -- 关闭写保护
-- 等待生效
sys.wait(10)
代码层面增强调试输出
修改 Lua 测试函数加入更多日志:
local function test_write_eeprom(fruData, origin_eeprommp)
log:notice("Starting EEPROM self-test for Fruid=%s", fruData.FruId)
log:notice("AddrWidth=%d, OffsetWidth=%d", fruData.FruDev.AddrWidth, fruData.FruDev.OffsetWidth)
local raw_data = fruData.FruDev:Read(context.get_context_or_default(), EEPROM_SELFTEST_OFFSET, #test_data)
if not raw_data then
log:error("Read original data failed")
error("Read failed before write")
end
local ok, ret = pcall(fruData.FruDev.Write, fruData.FruDev, context.get_context_or_default(),
EEPROM_SELFTEST_OFFSET, test_data)
if not ok then
log:error('Write failed: %s', ret or 'unknown')
return false
end
local buffer = fruData.FruDev:Read(context.get_context_or_default(), EEPROM_SELFTEST_OFFSET, #test_data)
if not buffer then
log:error("Verification read failed after write")
return false
end
-- 比较 test_data 和 buffer
for i = 1, #test_data do
if buffer:byte(i) ~= test_data:byte(i) then
log:error("Data mismatch at byte %d: expected %02x, got %02x", i, test_data:byte(i), buffer:byte(i))
return false
end
end
log:notice("Write and verify success")
return true
end
结论
最可能的根本原因是 AddrWidth 配置错误(设为 1 而非 2),导致 I2C 写命令格式不符合 16bit 位宽 EEPROM 的协议要求。
其他因素如 StorageType 设置异常、写保护未解除、I2C 工具使用不当等,可能会加剧问题,但核心在于 CSR 中 地址宽度未正确配置。
建议优先修正 AddrWidth=2 并重新测试,可解决大部分写入失败问题。同时配合正确的 I2C 工具命令和完整的写保护控制流程,确保测试全面覆盖。