EMS 知识库
首页 / knowledge/代码解析/data/fault_warn_log

fault_warn_log.c

源文件路径:data/fault_warn_log/fault_warn_log.c 所属模块:数据管理 / 故障告警日志(data/fault_warn_log) 代码行数:2171

1. 文件职责

本文件是 EMS 的"故障/告警全生命周期记录器":以固定的采样快照差分方式,把 EMS、BMS、逆变器(PCS)、充电桩(EVC)、电表/BB 箱的故障位、告警位、保护位的变化翻译成带时间戳的故障码记录,写入 SPI Flash 环形区(ERROR_LOG_DATA_RECORD_ADDR ~ ERROR_LOG_DATA_RECORD_END)。它同时承担三条下游通路:打包成 CSV 帧通过 STATUS_SEND_ERROR_LOG 上传云平台(net/ems.c:6085)、把最近 10 条记录喂给 LCD 历史故障界面(hmi/ui/ui_history_error_log.c)、把故障位合并成 3 个 32 位掩码供 LED/主界面显示(hmi/led.c:831)。文件还维护 LCD 主界面滚动故障码 FIFO、EEPROM 读写故障标志、电池加热故障标志等辅助状态。它由 data/data.c:251 的 task_system_data 任务驱动,每轮循环调用一次 error_log_data_handle()。

2. 关键数据结构与宏

名称类型说明
FAULT_CODE_PAIR_T结构体{u16 faultBitPos; u32 fault_code;},把"位域里的第 N 位"映射到"对外故障码",是所有差分扫描表的元素类型
ERROR_DEVICE_TYPE_E枚举设备类型:ERROR_NONE / ERROR_EMS / ERROR_INV / ERROR_BMS / ERROR_EVC / ERROR_METER
ERROR_TYPE_E枚举事件类型:NONE_TYPE / WARN_CLEAR / FAULT_CLEAR / WARN_OCCURRED / FAULT_OCCURRED / INFO_OCCURRED / PROTECTION_CLEAR / PROTECTION_OCCURRED
ERROR_CODE_E枚举全部对外故障码常量:E0000~E0094(EMS)、I10000~I10002(EMS 事件)、E60000~E60031(BMS)、W70000~W70015、P75000~P75009、P77500~P77532、E100000~E100456(INV)、W110000~W110137(INV 告警)、E200000~E200031(EVC)、E160000~E160002(METER)
BMS_DISPLAY_ERROR_U联合体u32 u32_all 与 6 个 BMS 显示位(u8_bms_lost、u8_circuit_breaker_open、u8_dial_switching_mode_inconsistence、u8_slave_battery_communication_lost、u8_master_battery_communication_lost、u8_multi_master_error)叠加
INV_DISPLAY_ERROR_U联合体25 个逆变器显示位(u8_inv_lost、u8_grid_ovp/uvp/ofp/ufp、u8_bus_ovp1、u8_insulation_fault、u8_gfci_fault、u8_para_*、u8_grid_loss_fault 等)叠加 u32_all
ACCESSORIES_DISPLAY_ERROR_U联合体附件/充电桩显示位(u8_grid_meter_lost、u8_pv_meter_lost、u8_evchargerlost、u8_relay_otp、u8_output_overload、u8_ac_leakage_current、u8_input_terminal_otp、u8_relay_abnormal、u8_ground_fault、u8_reverse_phase、u8_afci_*)叠加 u32_all
STORE_ERROR_LOG_ADDR_T结构体地址备份单元,#pragma pack(1) 共 16 字节:u32_log_send_addr、u32_log_save_addr、u16_flash_idex、u8_reserve[4]、u16_crc_code;4096/16 = 256 个单元恰好占满一个 Flash 扇区
STORE_ERROR_LOG_DATA_T结构体单条故障日志,#pragma pack(1) 共 32 字节:Time(6)、u8_device_type、u8_fault_or_warn、u8_fault_location、u8_fault_id、u32_fault_code、s32_fault_value、u8_reserve[12]、u16_crc_code
ERROR_LOG_TABLE_T结构体模块总上下文,约 17.5KB,放在 SDRAM(SDRAM_FAULT_LOG_START_ADDR,预留 20K)。含 4KB 扇区临时缓冲、各设备本地位域快照、地址结构、256 条写缓存、256B×5KB 上传缓冲、3 个显示掩码、BB 箱故障
ERRCODE_FIFO_T结构体LCD 主界面故障码 FIFO:u8_error_code_level_judgment_flag、u8_lcd_show_buf_len、u8_errcode_Write(写指针=当前有效条数)、u32_errcode_buf[10] 环形缓冲
BIT_SET / BIT_CLEAR / BIT_IS_SET / BIT_VALUE宏按位索引读写字节数组:BIT_VALUE(byteData,i) 取第 i 位值;BIT_IS_SET(byteData,i) 判断是否为 1
ERROR_LOG_DATA_CACHE_MAX_SIZE宏256,写缓存条数上限(注释提醒"缓存不能超过 65535")
ERROR_LOG_SERVER_PACK_MAX_SIZE宏5*1024,单包上传缓冲上限
ERROR_LOG_DATA_RECORD_ADDR_BACKUP1/2/3宏0xF63000 / 0xF64000 / 0xF65000,地址三元冗余备份扇区
ERROR_LOG_DATA_RECORD_ADDR / _END宏0xF66000 / 0xFC8FFF,日志数据环形区(约 396KB)
ERRCODE_FIFO_SIZE宏10,LCD 故障码缓冲深度
DEBUG_FLASH_DATA_STORE宏0,日志调试打印总开关(注意与 flash_data_store 里的同名宏重复定义)

