fix(wave): 落盘道改覆盖写,修回放页全板「该段不可读」
段名是 100 个槽位的轮转复用,而写者用 FA_OPEN_APPEND 打开:槽位复用时撞上 同名旧文件,新段接在旧段尾巴上,文件长成 5250 的整数倍。回放页读侧按单段 判 size == total,于是逐件落进 UI_WAVE_REJ_LEN(reject=2),全板没有一段 放得出来。 板级取证(100 件全部归档到 ci-artifacts/wave_append_backup_20261110/): /wave 共 1868 段、9,807,000 B,尺寸全为 5250 的整数倍,恰好等于 5250 的 文件数为 0;逐段过 wave_read 校验全部合法、零损坏——数据一直是好的,只是 容器尺寸与写者语义相抵。 修法(用户裁定取写者截断,否掉读侧多段感知):打开模式改为 FA_WRITE|FA_CREATE_ALWAYS。本移植的覆盖分支会 remove_chain 并清零目录项 FileSize,是真截断;FA_CREATE_ALWAYS 单独用不含 FA_WRITE,两个位必须同给。 日志七本与 soe.log 仍用追加(靠历史累积,语义正确),读侧口径不动。 板端验收:新段尺寸恰好 5250 B;对已有 28 段的 WAVE00.BIN(147,000 B)录 一次当场变 5250 B,全目录总字节减 141,750 = 147,000 - 5,250。回放页从 bad 态(与黄金参考 shot_wave_play_bad 逐比特相同)转为正常态,页眉 24/24 行、页脚 20/20 行与 shot_wave_play 逐字节一致。 文档:故障录波设计说明 §5.2 陷阱表改打开模式完整口径,§10 新增收口记录; 带日期戳的 11-07 取证归档正文按当时口径冻结,只加一条口径已被推翻的指向。
This commit is contained in:
+12
-4
@@ -629,9 +629,17 @@ static FRESULT storage_bring_up(FATFS *fs) {
|
||||
* 函数说明:所有权按 docs/子系统设计/故障录波设计说明.md §5.1——环的生产者是
|
||||
* adcTask,本道是唯一落盘消费者;跨任务握手只认 wave_ring_sealed()。
|
||||
* 本道承担五条口径:
|
||||
* ① 打开一律 FA_WRITE|FA_OPEN_APPEND:本移植 FA_OPEN_APPEND 不含 FA_WRITE
|
||||
* (docs/架构设计/STM32F4-Base存储架构说明.md §10.1 陷阱一),少写位
|
||||
* f_write 恒 FR_DENIED;
|
||||
* ① 打开一律 FA_WRITE|FA_CREATE_ALWAYS(**覆盖,不是追加**):段名是 100 个
|
||||
* 槽位的轮转复用(wave_store.h 的「号 0..99 轮转覆盖,写满回绕盖最老的」),
|
||||
* 槽位被复用时同名文件已存在——用 FA_OPEN_APPEND 会把新段接在旧段尾巴上,
|
||||
* 文件长成 5250×N,而回放页的单段读侧要求 size == 5250,于是逐件判
|
||||
* 「长度废」(reject=2),全板没有一段放得出来。2026-11-10 板级实测:
|
||||
* 100 个文件 / 1868 段全部合法、零损坏,纯粹是容器尺寸与写侧追加语义相抵。
|
||||
* 本移植 FA_CREATE_ALWAYS 会 remove_chain 并清零目录项的 FileSize,
|
||||
* 是真正的截断(Lib/FatFs/ff.c 的 f_open 覆盖分支);
|
||||
* 注意 FA_CREATE_ALWAYS 单独用**不含 FA_WRITE**(本移植旧式标志位),
|
||||
* 缺写位 f_write 恒 FR_DENIED(docs/架构设计/STM32F4-Base存储架构说明.md
|
||||
* §10.1 陷阱一),两个位必须同时给;
|
||||
* ② 每次 f_write 比对写回字节数:本移植簇分配失败返 FR_OK+短写无错误码
|
||||
* (同处陷阱二),短写一律判失败;
|
||||
* ③ 轮转号由本道自持(lead 转告(b)):ring.seg_idx 只是本 boot 本地计数,
|
||||
@@ -766,7 +774,7 @@ static void wave_store_drain(void) {
|
||||
s_wnext_idx) <= 0) {
|
||||
why = "seg_path";
|
||||
} else {
|
||||
fr = f_open(&s_wfil, s_wpath, FA_WRITE | FA_OPEN_APPEND);
|
||||
fr = f_open(&s_wfil, s_wpath, FA_WRITE | FA_CREATE_ALWAYS);
|
||||
if (fr != FR_OK) {
|
||||
why = "f_open";
|
||||
} else {
|
||||
|
||||
+38
-1
@@ -158,7 +158,7 @@ flowchart TD
|
||||
| 陷阱 | 事实出处 | 本波处置 |
|
||||
|---|---|---|
|
||||
| **取窗竞态** | `App/algo/sample_ring.c` 的 `sample_ring_window()` 没有临界区(读 `s_head` 后逐点拷),现在只有 adcTask 同任务调用才安全 | 录波**不复用它**:adcTask 在自己的节拍里取「本拍帧」压专用环;跨任务只传递「已封存」标志,杜绝跨任务读活缓冲 |
|
||||
| **FatFs 追加写** | 该移植 `FA_OPEN_APPEND` 不含 `FA_WRITE`,且 `f_write` 簇分配失败时返回 `FR_OK` 加短写、无错误码(`docs/架构设计/STM32F4-Base存储架构说明.md` §10.1) | 打开一律 `FA_WRITE\|FA_OPEN_APPEND`;**判成功必须比对写回字节数**,短写按失败处理(丢段 + 日志),绝不当成功记账 |
|
||||
| **FatFs 打开模式** | ① 该移植 `FA_OPEN_APPEND` 与 `FA_CREATE_ALWAYS` 都**不含** `FA_WRITE`,缺写位 `f_write` 恒返 `FR_DENIED`;② `f_write` 簇分配失败时返回 `FR_OK` 加短写、无错误码(`docs/架构设计/STM32F4-Base存储架构说明.md` §10.1) | 录波段**一律 `FA_WRITE\|FA_CREATE_ALWAYS`(覆盖,不是追加)**——段名是 100 槽轮转复用,槽位复用时会撞上同名旧文件,追加语义会把新段接在旧段尾巴上,文件长成 5250×N 而读侧只认单段长度,全板判废(2026-11-10 收口,见 §10);日志类(一次 `f_open→写→f_close`、靠历史累积的)才用 `FA_WRITE\|FA_OPEN_APPEND`。**判成功必须比对写回字节数**,短写按失败处理(丢段 + 日志),绝不当成功记账 |
|
||||
| **只能 8.3 短名** | 出处同一张存储架构说明的短名限制:`FF_USE_LFN=0`,不得以点开头、不得长名 | 文件名 = WAVE 加两位十进制再加 .BIN,共 100 个名字轮转覆盖;目录 /wave(与 /log 平级,FTP 根下可见) |
|
||||
| **落盘途中环被解冻、甚至已换段**(实现期复核新增第四条,2026-10-29) | adcTask 优先级高于 defaultTask:搬段窗口里 adcTask 可能正好走到 SEALED 滞留 2 s 自弃,甚至已经封出下一段。**数据区 CRC 是对「本道实际读到的字节」算的**,半新半旧的段照样自洽——长度等式照过、两个 CRC 照对,文件骗得过任何读者,也骗过我们自己 | 写完关档后**复检环侧身份**:`wave_ring_sealed()` 仍为 1,且 `wave_ring_get_stat()` 的 `last_t0_ms` 与 `last_seq` 跟本道开始搬时那份段头一致;不符即走既有失败路——unlink 本道开过的文件 + `write_done(-1)`(此时多半回 `E_STATE`,环侧 `err` 已由自弃计过,不重复补账)+ 段号不推进(下一段同号重写覆盖)+ 单条 `[ERR] … seg drop: ring abandoned` 留痕。落点 `App/task/default_task.c`:818 到 823 行(复检与弃段处置),统一留痕打印在 843 行。**2026-11-07 板级已闭环**(#84 台架远程轮:临界占卷命中三判据逐条对上,见 §10「bench 定时自抓与占卷弃段观察闭环记录」小节) |
|
||||
|
||||
@@ -573,6 +573,7 @@ ui_sink 17 / wave_ring 113 / wave_store 170 / wave_trig 110 全过;Keil 0 错
|
||||
`default_task.c` 落盘道;11-06 的 STOR 全删全建掩盖了生长面)——拼接件对回放页单段读侧
|
||||
(`size == total`)逐件判长度废,1866 段逐段过 `wave_read` 校验**全部合法**(零损坏,纯口径
|
||||
相抵)。该面是否收口(写者截断 vs 读侧多段感知)是新的产品决定,本轮只如实记账,不并票。
|
||||
→ **2026-11-10 已裁定并收口为写者截断**,见下「段文件跨开机追加缺陷收口记录」。
|
||||
|
||||
板级验收(2026-11-07 台架远程轮,烧录经口头「烧」确认;证据
|
||||
`docs/测试说明/测试数据/wave_fix_20261107/`):**F1 五条 / F2 五条全过**——F1-1 页关投放
|
||||
@@ -588,6 +589,42 @@ ui_sink 17 / wave_ring 113 / wave_store 170 / wave_trig 110 全过;Keil 0 错
|
||||
缺失即其重试成功不打日志的一面;间歇边界(是否断电重连可消)未在本轮验证。详见证据目录 README 的
|
||||
Before/After 表与串口原文。
|
||||
|
||||
### 段文件跨开机追加缺陷收口记录(2026-11-10,写者改截断)
|
||||
|
||||
**问题**:手动录波后进回放页,一个波形都看不到,恒显「该段不可读」。根因不在数据,在文件形态:
|
||||
段名是 100 个槽位轮转复用(`App/algo/wave_store.h` 的「号 0..99 轮转覆盖,写满回绕盖最老的」),
|
||||
而写者用 `FA_OPEN_APPEND` 打开——槽位被复用时撞上同名旧文件,新段接在旧段尾巴上,文件长成
|
||||
5250×N。读侧(`App/task/ui_task.c` 的 `ui_task_wave_load_head`)按单段口径判 `size == total`,
|
||||
于是逐件落进 `UI_WAVE_REJ_LEN`(reject=2),全板没有一段放得出来。
|
||||
|
||||
**板级取证**(FTP 直读 `192.168.31.100`,admin/admin;100 件全部归档到
|
||||
`ci-artifacts/wave_append_backup_20261110/`):`/wave` 共 100 个 `WAVE00.BIN`…`WAVE99.BIN`、
|
||||
9,807,000 B = 1868 段;尺寸 10,500~147,000 B **全部是 5250 的整数倍**,**恰好等于 5250 的文件数为 0**;
|
||||
用 `test/host/wave_read.py` 的 `parse_segment()` 逐段校验 **1868 段全过、零损坏**。也就是说数据
|
||||
一直是好的,只是容器尺寸与写者语义相抵。
|
||||
|
||||
**修复(用户裁定取「写者截断」,否掉「读侧多段感知」——后者改动面大,还要同步 PC 侧
|
||||
`wave_read.py` 与 golden 帧)**:`App/task/default_task.c` 落盘道打开模式
|
||||
`FA_WRITE|FA_OPEN_APPEND` → **`FA_WRITE|FA_CREATE_ALWAYS`**。本移植 `Lib/FatFs/ff.c` 的 `f_open`
|
||||
覆盖分支会 `remove_chain` 并把目录项 `DIR_FileSize` 清零,是真截断;⚠ `FA_CREATE_ALWAYS`
|
||||
单独用**不含 `FA_WRITE`**(旧式标志位),缺写位 `f_write` 恒 `FR_DENIED`,两个位必须同时给。
|
||||
|
||||
**验收证据**(本工作树,串口 COM4 + TCP 7003):
|
||||
- Keil `0 Error(s), 0 Warning(s)`;烧录 `Programming Complete` / `Application started` / `RC: 0` / `FLASH: OK`,
|
||||
固件戳 `Nov 10 2026 22:03:04` 与本次构建一致;启动锚点全过(`App init OK` / `Network Init` /
|
||||
`net init: OK` / `protect task start: cycle=20ms elm=9` / 各 `[STACK]`),唯一 `[ERR]` 为既有的
|
||||
`[ERR][I104] i104: bind port 2404 FAIL, retry in loop`(既有面,非本次回归)。
|
||||
- **截断面**:清空 `/wave` 后触发一次手动录波,新段 `WAVE01.BIN` 尺寸**恰好 5250 B**;
|
||||
另在清理前对已有 28 段的 `WAVE00.BIN`(147,000 B)录一次,尺寸当场变成 **5250 B**、
|
||||
全目录总字节 9,807,000 → 9,665,250(差值 141,750 = 147,000 − 5,250),覆盖写落地。
|
||||
- **画面面**:回放页从 `wave_play_bad` 态(ink=408,与 `simulator/tests/ref/shot_wave_play_bad.bin`
|
||||
**逐比特相同**)转为正常态(ink=1087)——页眉 24/24 行、页脚 20/20 行与黄金参考
|
||||
`shot_wave_play.bin` **逐字节一致**,只有波形主体不同(真机信号 vs 模拟器注入,预期内);
|
||||
连按 12 次换段,ink 在 1065~1088 间变化,段间波形确实不同。
|
||||
|
||||
**未改动**:日志七本与 `soe.log` 仍用 `FA_WRITE|FA_OPEN_APPEND`(它们靠历史累积,语义正确);
|
||||
读侧逐件判 `size == total` 的口径**保持不变**——现在写者保证单段长度,读侧不需要多段感知。
|
||||
|
||||
---
|
||||
|
||||
## 11. 与 `docs/算法/采集与算法层设计说明.md §13` 的口径变更(三处)
|
||||
|
||||
@@ -11,6 +11,10 @@ PNG 为 4× 放大目检件(非判据)。
|
||||
`test/host/wave_read.py` 校验**全部合法、零损坏**)——写者 `FA_OPEN_APPEND` 跨开机累积
|
||||
属既有设计,回放页单段读侧(`size == total`)按口径逐件判「长度废」:全板无可放段。
|
||||
全量原件 RETR 备份 + sha256 台账在轮末**逐字节还原**(见「收工」节)。
|
||||
⚠ 上面这段描述的是**当时**(2026-11-07)的盘面;「追加属既有设计」的口径已于 2026-11-10
|
||||
推翻并收口为写者截断(`App/task/default_task.c` 改 `FA_WRITE|FA_CREATE_ALWAYS`),
|
||||
收口记录见 `docs/子系统设计/故障录波设计说明.md` §10「段文件跨开机追加缺陷收口记录」。
|
||||
本目录是带日期的取证归档,正文按当时口径冻结、不回改。
|
||||
- 串口唯一枚举 CH340 = **COM4**(仓库 `.serialtest/config.json` 钉 COM3 已过时,本仓文件
|
||||
未动,用 `$env:DSH_SERIAL_CONFIG` 覆盖);板端 FTP `admin/admin`。
|
||||
- 到场固件 = 修复前构建(当日 01:00 已在跑,串口捕获窗口起点晚于该启动,构建戳不可证;
|
||||
|
||||
@@ -1,15 +1,15 @@
|
||||
{
|
||||
"built_at": "2026-11-10T11:42:28+08:00",
|
||||
"fingerprint": "bd97996ef0586e185e13beca01d36f43fdbc118c69c0833166065752aacae96c",
|
||||
"built_at": "2026-11-10T22:31:07+08:00",
|
||||
"fingerprint": "5080b00d80af5604476422c1afa383cb09e782e6bb76aa2abf9e96a77d5c60fd",
|
||||
"fingerprint_files": 1479,
|
||||
"fingerprint_source": "git-index",
|
||||
"gated_regions": [
|
||||
"RW_IRAM1",
|
||||
"RW_CCM"
|
||||
],
|
||||
"git_head": "ae09c5737a0bc56cddc469fc2ca0afe78e6cbd74",
|
||||
"git_head": "7b05d7bfd40fafa514e166d3fda5270f2b040c2b",
|
||||
"map": "MDK-ARM/STM32F407-Demo/STM32F407-Demo.map",
|
||||
"map_mtime": 1794282125,
|
||||
"map_mtime": 1794321057,
|
||||
"pct": {
|
||||
"ER_IROM1": 27.31,
|
||||
"RW_CCM": 87.89,
|
||||
|
||||
Reference in New Issue
Block a user