refactor(编号): 自愈层号与 timeSync 挂起、CubeMX 三层、采集链层名清号(代码面)

批次六余账之二(代码与脚本面)。四族都是「批次一 / 三c 改了文档、漏了代码」的半改
状态。

- 日志自愈:「L1 文件级自愈」→「文件级自愈」、「L2 错误去重」→「错误去重」(正文
  本来就这么叫,层号纯属多余):App/log/soe_store.c、sys_log_mcu.c 三处、
  test/host/sys_log_mcu 的测试与假件头共 10 处。
- timeSync:「L3 pending 化」→ 挂起请求 / pending 化——这条口径早写在记忆里,
  今天才算全仓一致。App/sync/time_sync.c 3 处。
- CubeMX 防丢失三层优先级:scripts/check_cubemx_survival.py 6 处「由 L3 升级为
  L2」「L2 受保护」「L3 兜底」→ 写进 .ioc / 搬进 USER CODE 区 / 审计兜底;变迁史
  句子按「换号留事实」改写、日期原样保留。
- 采集链旧层名:App/README.md「采集与算法层(L1/L2/L3)」→「采集与算法层」;
  protect_task.c/.h「(L3 板端接线,B5)」→「(板端接线,B5)」。
- phasor 断言文案 19 处:改为 ASCII 的 phasor-in ring(C 字面量必须纯 ASCII)。
  改前先证明这些串无耦合——全仓只有本文件含它们、harness 只看 returncode 与汇总
  标记;改后 phasor 57/57 与基线同数。
- 零行为:剥注释 + 套登记表后与 HEAD 逐字节 / AST 相同;sys_log_mcu 141/141、
  phasor 57/57、watchdog 47/47、freq 46/46 均与动手前基线同数。