3. 函数清单

函数名作用域说明
error_log_data_init全局清零 g_t_error_log_tab,调用地址恢复,把临时发送地址对齐到已恢复的发送地址
error_log_data_addr_save全局重算地址结构 CRC 并写入 3 个备份扇区,然后递增 u16_flash_idex(0~255 环回)
error_log_data_addr_restorestatic从 3 个备份扇区各取最后一个合法记录,两两比对表决出地址,并补写一次地址
save_error_log_data_to_flash全局把缓存数组按 32B/条写入 Flash,处理越界回绕并调整发送指针
save_error_log_data_to_cache全局把一条故障写进 RAM 缓存并刷新 LCD 故障码 FIFO,满 256 条或收到 ERROR_NONE 时刷入 Flash
save_error_log_data全局核心差分扫描函数:重启/按键事件 + EMS/BMS/保护/BMS 告警/INV/INV 扩展/INV 告警/EVC/EVC-II/BB 箱共 13 组位域扫描
get_error_device_type_string全局设备类型枚举 → CSV 字段(System/PCS/BMS/EVC/NONE)
get_error_device_subtype_string全局设备类型枚举 → 子类型字符串(ems/dcac/lmu/evc/NONE)
get_error_state_string全局事件类型 → clear/occur/NONE
get_error_level_string全局事件类型 → Warning/Protection/Fault/Info/NONE
pack_error_log_data_endstatic给上传缓冲补 7 字节帧头(EMS+REQUEST_COMM+CMD_UPDATE_ERROR_LOG+4 字节长度)与 Modbus CRC
upload_error_log_data_package全局打包待上传故障日志成 CSV 帧;同时处理发送成功后的发送指针确认(ACK)分支
error_log_data_handle全局模块总入口:采集→上传→LCD 历史查询,并每轮调用 package_display_error_code
set_error_log_data_send_ok_true全局云平台确认收到日志后置 ACK 标志、清发送标志与发送长度
erase_error_log全局擦除 0xF63000~0xFC8FFF 全区间(块+首尾零头扇区),按 3 次重试并喂看门狗
error_log_data_clear全局工厂复位用:整体清零上下文、擦除日志区、重置地址并保存
get_history_error_log_data全局从保存指针往前读最多 len(≤50)条日志,CRC 校验后填入 g_t_history_error_log[],返回有效条数
put_errcodestatic向故障码 FIFO 压入一个故障码(去重;满 10 条则整体前移丢弃最旧)
release_errcodestatic从故障码 FIFO 中移除一个故障码并压缩数组
lcd_get_errcode_buf_len全局返回 FIFO 当前有效条数,同时刷新"故障码变化"判定标志
lcd_get_errcode_buf_judgment_flag全局比较条数与登录界面状态,设置 u8_lcd_error_code_judgment_flag
get_show_errcode全局按偏移读 FIFO 中一个故障码,空则返回 0
update_lcd_mainui_app_show_error_codestatic仅对 FAULT_OCCURRED/FAULT_CLEAR 生效,分别调用 put_errcode/release_errcode
package_display_error_codestatic把各设备原始故障位与跨簇"或"运算合并成 BMS/INV/附件三个显示掩码
get_bms_display_error_code全局返回 u_bms_display_error.u32_all
get_inv_display_error_code全局返回 u_inv_display_error.u32_all
get_accessories_display_error_code全局返回 u_accessories_display_error.u32_all
set_eeprom_fault_flag全局按 EEPROM 页号在 32 位掩码中置/清对应位(页范围 SYSTEM_STARTE_PAGE~SYSTEM_DATA_BACKUP_PAGE 之外直接返回)
get_eeprom_hardware_read_fault_flag全局返回硬件读故障掩码指针
get_eeprom_hardware_write_fault_flag全局返回硬件写故障掩码指针
get_eeprom_software_read_fault_flag全局返回软件读故障掩码指针
get_eeprom_software_write_fault_flag全局返回软件写故障掩码指针
set_bat_heat_fault_flag全局置/清 g_t_ems_info.u_ems_fault.bit.u8_bat_heat_fault
read_bat_heat_fault_flag全局读电池加热故障位

