dft eeprom 测试在手动关闭写保护后 执行i2c write 失败

在执行DFT测试项时,发现测试项存在PSR eeprom self test 和eeprom self test 失败

发现是i2c写入失败

手动关闭写保护尝试写入也失败

当前主板和扩展板上的eeprom是16bit位宽,其它几个板子的eeprom是8bit位宽

当前在执行dfteeprom测试时 出现了8bit位宽的板子dfteeprom能通过,但16bit位宽的板子测试失败,查看代码,能看到调用了frudata的write方法,但没看明白如何处理不同eeprom位宽不同的场景,想确认一下是否跟位宽不同有关

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

结论

最可能的根本原因是 AddrWidth 配置错误(设为 1 而非 2),导致 I2C 写命令格式不符合 16bit 位宽 EEPROM 的协议要求。

其他因素如 StorageType 设置异常、写保护未解除、I2C 工具使用不当等,可能会加剧问题,但核心在于 CSR 中 地址宽度未正确配置

建议优先修正 AddrWidth=2 并重新测试,可解决大部分写入失败问题。同时配合正确的 I2C 工具命令和完整的写保护控制流程,确保测试全面覆盖。

点击此处查看详细分析解答

DFT EEPROM 测试写入失败问题分析

根据提供的日志、配置信息和代码上下文,对 DFT EEPROM 测试中 I2C 写入失败的问题进行系统性分析。

问题现象

  1. DFT 测试失败

    • PSR eeprom self testeeprom self test 均失败。
    • 日志显示写入操作返回 BMC_Error_Unknown
    • 实际读取返回值为 nil 或非预期数据。
  2. 手动写入失败

    • 使用 i2ctool64 手动执行 I2C 写操作也报错 i2c write err
    • 读操作可以成功(返回 0x00 数据),但写入失败。
  3. 硬件差异

    • 主板和扩展板使用 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,而写操作因指令错误而失败。

:white_check_mark: 此错误完全符合“读可行、写失败”的表现。


2. I2C 工具参数错误

命令示例:

./i2ctool64 2 4 4 0xae 0x00 0x06 0x06

参数说明需核实,若未正确指定地址宽度,则无法完成 16bit 寻址。

多数底层驱动要求明确指定 Address WidthOffset 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 配置中指定的 AddrWidthOffsetWidth

如果底层 hwproxy 或其 I2C 驱动未正确解析 AddrWidth=1(应为2),则不会生成正确的 I2C 数据包格式。


4. EEPROM 类型不匹配(Storagetype 限制)

文档指出:

StorageType="TianChi",而正常存储型应支持 EepromV2 或类似定义。

TianChi 架构有特殊限制。若 CSR 文件将 FRU 定义为非标准类型,可能导致写入路径被禁用或校验失败。


5. 写保护机制仍生效

尽管手动关闭写保护,但以下因素可能导致仍无法写入:

  • 写保护通过 GPIO 或专用芯片控制,未正确释放。
  • CSR 中缺少 EepromWpStorageLockChip 配置项,导致写保护逻辑未触发。
  • 写保护状态缓存未刷新。

根本原因归纳

因素 状态 是否导致失败
AddrWidth 设置错误(1 而非 2) :white_check_mark: 存在 :warning: 极可能主因
使用错误的 I2C 工具参数 :white_check_mark: 存在 :white_check_mark:
CSR 中 StorageType 不当 :white_check_mark:"TianChi" :warning: 可能影响写权限
驱动不支持 16bit 地址模式 :red_question_mark: 未知 :warning: 潜在原因
写保护未彻底释放 :warning: 存疑 可能叠加影响

解决方案建议

:white_check_mark: 修改 CSR 配置

AddrWidth 改为 2,以匹配 16bit 地址宽度:

"Eeprom_BCU": {
  "OffsetWidth": 2,
  "AddrWidth": 2,
  "Address": 174,
  "WriteTmout": 100,
  "ReadTmout": 100,
  "RwBlockSize": 32,
  "WriteInterval": 20,
  "HealthStatus": 0
}

:warning: 必须与实际 EEPROM 型号规格一致(如 24C256 支持 16bit 地址)。


:white_check_mark: 确认和更新 StorageType

如果该设备不是天池平台组件,应避免使用 StorageType="TianChi"

建议改为:

"StorageType": "EepromV2"

并在初始化中确保符合 FRU 写入规则。


:white_check_mark: 使用正确的 I2C 测试命令

确保 i2ctool64 支持指定地址宽度。例如(假设工具支持):

# 指定 AddressWidth=2, OffsetWidth=2
./i2ctool64 write --bus=1 --addr=0xae --aw=2 --ow=2 --offset=0x0000 --data=0x06

或根据真实接口文档调整参数顺序。


:white_check_mark: 验证写保护关闭流程

检查以下几点:

  1. 是否存在 EepromWp 控制对象?
  2. 是否在写入前调用 hwproxy 的写保护解除接口?
  3. 是否需要操作特定寄存器或 GPIO?

例如在代码中添加显式写保护控制:

-- 假设存在 WpControl 对象
fruData.EepromWp:Write(context, 0) -- 关闭写保护
-- 等待生效
sys.wait(10)

:white_check_mark: 代码层面增强调试输出

修改 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 工具命令和完整的写保护控制流程,确保测试全面覆盖。

我记得写保护不是往Eeprom写的,对应的Eeprom应该有个Accessor_wp对象,通过那个关闭写保护。还有你这里的16bit位宽和8bit位宽是指偏移位宽吗?

image是这么修改的,16bit是指偏移位宽

那是写入失败吗?报错是什么?

等下,setprop set实际不会触发硬件写入,手动设置需要用setprop modify。

这个是实际装备测试用例打印的内容:

2026-03-17 06:34:33.900930 network_adapter ERROR: ncsi_channel.lua(172): ncsi cmd ctrl enable channel tx failed, package_id = 8, channel_id = 2, eth_name = eth1 [repeated 26 times in 313s from 2026-03-17 06:29:21.009357 to 2026-03-17 06:34:33.900930]

2026-03-17 06:34:33.901526 network_adapter NOTICE: ncsi_comm.lua(182): ncsi port baisc init failed.(package_id = 8, channel_id = 2) [repeated 26 times in 313s from 2026-03-17 06:29:21.010113 to 2026-03-17 06:34:33.901526]

2026-03-17 06:34:38.106853 frudata NOTICE: frudata_manufacture_app.lua(83): write fruid(4) eeprom failed, ret(BMC.Error.Unknow: ./opt/bmc/libmc/lualib/mc/context.lua:203: ./opt/bmc/libmc/lualib/sd_bus/object.lua:317: ./opt/bmc/apps/hwproxy/lualib/hwproxy_objects/app_bus.lua:104: ./opt/bmc/apps/hwproxy/lualib/hw_utils/hw_wait_access.lua:101: chip: Eeprom_BCU_010102, bus: I2c_4, write failed: i2c.lua:120: response error, i2c write fail, ret: 5, input:{“mask”:4294967295,“buffer”:"55 55 55 55 55 55 55 55 ",“offsetWidth”:2,“addrWidth”:1,“addr”:174,“requestor”:“bmc.kepler.manufacture”,“type”:1,“is_trace”:false,“has_error”:false,“len”:8,“offset”:16376,“name”:“Eeprom_BCU_010102”,“rw_type”:0})