- 同一四族的文档面(CubeMX 30、采集链 5、菜单层级 2、双写 14)由下一笔收。
This commit is contained in:
2026-10-28 18:52:37 +08:00
parent 6572591181
commit da36f4ba56
10 changed files with 41 additions and 41 deletions
+19 -19
View File
@@ -312,9 +312,9 @@ static void tc_ring(void) {
int ok;
sample_ring_init();
CHECK(sample_ring_filled() == 0u, "L2-in ring: init clears fill");
CHECK(sample_ring_frames() == 0u, "L2-in ring: init clears frame counter");
CHECK(sample_ring_window(ADC_SEM_UA, 20u, w) == -2, "L2-in ring: window before data -> -2");
CHECK(sample_ring_filled() == 0u, "phasor-in ring: init clears fill");
CHECK(sample_ring_frames() == 0u, "phasor-in ring: init clears frame counter");
CHECK(sample_ring_window(ADC_SEM_UA, 20u, w) == -2, "phasor-in ring: window before data -> -2");
/* 前 3 帧:UA = 100/200/300 */
ok = 1;
@@ -323,15 +323,15 @@ static void tc_ring(void) {
f[ADC_SEM_UA] = (float)(100 * (i + 1));
if (sample_ring_push_frame(f, (uint8_t)ADC_SEM_COUNT) != 0) { ok = 0; }
}
CHECK(ok, "L2-in ring: 3 frames pushed OK");
CHECK(sample_ring_filled() == 3u, "L2-in ring: filled == 3");
CHECK(ok, "phasor-in ring: 3 frames pushed OK");
CHECK(sample_ring_filled() == 3u, "phasor-in ring: filled == 3");
CHECK((sample_ring_window(ADC_SEM_UA, 3u, w) == 0)
&& (w[0] == 100.0f) && (w[1] == 200.0f) && (w[2] == 300.0f),
"L2-in ring: window is chronological (old -> new)");
"phasor-in ring: window is chronological (old -> new)");
/* 通道隔离:其它语义通道不应被 UA 的写入污染 */
CHECK((sample_ring_window(ADC_SEM_IB, 3u, w) == 0)
&& (w[0] == 0.0f) && (w[1] == 0.0f) && (w[2] == 0.0f),
"L2-in ring: channels are independent");
"phasor-in ring: channels are independent");
/* 推到 45 帧(> DEPTH=40)→ 回绕 */
for (i = 3; i < 45; i++) {
@@ -339,25 +339,25 @@ static void tc_ring(void) {
f[ADC_SEM_UA] = (float)i;
(void)sample_ring_push_frame(f, (uint8_t)ADC_SEM_COUNT);
}
CHECK(sample_ring_filled() == SAMPLE_RING_DEPTH, "L2-in ring: fill saturates at DEPTH");
CHECK(sample_ring_frames() == 45u, "L2-in ring: frame counter is NOT saturated");
CHECK(sample_ring_filled() == SAMPLE_RING_DEPTH, "phasor-in ring: fill saturates at DEPTH");
CHECK(sample_ring_frames() == 45u, "phasor-in ring: frame counter is NOT saturated");
ok = (sample_ring_window(ADC_SEM_UA, 20u, w) == 0);
for (i = 0; i < 20; i++) { if (w[i] != (float)(25 + i)) { ok = 0; } }
CHECK(ok, "L2-in ring: wrapped window == last 20 values, in order");
CHECK(ok, "phasor-in ring: wrapped window == last 20 values, in order");
ok = (sample_ring_window(ADC_SEM_UA, (uint8_t)SAMPLE_RING_DEPTH, w) == 0);
for (i = 0; i < (int)SAMPLE_RING_DEPTH; i++) { if (w[i] != (float)(5 + i)) { ok = 0; } }
CHECK(ok, "L2-in ring: full-depth window == last DEPTH values, in order");
CHECK(ok, "phasor-in ring: full-depth window == last DEPTH values, in order");
CHECK(sample_ring_window(ADC_SEM_UA, 0u, w) == -1, "L2-in ring: n=0 rejected");
CHECK(sample_ring_window(ADC_SEM_UA, 0u, w) == -1, "phasor-in ring: n=0 rejected");
CHECK(sample_ring_window(ADC_SEM_UA, (uint8_t)(SAMPLE_RING_DEPTH + 1u), w) == -1,
"L2-in ring: n > DEPTH rejected");
"phasor-in ring: n > DEPTH rejected");
CHECK(sample_ring_window((adc_semantic_t)ADC_SEM_COUNT, 20u, w) == -1,
"L2-in ring: out-of-range channel rejected");
CHECK(sample_ring_window(ADC_SEM_UA, 20u, NULL) == -1, "L2-in ring: NULL out rejected");
CHECK(sample_ring_push_frame(NULL, (uint8_t)ADC_SEM_COUNT) == -1, "L2-in ring: NULL frame rejected");
CHECK(sample_ring_push_frame(f, 3u) == -1, "L2-in ring: wrong frame length rejected");
"phasor-in ring: out-of-range channel rejected");
CHECK(sample_ring_window(ADC_SEM_UA, 20u, NULL) == -1, "phasor-in ring: NULL out rejected");
CHECK(sample_ring_push_frame(NULL, (uint8_t)ADC_SEM_COUNT) == -1, "phasor-in ring: NULL frame rejected");
CHECK(sample_ring_push_frame(f, 3u) == -1, "phasor-in ring: wrong frame length rejected");
}
/* ===================== TC-PHASOR-020/021/022:实例层 + 滑动窗 + 双区 ===================== */
@@ -538,13 +538,13 @@ int main(void) {
tc_harmonic();
printf("-- frequency sensitivity --\n");
tc_freqdev();
printf("-- L2 input sample ring --\n");
printf("-- phasor input sample ring --\n");
tc_ring();
printf("-- 基波相量实例 / 每 1 ms 滑动窗刷新 / 双区指针原子交换 instance layer --\n");
tc_instances();
printf("-- 双区指针原子交换 dual-zone swap --\n");
tc_dualzone();
printf("-- L2 zero / init --\n");
printf("-- phasor zero / init --\n");
tc_zero();
printf("\n=== Phasor Tests: %d/%d PASSED (failed=%d) ===\n",
+2 -2
View File
@@ -1,13 +1,13 @@
/*
* 模块名称:主机侧单测桩 - dbg_log.h(sys_log_mcu 套件专用)
* 模块功能:DBG_* 换成计数,让"写故障只报第一次(L2 去重)"与"挂载失败重试不刷屏"
* 模块功能:DBG_* 换成计数,让"写故障只报第一次(去重)"与"挂载失败重试不刷屏"
* 成为可断言的行为。
*
* ⚠ 仅供 test/host/sys_log_mcu/ 使用,不参与 MCU 构建。
*
* 为什么本模块尤其需要计数而不是直通打印:sys_log_mcu.c 的 s_append_rec() 里
* 有一条刻意设计的静默规则(源码注释)——
* "L2 错误去重:持续故障只报第一次,恢复前静默(消除每次开机同一错误刷屏)"
* "错误去重:持续故障只报第一次,恢复前静默(消除每次开机同一错误刷屏)"
* 直通 printf 只能让人眼看,"到底报了几次"必须可数才能钉住;而另一头,
* 挂载幂等里的"建 /log 失败日志去重(成功复位)"同样是次断言。
*
+4 -4
View File
@@ -3,7 +3,7 @@
* 模块功能:在 PC 上离线验证 App/log/sys_log_mcu.c 的四族契约——
* A 64B 定长记录格式(时间戳 / epoch ASCII / 描述三段 + 截断 + 占位)
* B 写侧(单条 s_append_rec、批量 s_append_many、日志读写放大收口的"一批一次
* open/write/close"、容量轮转、L1 自愈、L2 留痕去重、卷锁 try)
* open/write/close"、容量轮转、文件级自愈、留痕去重、卷锁 try)
* C 排空(syslog_drain 的 preboot + 队列两条来源、换文件分批、
* 失败回投不丢条目、-3 退回慢路径)
* D 读侧(日志读写放大收口的 8 条滑动窗口 + 写者代数失效 + 越界/忙/短读处置)
@@ -1634,7 +1634,7 @@ static void tc_name_rules(void)
(void)ff_fake_mkfile(P_SELFTEST, NULL, SYSLOG_REC_SIZE); /* 邻居文件 */
(void)ff_fake_mkfile("/config.ini", NULL, 12u); /* 同卷别的东西 */
/* D 项整改后:名字/参数类码**一次都不许 unlink**(旧实现每轮删一次自己的
* 历史日志、且永远修不好)。留痕仍受 L2 去重,只 1 条。 */
* 历史日志、且永远修不好)。留痕仍受去重约束,只 1 条。 */
ff_fake_inject_rc(P_RUN, FF_FAKE_OP_OPEN, FR_INVALID_NAME, 200);
for (i = 0u; i < 20u; i++) {
(void)s_append(SYSLOG_RUN, "bad-name");
@@ -1661,7 +1661,7 @@ static void tc_extra_branches(void)
printf("-- TC-SYSLOG-090..100 remaining branch coverage --\n");
/* 090 批量路径的 L1 自愈:open 失败一次 -> unlink + 重开 -> 整批照常落盘
/* 090 批量路径的文件级自愈:open 失败一次 -> unlink + 重开 -> 整批照常落盘
* (这条钉的是 s_append_many 里那段"和单条同一份自愈表";漏了它,
* FTP 侧删过文件之后的第一批日志就会整批丢) */
reset_all();
@@ -1911,7 +1911,7 @@ static void tc_selfheal_codes(void)
* 测不到,只能从"恢复后第一次真失败仍立刻留痕"反证它没被置位) */
reset_all();
ready_only();
/* s_append_rec 的 L2 去重位是函数级 static,外部清不了:先用一次成功写复位 */
/* s_append_rec 的去重位是函数级 static,外部清不了:先用一次成功写复位 */
ok = (s_append(SYSLOG_RUN, "reset-dedup") == 0);
g_sys_err_count = 0;
lock_busy_next(1);