4. 核心逻辑解析

4.1 调度入口与时序

error_log_data_handle()(fault_warn_log.c:1538)是唯一入口,被 data/data.c:294 的 task_system_data 调用。调用点位于 OSSemPend(g_t_power_down_sem, 500, &err) 超时分支(err != OS_ERR_NONE),即掉电信号量未在 500 tick 内到来时执行——因此扫描周期约为 500ms。

处理流程:

  1. IsDownloadEMS() 为真(正在升级 EMS 固件)时整段跳过,只执行最后的 package_display_error_code()。
  2. save_error_log_data() 做全量差分扫描。
  3. 仅在 g_stEMSInfo.bIsLogin && g_stEMSInfo.bIsBuiltSocket == TRUE 时调用 upload_error_log_data_package();否则强制 u8_error_log_send_flag = FALSE(断开时不保留半包)。
  4. LCD 历史查询:用 g_u8_get_history_error_log_flag 做一次性初始化,之后每 3*60*1000 tick(约 3 分钟)用 OSTimeGet() 差值判断刷新一次;OSTimeGet() - tick 为负数(时钟回绕或已刷新)时直接把 tick 拉平,避免长时间不再刷新。

4.2 快照差分扫描状态机(save_error_log_data,fault_warn_log.c:459)

这不是传统状态机,而是"位域镜像差分"机制:g_t_error_log_tab 中为每类故障保存一份上一周期的位域镜像,与实时全局变量比较后产生事件,最后把整份镜像更新为新值。

差分的通用判定(以 EMS 为例,fault_warn_log.c:551-563):

if (BIT_VALUE(镜像, bitPos) != BIT_VALUE(实时, bitPos)) {
    if (BIT_IS_SET(实时, bitPos))  → save_error_log_data_to_cache(..., FAULT_OCCURRED, ..., code);
    else                           → save_error_log_data_to_cache(..., FAULT_CLEAR,    ..., code);
}
镜像.u32_all = 实时.u32_all;

各组扫描对象、镜像变量与实时来源:

组镜像(旧)实时(新)事件类型故障码区间
EMS 故障u_ems_err_logg_t_ems_info.u_ems_faultFAULT_OCCURRED/CLEARE0001~E0094
BMS 故障(簇 0~12)u_bms_fault_log[i]g_t_bat_info.t_run_info.u_bms_fault_code[i]FAULT_OCCURRED/CLEARE60000~E60029
BMS 保护(簇 0~12)u_bms_protection_log[i]u_bms_protection_code[i]PROTECTION_OCCURRED/CLEARP75000~P75008
BMS 保护扩展 1u_bms_protection_extend1_log[i]u_bms_protection_extend1_code[i]位序号直接决定事件类型P77500 + j
BMS 保护扩展 2u_bms_protection_extend2_log[i]u_bms_protection_extend2_code[i]PROTECTION_OCCURRED/CLEARP75009(动力线过温)
BMS 告警(簇 0~12)u_bms_warn_log[i]u_bms_warning_code[i]WARN_OCCURRED/CLEARW70000~W70015
INV 故障u_inv_fault_logg_t_inv_info.t_run_info.u_fault_codeFAULT_OCCURRED/CLEARE100000~E100062、E100140
INV 故障扩展 1u_inv_fault_extend1_logu_fault_extend1_codeFAULT_OCCURRED/CLEARE100122~E100403
INV 故障扩展 2u_inv_fault_extend2_logu_fault_extend2_codeFAULT_OCCURRED/CLEARE100404~E100456
INV 告警u_warning_codeu_warning_codeWARN_OCCURRED/CLEARW110000~W110103
INV 告警扩展 1u_warning_extend1_codeu_warning_extend1_codeWARN_OCCURRED/CLEARW110108~W110137
EVC(一体桩)u_evc_fault_ug_t_evc_run_info.evc_fault_uFAULT_OCCURRED/CLEARE200000~E200031
EVC-II(4 路)u_evc_ii_fault_u[i]g_t_evc_ii_run_info[i].evc_ii_fault_uFAULT_OCCURRED/CLEARE200000~E200031,fault_location = i+1
BB 箱u_bb_fault_ug_t_meter.t_bb_debug.bb_fault_uFAULT_OCCURRED/CLEARE160000~E160002

