b7c0889cc7
用户裁定「不要用字母加数字的编号,语义标识是最好的」后的批次二代码半(道 ui-param 执行,逐文件站点数与 自证见其交付)。唯一口径 = 映射表 ci-artifacts/lprot_map.tsv 的功能名列原文,**零自造同义词**;L2.5 与 L-TEST 经实测各 0 处(不是本族),TC 族一字未动。 固件 22 文件 128 处(adc_task.c 21、phasor.c 22、phasor.h 13…),主机测试 13 文件 87 处(pha sor_test.c 57…);设计文档指针新增 19 行,另 16 只文件本来就写着规划文档 ⇒ 不重复加。 **两条只有真改过 215 处才会踩到的坑,都写进注释规范实践**: · 指针**不能接在原句尾部**——那会替原文一个未闭合的半括号封口,实测咬坏 App/algo/sample_ring.h 这类 跨行句 ⇒ 指针一律**单独成行**; · 号删掉会留下**叠词**(「自检失败闭锁 闭锁判定」「定值校验和 定值巡检」)⇒ 复扫并收口 4 处,措辞只用 映射名本身;具体对象需要留住时写成「自检失败闭锁(采样故障闭锁)」。 自证(不靠嘴说):改前把 35 只文件原文备份到仓外 temp,逐文件比 `/*`、`*/` 计数、三类括号计数、行数增量 恰等于指针行数、全角括号增删相等、残留号 0 ⇒ **35/35 通过**;Lead 复核后跑权威 @build **0 错 0 警**, Program Size `Code=233900 RO=26104 RW=1536 ZI=136808` —— **与三条道各自改前改后测的四数逐 字节同数**, 这就是「只动注释与文本」的机器证据;八套主机单测 exit 0,cppcheck 按钩子参数零发现,coding-standard 0。 文件头「修改记录」里的号**一并换名、不还原**(Lead 裁定):这些号是全仓退役的,留一个查无此号的引用比 留一条改过名的条目更坏——「冻结历史不回改」保护的是**别替历史改口**,不是保护一个再也查不到的字符串; id-check 对变更记录行本就豁免,两种选择都不影响门禁。
103 lines
3.9 KiB
C
103 lines
3.9 KiB
C
/*
|
||
* 模块名称:prot_set_store(B7 定值持久化)——实现
|
||
* 模块功能:见 prot_set_store.h。blob 格式/校验/原子装载全在 prot_set.c
|
||
* (纯逻辑,主机单测覆盖),本文件只做"读文件→parse、
|
||
* serialize→原子写"的平台胶水。
|
||
* 文件口径:"/prot_set.bin"(卷根,8.3 合规,FF_USE_LFN=0 约束);
|
||
* 原子写临时名由 cfg_store_write_atomic 按目标目录推导
|
||
* (固定 config.TMP),与 /config.ini 的保存同在 defaultTask
|
||
* 串行执行,无并发竞争。
|
||
* 创建日期:2026-10-12(B7)
|
||
*/
|
||
#include "prot_set_store.h"
|
||
|
||
#include <stddef.h>
|
||
|
||
#define DBG_TAG "[CFG]"
|
||
#include "dbg_log.h"
|
||
|
||
#include "cfg_file_store.h"
|
||
#include "prot_set.h"
|
||
|
||
#define PROT_SET_STORE_PATH "/prot_set.bin"
|
||
|
||
/* blob 收发缓冲(静态:defaultTask 栈深已是全项目最深链,勿再压局部 blob;
|
||
* B8 定值表 32→40 项 → blob 144→176 B,随 PROT_SET_BLOB_SZ 自动适配) */
|
||
static uint8_t s_blob[PROT_SET_BLOB_SZ];
|
||
|
||
/*
|
||
* 函数功能:从小端缓冲读 16 位值(仅头部判别用,与 prot_set.c 内部同字节序)
|
||
* 入口参数:p - 读位置
|
||
* 返 回 值:值 uint16_t
|
||
*/
|
||
static uint16_t s_ld16(const uint8_t *p) {
|
||
return (uint16_t)((uint32_t)p[0] | ((uint32_t)p[1] << 8));
|
||
}
|
||
|
||
/*
|
||
* 函数功能:从小端缓冲读 32 位值
|
||
* 入口参数:p - 读位置
|
||
* 返 回 值:值 uint32_t
|
||
*/
|
||
static uint32_t s_ld32(const uint8_t *p) {
|
||
return (uint32_t)p[0] | ((uint32_t)p[1] << 8) | ((uint32_t)p[2] << 16)
|
||
| ((uint32_t)p[3] << 24);
|
||
}
|
||
|
||
/*
|
||
* 函数功能:开机装载定值 blob
|
||
* 入口参数:无
|
||
* 返 回 值:0 已装载 / 1 文件缺失或读失败(保持默认)/
|
||
* 2 版本或项数换代(旧档被拒,保持默认;本函数已落 INFO 日志)/
|
||
* -1 损坏被拒
|
||
* 函数说明:读失败与"文件不存在"同归 1——启动期卷锁无竞争(本任务独占
|
||
* bring-up),try-lock 失败即真 I/O 故障,此时保持出厂默认并让
|
||
* 调用方按"无档"处理是安全侧(定值仍封存自洽,定值校验和不误锁)。
|
||
* **换代与损坏分开**(B8):magic 完好但 ver/cnt 与当前固件不符 =
|
||
* 定值表升级(如 B8 32→40 项),是**预期升级路径**不是损坏 →
|
||
* 归 2 并打 INFO("version change"措辞),调用方不得按 CORRUPT
|
||
* 报 ERROR/自检留痕;magic 或校验对被破坏才是 -1。
|
||
*/
|
||
int prot_set_store_load(void) {
|
||
size_t nread = 0u;
|
||
|
||
if (cfg_store_read(PROT_SET_STORE_PATH, s_blob, sizeof(s_blob), &nread) != 0) {
|
||
return 1;
|
||
}
|
||
if (prot_set_store_parse(s_blob, (uint32_t)nread) == 0) {
|
||
return 0;
|
||
}
|
||
/* 拒绝原因分流:头部 magic 完好 + 版本/项数与当前固件不符 = 换代 */
|
||
if ((nread >= (size_t)PROT_SET_BLOB_HDR_SZ)
|
||
&& (s_ld32(s_blob) == (uint32_t)PROT_SET_BLOB_MAGIC)
|
||
&& ((s_ld16(s_blob + 4u) != (uint16_t)PROT_SET_BLOB_VER)
|
||
|| (s_ld16(s_blob + 6u) != (uint16_t)PS_ID_COUNT))) {
|
||
DBG_INFO("prot set blob version change (ver=%u cnt=%u), defaults in use",
|
||
(unsigned)s_ld16(s_blob + 4u), (unsigned)s_ld16(s_blob + 6u));
|
||
return 2;
|
||
}
|
||
return -1;
|
||
}
|
||
|
||
/*
|
||
* 函数功能:落盘当前定值(消费脏标志;失败回置等重试)
|
||
* 入口参数:无
|
||
* 返 回 值:0 无待写或成功 / -1 写失败
|
||
*/
|
||
int prot_set_store_save(void) {
|
||
uint32_t len = 0u;
|
||
|
||
if (prot_set_dirty_take() == 0u) {
|
||
return 0;
|
||
}
|
||
if (prot_set_store_serialize(s_blob, (uint32_t)sizeof(s_blob), &len) != 0) {
|
||
prot_set_dirty_mark();
|
||
return -1;
|
||
}
|
||
if (cfg_store_write_atomic(PROT_SET_STORE_PATH, s_blob, (size_t)len) != 0) {
|
||
prot_set_dirty_mark(); /* 卷忙/写失败:脏保留,iec104Task 下轮再通知 */
|
||
return -1;
|
||
}
|
||
return 0;
|
||
}
|