2026-03-17 06:34:38.912035 frudata NOTICE: frudata_manufacture_app.lua(83): write fruid(1) eeprom failed, ret(BMC.Error.Unknow: ./opt/bmc/libmc/lualib/mc/context.lua:203: ./opt/bmc/libmc/lualib/sd_bus/object.lua:317: ./opt/bmc/apps/hwproxy/lualib/hwproxy_objects/app_bus.lua:104: ./opt/bmc/apps/hwproxy/lualib/hw_utils/hw_wait_access.lua:101: chip: Eeprom_EXU_0101, bus: I2c_15, write failed: i2c.lua:120: response error, i2c write fail, ret: 5, input:{“mask”:4294967295,“is_trace”:false,“rw_type”:0,“has_error”:false,“drv_write_delay”:0,“buffer”:"55 55 55 55 55 55 55 55 ",“offsetWidth”:2,“addrWidth”:1,“type”:1,“name”:“Eeprom_EXU_0101”,“addr”:174,“requestor”:“bmc.kepler.manufacture”,“len”:8,“offset”:16376})

2026-03-17 06:34:39.690551 general_hardware NOTICE: retimer_PT5161L.lua(163): [PT5161L] notify upgrade status, name=Retimer_PT5161L_2_010132 status=IDLE [repeated 40 times in 302s from 2026-03-17 06:29:37.951619 to 2026-03-17 06:34:39.690551]

2026-03-17 06:34:39.984163 frudata NOTICE: frudata_manufacture_app.lua(83): write fruid(0) eeprom failed, ret(BMC.Error.Unknow: ./opt/bmc/libmc/lualib/mc/context.lua:203: ./opt/bmc/libmc/lualib/sd_bus/object.lua:317: ./opt/bmc/apps/hwproxy/lualib/hwproxy_objects/app_bus.lua:104: ./opt/bmc/apps/hwproxy/lualib/hw_utils/hw_wait_access.lua:101: chip: Eeprom_BCU_010102, bus: I2c_4, write failed: i2c.lua:120: response error, i2c write fail, ret: 5, input:{“buffer”:"55 55 55 55 55 55 55 55 ",“offsetWidth”:2,“len”:8,“addr”:174,“addrWidth”:1,“name”:“Eeprom_BCU_010102”,“offset”:16376,“has_error”:false,“mask”:4294967295,“requestor”:“bmc.kepler.manufacture”,“is_trace”:false,“type”:1,“rw_type”:0})

2026-03-17 06:34:39.986120 frudata ERROR: frudata_manufacture_app.lua(118): DFTSelfEeprom test failed, ret(2E 2F 6F 70 74 2F 62 6D 63 2F 61 70 70 73 2F 66 72 75 64 61 74 61 2F 66 72 75 64 61 74 61 5F 6D 61 6E 75 66 61 63 74 75 72 65 5F 61 70 70 2E 6C 75 61 3A 38 34 3A 20 46 61 69 6C 65 64 20 74 6F 20 77 72 69 74 65 20 45 65 70 72 6F 6D ) is not equal to test hex data

2026-03-17 06:34:40.712553 frudata ERROR: frudata_manufacture_app.lua(118): DFTSelfEeprom test failed, ret(nil) is not equal to test hex data

2026-03-17 06:34:41.303987 frudata ERROR: frudata_manufacture_app.lua(118): DFTSelfEeprom test failed, ret(nil) is not equal to test hex data

2026-03-17 06:34:41.806479 frudata ERROR: frudata_manufacture_app.lua(118): DFTSelfEeprom test failed, ret(nil) is not equal to test hex data

这种一般就是写保护实际没有关闭,你试下我说的用modify手动关闭在写看看,set是不触发硬件写入的。

那现在实际DFT测试场景还需要手动关闭写保护么,这感觉不合理,或者是这块代码有问题,实际并未关闭成功?

执行setprop modify Accessor_BCUWP_010101 bmc.kepler.Accessor Value 0后查询还是未修改成功

image

setprop set 能成功,但是示波器抓电压发现还是高电平

image

你之前是不是有用过set,set是覆写模式,会改变对外显示的值,你先unset后,再modify。然后再试下写eeprom能不能成功。