两个特殊分支:

BMS 保护扩展 1 的事件类型判定比较特殊(fault_warn_log.c:657-688):位序号 P77500 + j 若命中硬编码集合 {P77501, P77504, P77505, P77510, P77514, P77516} 则记为 FAULT,否则记为 PROTECTION。

函数末尾(fault_warn_log.c:1233)用 save_error_log_data_to_cache(ERROR_NONE, NONE_TYPE, 0, 0, E0000) 作为"刷盘哨兵"。

4.3 缓存批量落盘

save_error_log_data_to_cache(fault_warn_log.c:421):

save_error_log_data_to_flash(fault_warn_log.c:319)的写入与回绕:

若 save_addr + len > ERROR_LOG_DATA_RECORD_END:
    secremain = (END+1 - save_addr) - (END+1 - save_addr) % 32   // 向下取整到 32B 边界
    先写 [save_addr, +secremain),再写 [RECORD_ADDR, +剩余长度)
    save_addr = RECORD_ADDR + 剩余长度
否则:
    直接写,save_addr += len

随后是一段"发送指针追赶"逻辑(fault_warn_log.c:364-409),等价语义是:

每次写完都调用 error_log_data_addr_save() 落盘地址。

4.4 地址三元冗余与表决(error_log_data_addr_restore,fault_warn_log.c:107)

error_log_data_addr_save(fault_warn_log.c:66)反向操作:算 CRC,分别写到三个备份区的第 u16_flash_idex 槽(各重试 3 次),最后 u16_flash_idex++ 并按 256 环回。

4.5 上传打包与帧格式

upload_error_log_data_package(fault_warn_log.c:1397)有两个分支:

ACK 分支(u8_error_log_send_ok_flag == TRUE):set_error_log_data_send_ok_true()(由 net/server.c:6749 在收到平台回执时调用)已置位。此时把"上一次打包时记下的 u32_error_log_addr_temp"与当前发送指针做一致性比对,决定是否把 u32_log_send_addr 前推并重新保存地址;三个子分支覆盖"发送地址已回绕 / 未偏移 / 已偏移但 Flash 未填满"三种情形(fault_warn_log.c:1409-1444)。

打包分支:从 u32_error_log_addr_temp 一直读到 u32_log_save_addr(环形,越过 ERROR_LOG_DATA_RECORD_END 回绕到 ERROR_LOG_DATA_RECORD_ADDR),每条先 Flash_Read 3 次并校验 Modbus CRC,通过后才拼 CSV。

CSV 内容:

SN,Time,type,subtype,id,Code,state,level\n                       ← 首行,仅在 send_len == 0 时添加
<SN>,20YY/MM/DD HH:MM:SS,<type>,<subtype>,<fault_id>,<fault_code>,<state>,<level>\n

其中 type = get_error_device_type_string(u8_device_type)、state = get_error_state_string(u8_fault_or_warn)、level = get_error_level_string(u8_fault_or_warn)。

帧头(pack_error_log_data_end,fault_warn_log.c:1367):

偏移长度内容
01EMS(net/ems.h 中的设备地址宏)
11REQUEST_COMM = 0x01
21CMD_UPDATE_ERROR_LOG = 0x0F
34大端 32 位数据域长度 = u32_error_log_send_len - 7
7NCSV 文本
7+N2CRC16-Modbus,高字节在前

u32_error_log_send_len + N + 2 > 5120 时截断成当前包(fault_warn_log.c:1499)。

4.6 LCD 故障码 FIFO

update_lcd_mainui_app_show_error_code(fault_warn_log.c:1893)只处理 FAULT_OCCURRED/FAULT_CLEAR,分别对应 put_errcode(去重压入,满 10 条则整体左移淘汰最旧,fault_warn_log.c:1785-1798)与 release_errcode(把匹配项之后的元素左移压缩,fault_warn_log.c:1817-1830)。

lcd_get_errcode_buf_len 每次读长度时都调用 lcd_get_errcode_buf_judgment_flag,后者在"长度变化"或"登录界面 id_setting_into_last 变化"时置 u8_lcd_error_code_judgment_flag = TRUE,供 hmi/ui/ui_main.c:453 决定是否重绘主界面故障码区。

4.7 显示掩码打包(package_display_error_code,fault_warn_log.c:1936)

每轮 error_log_data_handle 末尾无条件调用(含升级期间),把多簇原始位做跨簇"或":

结果供 hmi/led.c:831/857/859/892/894 与主界面使用。

4.8 Flash 擦除(erase_error_log,fault_warn_log.c:1604)

先算出区间首尾包含整块的地址,然后分三段擦:块前的零头扇区(Flash_Erase_Sector)、中间整块(Flash_Erase_Block,64KB)、块后的零头扇区,每步最多重试 3 次并 IWDG_Feed()。error_log_data_clear(fault_warn_log.c:1685)在擦除前整体 memset 上下文,擦除后重置地址三要素并重新保存。

4.9 历史查询地址计算(get_history_error_log_data,fault_warn_log.c:1703)

len 限定在 (0, 50]
起始地址 = save_addr - 32*len
若起始地址 < ERROR_LOG_DATA_RECORD_ADDR:
    起始地址 = ERROR_LOG_DATA_RECORD_END - (ERROR_LOG_DATA_RECORD_ADDR - 起始地址)   // 环形回绕
逐条 +32 读取并 CRC 校验;u8_fault_or_warn != 255 才算"有效条数"

4.10 EEPROM 与加热标志

set_eeprom_fault_flag(fault_warn_log.c:2075)用 1 << (addr - SYSTEM_STARTE_PAGE) 把 EEPROM 页号映射到 32 位掩码(SYSTEM_STARTE_PAGE = 4071、SYSTEM_DATA_BACKUP_PAGE = 4095,恰好 25 页)。4 个 get_eeprom_*_fault_flag 返回各自静态掩码的地址,由 hardware/flash/feeprom.c、data/system_config/system_config.c、data/data.c 多处读写。set_bat_heat_fault_flag/read_bat_heat_fault_flag 直接操作 g_t_ems_info.u_ems_fault 的 u8_bat_heat_fault 位,由 midware/bms/bms.c 与 midware/inverter/set/set_comm_can.c 使用。

5. 对外接口

导出的函数(供谁调用)

函数主要调用方
error_log_data_initdata/data.c:259(task_system_data 初始化)
error_log_data_handledata/data.c:294
error_log_data_cleardata/data.c:99(工厂复位)
set_error_log_data_send_ok_truenet/server.c:6749
get_history_error_log_datadata/fault_warn_log/fault_warn_log.c:1556(自用)、LCD 历史界面
get_show_errcodehmi/ui/ui_main.c:479/484/491、net/ems.c:850
lcd_get_errcode_buf_lenhmi/ui/ui_main.c:465/471/574
get_bms_display_error_codehmi/led.c:831/857
get_inv_display_error_codehmi/led.c:859/892
get_accessories_display_error_codehmi/led.c:245/630/894/920
set_eeprom_fault_flaghardware/flash/feeprom.c、data/system_config/system_config.c、data/data.c
get_eeprom_hardware_read/write_fault_flaghardware/flash/feeprom.c、data/data.c
get_eeprom_software_read/write_fault_flagdata/system_config/system_config.c、data/data.c
set_bat_heat_fault_flagmidware/bms/bms.c:1828/2306/2455/2611
read_bat_heat_fault_flagmidware/inverter/set/set_comm_can.c:211

导出的全局变量

调用的外部函数/变量

6. 依赖关系

依赖

fault_warn_log.h(自身头)、<time.h>、system_aux.h、ems_download.h、crc.h、ems.h、system_config.h、gpio.h、ui.h、iwdg.h、key.h;通过头文件间接依赖 chip.h、pcf8563.h、sdram.h、flash.h、data.h、bms.h、evc.h、evc_ii.h、inverter.h、meter.h。

被依赖

7. 备注与风险点

  1. release_errcode 存在数组越界读(fault_warn_log.c:1817-1829):循环体先执行 s_t_errcode.u32_errcode_buf[i] = s_t_errcode.u32_errcode_buf[i + l_u8_offset]; 再判断 i + l_u8_offset >= u8_errcode_Write 才 break。当 u8_errcode_Write == ERRCODE_FIFO_SIZE(10) 且最后一项命中删除时,会读出 u32_errcode_buf[10](数组只有 10 个元素),属越界读。
  2. 差分扫描会漏事件:镜像在每轮末尾被整体覆盖,若某故障位在 500ms 窗口内"置位—清零"自恢复,则永久不会产生日志;反之若轮询被长任务挤占,也会漏记中间态。
  3. 差分表不完整即丢失变化:u32_all 的比较只是"快速跳过"的门闩,但真正逐位扫的只有表中列出的 FAULT_CODE_PAIR_T。若实时位域中某位置位而表中没有对应项,则该位变化永远不会被记录(例如 EMS 表里没有 E0018~E0030 等区段)。
  4. 硬编码簇数:BMS 保护/告警循环用 13、package_display_error_code 里 BMS 显示位只 OR 了 u_bms_fault_log[0..6]、EVC-II 只 OR 了 [0..3],与 BATTERY_MAX_NUM(12)+1、MAX_EVC_II_NUM(4) 虽然当前一致,但都不是用宏表达,扩簇时极易漏改。
  5. error_log_data_addr_save 复用同一个 l_u8_res:三段重试共用同一变量,且该变量初值 FALSE(0) 与 FLASH_ERR(0) 同值;虽然三段各自先赋值再判断、逻辑上不影响结果,但函数返回值 l_u8_res 未被使用,调用方无法感知地址保存是否成功。
  6. 发送指针推进公式的 off-by-one 嫌疑(fault_warn_log.c:381/396):(FLASH_ADDR_TO_SECTOR(save_addr) + 1) * FLASH_SECTOR_SIZE 得到的是"保存地址所在扇区的下一个扇区首地址";当 save_addr 恰好落在扇区首地址时,会跳过整整一个扇区(4096B)未读日志,造成日志丢失。
  7. get_show_errcode 不做边界检查(fault_warn_log.c:1877):仅判断 FIFO 是否为空,直接用调用方传入的 offset 索引 u32_errcode_buf[10]。hmi/ui/ui_main.c 与 net/ems.c:850 必须自行用 lcd_get_errcode_buf_len() 约束 offset,否则越界读。
  8. read_bat_heat_fault_flag 在头文件中重复声明:fault_warn_log.h:727 声明 void set_bat_heat_fault_flag(...),fault_warn_log.h:728 前一行缺少换行分隔,紧接着写 extern u8 read_bat_heat_fault_flag(void);——extern 在函数声明上虽是合法的,但风格与同文件其它声明不一致。
  9. erase_error_log 的整块计数可疑(fault_warn_log.c:1641):FLASH_ADDR_TO_BLOCK(l_u32_end_block_addr - l_u32_start_block_addr) 是对"两地址之差"取整,而末尾零头扇区又以 l_u32_end_block_addr 为起点重算,边界上可能少擦或多擦一个块,需实机验证。
  10. 魔法数字:3*60*1000(LCD 历史刷新周期)、180(无,那是 resume 模块)、50(历史查询上限)、10(FIFO 深度)、0..6、13、[0..3] 等硬编码散落在函数体内。
  11. DEBUG_FLASH_DATA_STORE 宏与本目录 fault_warn_log.h:30 和 flash_data_store.h:20 中同名宏重复定义,本文件实际包含的是 fault_warn_log.h 的版本,容易误判调试开关生效范围。
  12. STORE_ERROR_LOG_DATA_T.s32_fault_value 字段从未赋值,落盘数据恒为 0(配合 u8_reserve[12] 使结构凑满 32 字节,可整除 4096 的扇区大小)。