整理 App 与 test 目录:按职责分子目录并同步全库引用
This commit is contained in:
@@ -34,13 +34,13 @@ Interpretation (per AGENTS.md): exit code 0 = PASS (0 errors, 0 warnings). 1/2+
|
||||
|
||||
### Step 2 — Flash + capture boot log (one orchestrated call)
|
||||
|
||||
Use `test/run_boot_test.py` (pure-stdlib Python, 2026-09-20 起替代 PowerShell 版) which opens the port + clears the log (arming),
|
||||
Use `test/host/run_boot_test.py` (pure-stdlib Python, 2026-09-20 起替代 PowerShell 版) which opens the port + clears the log (arming),
|
||||
flashes, waits for RX silence, extracts the boot log and verifies — all in one
|
||||
call. The serial daemon buffers the full stream in `tools/serial_tool/state/serial.log`,
|
||||
so nothing can be lost between steps:
|
||||
|
||||
```powershell
|
||||
& '.venv\Scripts\python.exe' test/run_boot_test.py `
|
||||
& '.venv\Scripts\python.exe' test/host/run_boot_test.py `
|
||||
--settle-ms 8000 --max-wait-ms 30000 `
|
||||
--flash-cmd "MDK-ARM\download.bat" `
|
||||
--required "App init OK;Network Init;net init: OK" `
|
||||
|
||||
@@ -35,5 +35,5 @@ cmake --build simulator/build --config Debug # 0 警告
|
||||
- **禁止**把源文件复制进 `simulator/`——两端共用 `Drivers/BSP/` 原件(UI_界面制作流程.md C7)
|
||||
- 只注册 `.c`(含 `.s`);`.h` 靠 include 路径找到,不加工程
|
||||
- 漏注册的典型症状:一端编译失败(undefined reference)或一端行为悄悄停留在旧逻辑
|
||||
- 注册完成后跑回归:UI 文件 → `ui-verify` skill;其他模块 → `@test`(`test/run_boot_test.py`)
|
||||
- 注册完成后跑回归:UI 文件 → `ui-verify` skill;其他模块 → `@test`(`test/host/run_boot_test.py`)
|
||||
- 改过 `CMakeLists.txt` 后需重新 `cmake -B build` 配置
|
||||
|
||||
@@ -7,15 +7,15 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v
|
||||
## 铁律:源码编辑与编码
|
||||
|
||||
- 改代码**只用 Edit 工具**(精确子串替换);批量替换用 Edit 的 replaceAll。**绝不用 `Get-Content`/`Set-Content`/`cmd` 重写含中文的文件**——整文件重写会按系统默认编码重解码 → `U+FFFD` 乱码且不可逆
|
||||
- **字符串字面量必须纯 ASCII**(2026-09-15 实测):本机 ARMCC 对**无 BOM** 源文件按 CP936 解读,字符串内含**奇数个**汉字时末尾高字节吞掉结束引号 → 编译错(偶数个汉字侥幸通过);中文只写注释(注释不参与解析)。带 BOM 的文件(`Drivers/BSP/UI/*`、`App/task/ui_task.c`、`App/cfg_file.c`、`Lib/lv_conf.h`)经 BOM 按 UTF-8 解码,不受此条限制
|
||||
- **字符串字面量必须纯 ASCII**(2026-09-15 实测):本机 ARMCC 对**无 BOM** 源文件按 CP936 解读,字符串内含**奇数个**汉字时末尾高字节吞掉结束引号 → 编译错(偶数个汉字侥幸通过);中文只写注释(注释不参与解析)。带 BOM 的文件(`Drivers/BSP/UI/*`、`App/task/ui_task.c`、`App/cfg/cfg_file.c`、`Lib/lv_conf.h`)经 BOM 按 UTF-8 解码,不受此条限制
|
||||
- 确需脚本级重写:工程源码为 UTF-8(多数文件无 BOM,UI 系带 BOM),按原样同编码回写、保持 BOM 状态;拿不准就别碰
|
||||
- 发现乱码:先统计 `EF BF BD` 字节数确认真损坏(勿信终端/Read 渲染);**不要急著 `git checkout`**(会丢弃全部未提交工作)——先用 Edit 只修坏行
|
||||
- **Edit 工具会剥掉文件原有的 UTF-8 BOM**(2026-09-18 实测):带 BOM 文件(如 `App/cfg_file.c`)被 Edit 后 BOM 静默消失 → ARMCC 改按 CP936 解码 → 中文字符串字面量报 `#870-D: invalid multibyte character sequence`(**只有重编译该文件才暴露,历史"0 警告"不代表安全**)。改完带中文字面量的文件须核对 BOM 并按原样补回(只在文件头前缀 3 字节 `EF BB BF`,勿整文件重写)
|
||||
- **Edit 工具会剥掉文件原有的 UTF-8 BOM**(2026-09-18 实测):带 BOM 文件(如 `App/cfg/cfg_file.c`)被 Edit 后 BOM 静默消失 → ARMCC 改按 CP936 解码 → 中文字符串字面量报 `#870-D: invalid multibyte character sequence`(**只有重编译该文件才暴露,历史"0 警告"不代表安全**)。改完带中文字面量的文件须核对 BOM 并按原样补回(只在文件头前缀 3 字节 `EF BB BF`,勿整文件重写)
|
||||
|
||||
## 构建与验证
|
||||
|
||||
- `@build` = `& "MDK-ARM\build.bat"`(仓库根目录用**相对路径**);退出码 0 = 0 错误 0 警告,1 = 有警告或错误(查 `MDK-ARM/build_log.txt`);`build.bat` 硬编码本机 Keil 路径 `C:\Keil_v5\UV4\UV4.exe`(换机需改)
|
||||
- `@test` / `test/run_boot_test.py` 一键闭环(2026-09-20 起为纯 Python 标准库实现,替代 PowerShell 版;`& '.venv\Scripts\python.exe' test/run_boot_test.py`):开串口+清日志 → 烧录(`MDK-ARM/download.bat`,下载后 Reset&Run)→ wait-idle(等 RX 静默 8s,超时 30s)→ `test/verify_log.py` 标记校验;退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法/预检错误
|
||||
- `@test` / `test/host/run_boot_test.py` 一键闭环(2026-09-20 起为纯 Python 标准库实现,替代 PowerShell 版;`& '.venv\Scripts\python.exe' test/host/run_boot_test.py`):开串口+清日志 → 烧录(`MDK-ARM/download.bat`,下载后 Reset&Run)→ wait-idle(等 RX 静默 8s,超时 30s)→ `test/host/verify_log.py` 标记校验;退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法/预检错误
|
||||
- 默认校验标记:Required `App init OK` / `Network Init` / `net init: OK`;Forbidden `FAIL` / `ERROR` / `HardFault`;按模块定制标记(网络/存储/RTC/ADC/RS485/UI)见 `docs/测试说明/自动化测试流程.md`
|
||||
- ⚠️ 旧绝对路径 `D:\Code\DTU 程序\...` 出现即失效(仓库已搬迁),一律改用仓库相对路径
|
||||
- **下载/烧录铁律(2026-09-20 实测)**:走 `& "MDK-ARM\reset.bat" flash [文件]`(= `ST-LINK_CLI -c SWD -P <文件> -Rst -Run`),烧后 `-Rst -Run` **不可省略**——裸 `-P` 会报 `Programming Complete`,但目标核处于死循环/异常状态时写入并不落地(芯片内容不变;这就是 09/19~09/20 "反复重下载、芯片一直是旧镜像、二分法失效" 的根因);`.hex`/`.bin` 均可直烧(1MB ≈ 6.5s,快于 UV4 路径);只重启不烧录用 `reset.bat` 无参(= `-c SWD -Rst -Run`,本机 3 线接线唯一复位手段:nRST 未接、`-HardRst`/`RM=` 不可用)
|
||||
@@ -65,7 +65,7 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v
|
||||
`Src/main.c`(CubeMX 初始化)→ `app_main_init` → `osKernelStart` → 6 任务(`osKernelStart` 之前全是内核启动前代码:禁调任何 FreeRTOS/CMSIS-RTOS API,见「平台约束」)
|
||||
|
||||
- `app_main_init`(时间子系统优先,使后续日志带时间戳):`sd2506_init` → `sys_clock_init`(墙钟;RTC 故障时降级默认时间基准并返回 -1 触发"时钟芯片异常"自检;`sys_clock_get` 每 30 天惰性再基准化防 49.7 天 tick 回绕)→ `rs485_init` → `gd5f2gq5ue_init` → `tpafe5160_init` → SD2506 诊断 → `tpafe5160_start_conv_irq`
|
||||
- **就绪屏障**(`App/sys_events.h` Event Flags,取代魔法延时):`SYS_EVT_NET_READY`(netTask 置位)/ `STORAGE_READY`(defaultTask:卷挂载 + 网络配置加载完成)/ `FTP_READY` / `TIMESYNC_READY`;消费者用 `osEventFlagsWait` 阻塞等待
|
||||
- **就绪屏障**(`App/app/sys_events.h` Event Flags,取代魔法延时):`SYS_EVT_NET_READY`(netTask 置位)/ `STORAGE_READY`(defaultTask:卷挂载 + 网络配置加载完成)/ `FTP_READY` / `TIMESYNC_READY`;消费者用 `osEventFlagsWait` 阻塞等待
|
||||
- netTask:`net_stack_bring_up`(配置已由 defaultTask 在屏障前加载,本任务只读 RAM 副本 → `net_init` + PHY 强制 100M 全双工 → 递增网络代次号)→ 置 NET_READY → 循环 `net_poll` + `net_process_messages`;消费 `SYS_EVT_NET_RECONFIG` → 立即重建网络(新 IP 免重启生效,各 TCP 服务据代次号重建监听)
|
||||
- defaultTask:`f_mount` forced(无卷自动 `f_mkfs` FAT32;挂载后卷健康探针:小写两击确认,FAT 区陈旧/擦除时自动重格式化自愈,`/config.ini` 回落工厂默认——2026-09-20 /log 写失败修复)→ 网络配置加载(`net_cfg_load`,首启含旧档迁移)→ STORAGE_READY → LED 闪烁;同时是 syslog(`/log/run.log`·`selftest.log`,定长 64B 记录)的**唯一写者**与**配置引擎属主**(`cfg_file` 静态态单任务收敛于此:UI 保存请求执行 `net_cfg_save_run` + 2s `cfg_file_poll`,经 `SYS_EVT_CFG_SAVE` 事件唤醒;netTask/uiTask 不得直接触碰配置引擎,见 P1-3)
|
||||
- 全景 `docs/架构设计/项目架构总览.md`(六层分层 / 启动时序 / 存储·网络·UI 栈 / 目录组织)
|
||||
@@ -89,7 +89,7 @@ STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v
|
||||
- **单连接 socket 的断开语义**:监听 Socket 在 CONNECT 后自身即数据通道(`g_client == g_listen`),EOF 时 net 层已 `auto_relisten`;应用层**不得**在 EOF 时 `net_close` 该 fd(会连监听一起毁掉 → 端口"连接被拒"),仅当数据 fd ≠ 监听 fd(模拟器多连接后端)时才关
|
||||
- 网口配置:`/config.ini` [network] 段(工厂默认 192.168.1.100/24、gw .1;MAC 全零 = 芯片内置;UI 保存立即生效;旧档 `/cfg/netcfg.bin` 首启自动迁移)→ `docs/子系统设计/网络配置说明.md`
|
||||
- **新 .c 文件必须手动注册到两处**才能双端编译:`MDK-ARM/STM32F407-Demo.uvprojx` + `simulator/CMakeLists.txt`(用 `new-source-file` skill)
|
||||
- 测试构建:`test/test_config.h` 的 `TEST_SUITE_CH395F/STORAGE/GD5F/RTC` **互斥**(一次只能启用一个,`#error`);全部注释 = 产品构建;**破坏性用例默认关闭**:同文件 `ENABLE_DESTRUCTIVE_TESTS`(默认注释)控制写/擦 NAND、格式化、坏块注入与 FatFS 写类用例——关闭时套件为**只读模式**(开机横幅 `mode: READ-ONLY`,可随时在在用设备上跑、不动卷内容与容量),只在**产品首次上电/产线首启**或明确需要时打开(`mode: DESTRUCTIVE`);2026-09-21 实测一轮破坏性 GD5F 运行即让 dhara 多记一个坏块(容量 95248 → 95200;该计数持久化在 dhara journal checkpoint 头里,普通恢复模式清不掉,需全片擦除——见 `docs/测试说明/存储维护与容量恢复.md`);CH395F 套件 `test/ch395f_test.h`:硬件层 Phase 1~5 与 NET 层 Phase 6~11 互斥;CH395F 硬件层模式下 netTask(基础线程:无条件创建、全构建唯一实例)入口自挂起(不运行),testTask 独占 CH395F
|
||||
- 测试构建:`test/board/test_config.h` 的 `TEST_SUITE_CH395F/STORAGE/GD5F/RTC` **互斥**(一次只能启用一个,`#error`);全部注释 = 产品构建;**破坏性用例默认关闭**:同文件 `ENABLE_DESTRUCTIVE_TESTS`(默认注释)控制写/擦 NAND、格式化、坏块注入与 FatFS 写类用例——关闭时套件为**只读模式**(开机横幅 `mode: READ-ONLY`,可随时在在用设备上跑、不动卷内容与容量),只在**产品首次上电/产线首启**或明确需要时打开(`mode: DESTRUCTIVE`);2026-09-21 实测一轮破坏性 GD5F 运行即让 dhara 多记一个坏块(容量 95248 → 95200;该计数持久化在 dhara journal checkpoint 头里,普通恢复模式清不掉,需全片擦除——见 `docs/测试说明/存储维护与容量恢复.md`);CH395F 套件 `test/board/ch395f_test.h`:硬件层 Phase 1~5 与 NET 层 Phase 6~11 互斥;CH395F 硬件层模式下 netTask(基础线程:无条件创建、全构建唯一实例)入口自挂起(不运行),testTask 独占 CH395F
|
||||
- **改驱动前先读对应 `docs/问题记录/*_Trap_Records.md`**(CH395F / GD5F2GQ5UE / SD2506);各模块测试指南见 `docs/测试说明/`;**存储维护/容量恢复**(全片擦除恢复 dhara 坏块记账)见 `docs/测试说明/存储维护与容量恢复.md`
|
||||
- **LVGL I1 绘制缓冲含 palette 头(2026-09-21 实证)**:索引色格式 draw buffer 布局 = `[palette 8B][pixel data stride×h]`(`lv_draw_buf_create` 加 8B、`lv_draw_buf_goto_xy`/`lv_refr get_max_row` 都按此跳/扣),但 `lv_display_set_buffers`/`lv_draw_buf_init` 的容量校验**只看 `stride×h`**——只给 3200B 会被静默接受:末 8 个像素字节写到缓冲外(曾打脏相邻 `s_frame_box[0]` 指针 → HardFault),且 flush 收到的首地址含 palette(整帧错位 8 字节)。`ui_port.c` 按 `stride×h + palette` 供给并在 flush 时 `+palette` 取像素;详见 `docs/UI设计/UI_设计架构.md` §1.4 第 8 条
|
||||
- **MCU 端必须显式应用 dark mono 主题(2026-09-21 实证,远端"纯白屏"根因)**:`lv_display_create()` 会按 `lv_theme_mono_init(disp, false)`(白底黑字)初始化**单例**主题,且 `lv_display_set_theme()` 只把主题重应用到 `screens[0]`(底层)→ **活动屏幕仍是 LVGL 类默认浅灰 `F5F5F5`**;而 UI 内容恒用 `lv_color_white()` 绘制 → 白底白字不可见、远端整帧 99% 为亮(客户端显示纯白)。修法(`ui_port.c`):`lv_theme_mono_init(disp, true, ...)` + `lv_display_set_theme()` + 对活动屏幕再 `lv_theme_apply()`(实测 `F5F5F5` → `000000`);同时显式写 I1 调色板头 8B(`[0]=黑 [1]=白`,LVGL 不替调用方初始化);详见 `docs/UI设计/UI_设计架构.md` §1.4 第 9 条
|
||||
|
||||
+10
-23
@@ -5,38 +5,25 @@
|
||||
|
||||
## 职责
|
||||
|
||||
`Src/main.c`(CubeMX 初始化)→ `app_main_init`(本目录 `app_main.c`)→ `osKernelStart` →
|
||||
`Src/main.c`(CubeMX 初始化)→ `app_main_init`(本目录 `app/app_main.c`)→ `osKernelStart` →
|
||||
6 个 FreeRTOS 任务(见 `task/`)。**`osKernelStart` 之前全是内核启动前代码,禁止调用任何
|
||||
FreeRTOS/CMSIS-RTOS API**(见 `AGENTS.md`「平台约束」)。
|
||||
|
||||
## 文件一览
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `app_main.c/h` | 应用初始化入口 `app_main_init`:时间子系统优先 → RS485 → NAND → ADC → 诊断 |
|
||||
| `app_cfg.h` | **功能模块编译开关**(裁剪测试套件/模块用) |
|
||||
| `sys_events.h` | 系统就绪事件定义(Event Flags:`SYS_EVT_NET_READY` 等就绪屏障) |
|
||||
| `time_sync.c/h` | 时间同步任务(等待网络就绪后与时间源同步) |
|
||||
| `cfg_file.c/h` | **配置引擎**(`/config.ini` 解析 + 持久化 + 旧档迁移),属主为 defaultTask |
|
||||
| `cfg_file_store.h` | 配置存储后端抽象接口(MCU=FreeRTOS 堆 / 模拟器=宿主堆,共享核心零分配) |
|
||||
| `cfg_file_store_mcu.c` | 配置存储的 MCU 端后端实现(`cfg_store_alloc/free` → FreeRTOS 堆) |
|
||||
| `log/` | 日志子系统(见下) |
|
||||
| `task/` | FreeRTOS 任务实现(见下) |
|
||||
| `util/` | 工具函数(见下) |
|
||||
| `protocol/` | 通信协议(预留,当前为空) |
|
||||
|
||||
## 子目录
|
||||
## 目录结构(按职责分层)
|
||||
|
||||
| 目录 | 内容 | README |
|
||||
|---|---|---|
|
||||
| `log/` | syslog(`/log/run.log`·`selftest.log` 定长记录)+ 控制台单写者日志 | [`log/README.md`](log/README.md) |
|
||||
| `task/` | 6 个 FreeRTOS 任务实现 | [`task/README.md`](task/README.md) |
|
||||
| `util/` | CRC / 环形缓冲 / 墙钟时间 | [`util/README.md`](util/README.md) |
|
||||
| `protocol/` | 通信协议(预留) | — |
|
||||
| `app/` | **应用入口与全局**:`app_main.c/h`(初始化入口)、`app_cfg.h`(编译开关)、`sys_events.h`(就绪事件) | [`app/README.md`](app/README.md) |
|
||||
| `cfg/` | **配置引擎**:`/config.ini` 解析 + 持久化 + 旧档迁移 | [`cfg/README.md`](cfg/README.md) |
|
||||
| `sync/` | **时间同步任务**:`time_sync.c/h` | [`sync/README.md`](sync/README.md) |
|
||||
| `log/` | **日志子系统**:syslog(NAND)+ 控制台单写者日志 | [`log/README.md`](log/README.md) |
|
||||
| `task/` | **FreeRTOS 任务实现**(6 个任务) | [`task/README.md`](task/README.md) |
|
||||
| `util/` | **通用工具**:CRC / 环形缓冲 / 墙钟时间 | [`util/README.md`](util/README.md) |
|
||||
| `protocol/` | 通信协议(预留,当前为空) | [`protocol/README.md`](protocol/README.md) |
|
||||
|
||||
## 关键约束
|
||||
|
||||
- **配置引擎单任务收敛**:`cfg_file` 为静态态、属主是 defaultTask;UI 保存请求经
|
||||
- **配置引擎单任务收敛**:`cfg/` 为静态态、属主是 defaultTask;UI 保存请求经
|
||||
`SYS_EVT_CFG_SAVE` 事件唤醒,netTask/uiTask **不得直接触碰**配置引擎
|
||||
- **syslog 唯一写者**:`/log/*` 只由 defaultTask 写入
|
||||
- 新增任务/缓冲/栈前**必须先核算 RAM 余量**(`docs/内存管理/`)
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
# App/app/ — 应用入口与全局定义
|
||||
|
||||
> 应用层的**入口**与**全局定义**:初始化编排、功能编译开关、跨模块的就绪事件定义。
|
||||
|
||||
## 文件一览
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `app_main.c/h` | **应用初始化入口 `app_main_init`**:时间子系统优先 → RS485 → NAND → ADC → 诊断(在 `osKernelStart` 之前执行) |
|
||||
| `app_cfg.h` | **功能模块编译开关**(裁剪测试套件/模块用) |
|
||||
| `sys_events.h` | **系统就绪事件定义**(CMSIS-RTOS v2 Event Flags:`SYS_EVT_NET_READY` / `SYS_EVT_STORAGE_READY` / `SYS_EVT_FTP_READY` / `SYS_EVT_TIMESYNC_READY` 及命令位) |
|
||||
|
||||
## 初始化顺序(`app_main_init`)
|
||||
|
||||
```
|
||||
sd2506_init // 时间子系统优先,使后续日志带时间戳
|
||||
sys_clock_init // 墙钟(RTC 故障降级并返回 -1 → 触发自检)
|
||||
rs485_init
|
||||
gd5f2gq5ue_init
|
||||
tpafe5160_init
|
||||
SD2506 诊断 // ID / 时间 / 温度 / 电池
|
||||
tpafe5160_start_conv_irq // 首次 ADC 转换
|
||||
```
|
||||
|
||||
> ⚠️ 以上全部在内核启动前执行 → **禁止任何 FreeRTOS/CMSIS-RTOS API 调用**
|
||||
> (`osMessageQueueNew` 等会杀死启动)。内核前日志走无锁静态缓冲(见 `../log/`)。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 架构全景:`docs/架构设计/项目架构总览.md`
|
||||
- 启动顺序与就绪屏障:`docs/架构设计/项目启动顺序管理.md`
|
||||
- 墙钟:`docs/子系统设计/系统墙钟时间维护说明.md`
|
||||
@@ -0,0 +1,28 @@
|
||||
# App/cfg/ — 配置引擎
|
||||
|
||||
> **`/config.ini` 配置引擎**:分层解析、持久化(原子写)、旧档迁移。
|
||||
> 属主 = **defaultTask**(单任务收敛,静态态);其它任务不得直接触碰。
|
||||
|
||||
## 文件一览
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `cfg_file.c/h` | **配置引擎核心**:解析 / 查询 / 保存 / 2s 周期 `cfg_file_poll` |
|
||||
| `cfg_file_store.h` | **存储后端抽象接口**(MCU=FreeRTOS 堆 / 模拟器=宿主堆,共享核心零分配符号) |
|
||||
| `cfg_file_store_mcu.c` | **MCU 端后端实现**:`/config.ini`(`/config.TMP` + `f_rename` 原子写) |
|
||||
|
||||
## 设计要点
|
||||
|
||||
- **单任务收敛**:`cfg_file` 为静态态,只有 defaultTask 操作;UI 保存请求经
|
||||
`SYS_EVT_CFG_SAVE` 事件唤醒 defaultTask 执行(netTask/uiTask 不得直接调用)
|
||||
- **零分配共享核心**:核心逻辑不含任何分配符号,动态内存收进平台后端
|
||||
(`cfg_store_alloc/free`:MCU→`pvPortMalloc`,模拟器→宿主堆)
|
||||
- **原子写**:写 `/config.TMP` 后 `f_rename` 替换,避免掉电损坏
|
||||
- **旧档迁移**:首启时把旧格式转换为当前格式(`net_cfg_legacy.c` 负责网络段)
|
||||
- **自研代码禁用 C 库堆分配**:MicroLIB 堆仅 512B(`malloc` 必返回 NULL)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- `docs/子系统设计/配置文件设计说明.md` — 完整设计(分层/解析/持久化/迁移)
|
||||
- `docs/子系统设计/网络配置说明.md` — 网络段
|
||||
- `docs/审查记录/项目审计改进清单.md` P3-2 — 临时文件名硬编码问题
|
||||
@@ -0,0 +1,29 @@
|
||||
# App/sync/ — 时间同步
|
||||
|
||||
> 墙钟时间与外部时间源的同步(timeSyncTask)。墙钟本身由 `../util/sys_clock.c` 维护,
|
||||
> 本目录负责**从时间源拉取/接收时间并校准**。
|
||||
|
||||
## 文件一览
|
||||
|
||||
| 文件 | 作用 |
|
||||
|---|---|
|
||||
| `time_sync.c/h` | **时间同步任务**:等待网络就绪 → 与时间源交互 → 校准墙钟 |
|
||||
|
||||
## 工作流
|
||||
|
||||
```
|
||||
timeSyncTask 启动
|
||||
↓ osEventFlagsWait(SYS_EVT_NET_READY, ...|osFlagsNoClear) // 状态位不可消费!
|
||||
time_sync 主循环 → 与时间源通信 → sys_clock 校准
|
||||
↓
|
||||
置 SYS_EVT_TIMESYNC_READY
|
||||
```
|
||||
|
||||
> ⚠️ 等待**就绪位**(`SYS_EVT_NET_READY`)必须 `osFlagsNoClear`——它是状态位,
|
||||
> 用默认消费型等待会把它清掉,导致后续消费者(如 ftpTask)永远等不到。
|
||||
|
||||
## 相关文档
|
||||
|
||||
- `docs/子系统设计/系统墙钟时间维护说明.md` — 墙钟基准 / tick 回绕防护
|
||||
- `test/host/time_sync_server.py` — PC 端对时推送服务(测试用)
|
||||
- `docs/架构设计/项目启动顺序管理.md` — 就绪屏障
|
||||
+2
-2
@@ -12,14 +12,14 @@
|
||||
| `ui_task.c/h` | uiTask | BelowNormal | LVGL 界面(菜单 / 内容页 / 待机)+ 推流 |
|
||||
| `adc_task.c/h` | (ADC 任务) | — | 高精度 ADC(TPAFE5160)数据采集 |
|
||||
| `rs485_task.c/h` | (RS-485 任务) | — | 半双工 RS-485 协议通信 |
|
||||
| `time_sync.c`(在 `App/` 根) | timeSyncTask | Normal | 墙钟时间同步(实现不在本目录) |
|
||||
| `../sync/time_sync.c` | timeSyncTask | Normal | 墙钟时间同步(实现不在本目录,见 [`../sync/README.md`](../sync/README.md)) |
|
||||
|
||||
> 上表栈大小/优先级以 `Src/freertos.c` 为准(`README.md`/`AGENTS.md` 的任务表由
|
||||
> `scripts/gen_task_table.py` 生成,勿手抄)。
|
||||
|
||||
## 就绪屏障(重要)
|
||||
|
||||
任务间**不用魔法延时**,改用 `App/sys_events.h` 的 Event Flags:
|
||||
任务间**不用魔法延时**,改用 `App/app/sys_events.h` 的 Event Flags:
|
||||
|
||||
- `SYS_EVT_NET_READY` / `SYS_EVT_STORAGE_READY` 等是**状态位**——等待时必须
|
||||
`osFlagsWaitAny|osFlagsNoClear`,**不能用默认消费型等待**(否则先到的消费者会清掉位,
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# Drivers/BSP/NETCFG/ — 网络配置
|
||||
|
||||
> 网络参数的**加载 / 保存 / 旧档迁移**(IP、掩码、网关等)。
|
||||
> 本模块是**网络配置的持久化层**,与 `App/cfg_file.c`(配置引擎)配合工作。
|
||||
> 本模块是**网络配置的持久化层**,与 `App/cfg/cfg_file.c`(配置引擎)配合工作。
|
||||
|
||||
## 文件一览
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@
|
||||
`sys_clock_init`,使后续日志都带时间戳
|
||||
- 开机执行 **SD2506 诊断**(ID / 时间 / 温度 / 电池),失败触发"时钟芯片异常"自检上报
|
||||
- RTC 故障时 `sys_clock_init` **降级到默认时间基准并返回 -1**
|
||||
- 时间源同步由 `App/time_sync.c`(timeSyncTask)负责
|
||||
- 时间源同步由 `App/sync/time_sync.c`(timeSyncTask)负责
|
||||
|
||||
## 相关文档
|
||||
|
||||
|
||||
@@ -339,7 +339,7 @@
|
||||
<MiscControls>--diag_suppress=1,68,111,188,191,546,1293</MiscControls>
|
||||
<Define>USE_HAL_DRIVER,STM32F407xx,NDEBUG</Define>
|
||||
<Undefine></Undefine>
|
||||
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../Drivers/BSP/NET/lftpd;../Drivers/BSP/NETCFG;../App;../App/log;../App/task;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs;../test;../Lib/lvgl;../Drivers/BSP/UI;../Lib</IncludePath>
|
||||
<IncludePath>../Inc;../Drivers/STM32F4xx_HAL_Driver/Inc;../Drivers/STM32F4xx_HAL_Driver/Inc/Legacy;../Drivers/CMSIS/Device/ST/STM32F4xx/Include;../Drivers/CMSIS/Include;../Drivers/BSP;../Drivers/BSP/CH395F;../Drivers/BSP/GD5F2GQ5UE;../Drivers/BSP/TPAFE5160;../Drivers/BSP/SD2506;../Drivers/BSP/RS485;../Drivers/BSP/NET;../Drivers/BSP/NET/lftpd;../Drivers/BSP/NETCFG;../App;../App/app;../App/cfg;../App/log;../App/sync;../App/task;../App/util;../Middlewares/Third_Party/FreeRTOS/Source/include;../Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2;../Middlewares/Third_Party/FreeRTOS/Source/portable/RVDS/ARM_CM4F;../Lib/dhara;../Lib/FatFs;../test/board;../Lib/lvgl;../Drivers/BSP/UI;../Lib</IncludePath>
|
||||
</VariousControls>
|
||||
</Cads>
|
||||
<Aads>
|
||||
@@ -757,17 +757,17 @@
|
||||
<File>
|
||||
<FileName>app_main.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\App\app_main.c</FilePath>
|
||||
<FilePath>..\App\app\app_main.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>cfg_file.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\App\cfg_file.c</FilePath>
|
||||
<FilePath>..\App\cfg\cfg_file.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>cfg_file_store_mcu.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\App\cfg_file_store_mcu.c</FilePath>
|
||||
<FilePath>..\App\cfg\cfg_file_store_mcu.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>sys_log_mcu.c</FileName>
|
||||
@@ -787,7 +787,7 @@
|
||||
<File>
|
||||
<FileName>time_sync.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\App\time_sync.c</FilePath>
|
||||
<FilePath>..\App\sync\time_sync.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>default_task.c</FileName>
|
||||
@@ -2036,37 +2036,37 @@
|
||||
<File>
|
||||
<FileName>ch395f_test_task.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\test\ch395f_test_task.c</FilePath>
|
||||
<FilePath>..\test\board\ch395f_test_task.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>test_config.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\test\test_config.c</FilePath>
|
||||
<FilePath>..\test\board\test_config.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>net_test_task.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\test\net_test_task.c</FilePath>
|
||||
<FilePath>..\test\board\net_test_task.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>net_latency_test.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\test\net_latency_test.c</FilePath>
|
||||
<FilePath>..\test\board\net_latency_test.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>gd5f_test_task.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\test\gd5f_test_task.c</FilePath>
|
||||
<FilePath>..\test\board\gd5f_test_task.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>storage_test_task.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\test\storage_test_task.c</FilePath>
|
||||
<FilePath>..\test\board\storage_test_task.c</FilePath>
|
||||
</File>
|
||||
<File>
|
||||
<FileName>sd2506_test_task.c</FileName>
|
||||
<FileType>1</FileType>
|
||||
<FilePath>..\test\sd2506_test_task.c</FilePath>
|
||||
<FilePath>..\test\board\sd2506_test_task.c</FilePath>
|
||||
</File>
|
||||
</Files>
|
||||
</Group>
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
flowchart TB
|
||||
subgraph APP["应用层 (App/)"]
|
||||
direction LR
|
||||
A1["app_main.c"] ~~~ A2["net_task.c"] ~~~ A3["ui_task.c"] ~~~ A4["time_sync.c"]
|
||||
A1["app/app_main.c"] ~~~ A2["task/net_task.c"] ~~~ A3["task/ui_task.c"] ~~~ A4["sync/time_sync.c"]
|
||||
end
|
||||
subgraph BSP["驱动层 (Drivers/BSP/)"]
|
||||
direction LR
|
||||
@@ -107,19 +107,18 @@ STM32F4-Base/
|
||||
│ ├── main.h / FreeRTOSConfig.h / stm32f4xx_hal_conf.h
|
||||
│ └── gpio.h / dma.h / spi.h / i2c.h / usart.h
|
||||
├── App/ # 应用层代码
|
||||
│ ├── app_main.c/h # 应用初始化入口
|
||||
│ ├── app_cfg.h # 功能模块编译开关
|
||||
│ ├── sys_events.h # 系统就绪事件定义
|
||||
│ ├── sys_clock.c/h # 墙钟时间管理
|
||||
│ ├── time_sync.c/h # 时间同步任务
|
||||
│ ├── app/ # 应用入口与全局(app_main / app_cfg / sys_events)
|
||||
│ ├── cfg/ # 配置引擎(cfg_file 解析/持久化/迁移 + 存储后端)
|
||||
│ ├── sync/ # 时间同步(time_sync 任务)
|
||||
│ ├── log/ # 日志(sys_log 运行/自检记录、console_log 控制台单写者)
|
||||
│ ├── task/ # FreeRTOS 任务实现
|
||||
│ │ ├── default_task.c/h # 存储挂载 + 配置引擎属主 + syslog 写者
|
||||
│ │ ├── net_task.c/h # 网络任务
|
||||
│ │ ├── ui_task.c/h # UI 任务
|
||||
│ │ ├── adc_task.c/h # ADC 任务
|
||||
│ │ └── rs485_task.c/h # RS-485 任务
|
||||
│ ├── protocol/ # 通信协议(预留)
|
||||
│ └── util/ # 工具函数(CRC、环形缓冲等)
|
||||
│ ├── util/ # 工具函数(crc / ringbuf / sys_clock)
|
||||
│ └── protocol/ # 通信协议(预留)
|
||||
├── Drivers/
|
||||
│ ├── BSP/ # 板级驱动(手工编写)
|
||||
│ │ ├── CH395F/ # 以太网控制器驱动
|
||||
@@ -131,6 +130,7 @@ STM32F4-Base/
|
||||
│ │ │ ├── net_socket.c/h # Socket API
|
||||
│ │ │ ├── net_select.c/h # select/poll 多路复用
|
||||
│ │ │ └── lftpd/ # 轻量 FTP 服务器
|
||||
│ │ ├── NETCFG/ # 网络配置(加载/保存/旧档迁移)
|
||||
│ │ ├── UI/ # LVGL UI 组件
|
||||
│ │ └── dbg_log.h / dbg_cfg.h # 调试日志(DBG_INFO 等)
|
||||
│ ├── STM32F4xx_HAL_Driver/ # ST HAL 库
|
||||
@@ -145,22 +145,26 @@ STM32F4-Base/
|
||||
│ ├── STM32F407-Demo.uvprojx # 工程文件
|
||||
│ ├── build.bat # 命令行编译脚本
|
||||
│ ├── download.bat # 烧录脚本
|
||||
│ ├── reset.bat # 复位 / 烧录(ST-LINK_CLI)
|
||||
│ ├── *_probe.py # 台架探针(TCP 复连 / FTP 中止等)
|
||||
│ └── startup_stm32f407xx.s # 启动文件
|
||||
├── test/ # 测试代码与脚本
|
||||
│ ├── run_boot_test.py # 自动化启动测试
|
||||
│ ├── verify_log.py # 日志校验脚本
|
||||
│ ├── test_config.c/h # 测试任务配置
|
||||
│ ├── ch395f_test_task.c/h # CH395F 硬件测试
|
||||
│ ├── gd5f_test_task.c/h # NAND Flash 测试
|
||||
│ ├── net_test_task.c/h # 网络层测试
|
||||
│ ├── sd2506_test_task.c/h # RTC 测试
|
||||
│ ├── storage_test_task.c/h # 存储性能测试
|
||||
│ ├── ch395f_socket_test.py # Socket 通信测试(主机端)
|
||||
│ ├── ftp_test.py # FTP 服务器测试(主机端)
|
||||
│ ├── ftp_up_dl_test.py # FTP 上传下载测试(主机端)
|
||||
│ ├── ftp_speed_test.py # FTP 传输速度测试(主机端)
|
||||
│ ├── ftp_capture.py # FTP 流量抓取(主机端)
|
||||
│ └── time_sync_server.py # 时间同步推送服务(主机端)
|
||||
│ ├── board/ # 板端测试套件(编入固件)
|
||||
│ │ ├── test_config.c/h # 套件选择开关(互斥)
|
||||
│ │ ├── ch395f_test_task.c/h # CH395F 测试
|
||||
│ │ ├── gd5f_test_task.c/h # NAND Flash 测试
|
||||
│ │ ├── sd2506_test_task.c/h # RTC 测试
|
||||
│ │ ├── storage_test_task.c/h # 存储性能测试
|
||||
│ │ ├── net_test_task.c/h # 网络层测试
|
||||
│ │ └── net_latency_test.c/h # 链路时延探针
|
||||
│ └── host/ # 主机端脚本(PC 侧)
|
||||
│ ├── run_boot_test.py # 自动化启动测试(@test 入口)
|
||||
│ ├── verify_log.py # 日志标记校验
|
||||
│ ├── ch395f_socket_test.py # Socket 通信测试
|
||||
│ ├── ftp_test.py / ftp_up_dl_test.py / ftp_speed_test.py / ftp_capture.py / ftp_regression.py
|
||||
│ ├── e02_probe.py # E-02 专项探针
|
||||
│ ├── latency_peer.py # 链路时延 PC 对端
|
||||
│ └── time_sync_server.py # 时间同步推送服务
|
||||
├── docs/ # 项目文档(全量索引见 docs/README.md)
|
||||
│ ├── README.md # 文档索引:目录结构 + 推荐阅读顺序 + 全量清单
|
||||
│ ├── 待处理内容.md # 跨文档待办登记簿
|
||||
@@ -281,7 +285,7 @@ UI 改动回归门禁(菜单像素回归 + 内容页黄金参考 + 池水位
|
||||
|
||||
```powershell
|
||||
# 一键测试:串口捕获 → 烧录 → 日志校验(2026-09-20 起为纯 Python 标准库实现)
|
||||
& '.venv\Scripts\python.exe' test/run_boot_test.py
|
||||
& '.venv\Scripts\python.exe' test/host/run_boot_test.py
|
||||
```
|
||||
|
||||
退出码:0 = PASS | 1 = FAIL | 2 = 错误
|
||||
@@ -365,15 +369,15 @@ pre-commit run --all-files
|
||||
|------|------|
|
||||
| `Src/main.c` | 程序入口,CubeMX 生成 + USER CODE 区域 |
|
||||
| `Src/freertos.c` | FreeRTOS 任务创建 |
|
||||
| `App/app_main.c` | 应用初始化流程编排 |
|
||||
| `App/app/app_main.c` | 应用初始化流程编排 |
|
||||
| `App/task/net_task.c` | 网络任务主循环 |
|
||||
| `App/sys_events.h` | 系统就绪事件定义 |
|
||||
| `App/app_cfg.h` | 功能模块编译开关 |
|
||||
| `App/app/sys_events.h` | 系统就绪事件定义 |
|
||||
| `App/app/app_cfg.h` | 功能模块编译开关 |
|
||||
| `Drivers/BSP/CH395F/ch395f.c` | 以太网控制器驱动 |
|
||||
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c` | NAND Flash 驱动 |
|
||||
| `Drivers/BSP/NET/net_socket.c` | BSD Socket API |
|
||||
| `MDK-ARM/build.bat` | 编译脚本 |
|
||||
| `test/run_boot_test.py` | 自动化测试脚本 |
|
||||
| `test/host/run_boot_test.py` | 自动化测试脚本 |
|
||||
|
||||
## 已知问题
|
||||
|
||||
|
||||
+3
-3
@@ -32,8 +32,8 @@
|
||||
#include "dbg_log.h"
|
||||
#include "net_socket.h"
|
||||
#include "lftpd.h"
|
||||
#include "../test/ch395f_test_task.h"
|
||||
#include "../test/ch395f_test.h" /* ENABLE_NET_LAYER_TESTS:netTask 条件创建 */
|
||||
#include "../test/board/ch395f_test_task.h"
|
||||
#include "../test/board/ch395f_test.h" /* ENABLE_NET_LAYER_TESTS:netTask 条件创建 */
|
||||
#include "time_sync.h"
|
||||
#include "sys_events.h"
|
||||
#include "default_task.h"
|
||||
@@ -56,7 +56,7 @@
|
||||
|
||||
/* Private variables ---------------------------------------------------------*/
|
||||
/* USER CODE BEGIN Variables */
|
||||
/* 存储测试变量(g_storage_stats / s_perf_buf)已迁至 test/storage_test_task.c */
|
||||
/* 存储测试变量(g_storage_stats / s_perf_buf)已迁至 test/board/storage_test_task.c */
|
||||
osThreadId_t timeSyncTaskHandle;
|
||||
const osThreadAttr_t timeSyncTask_attributes = {
|
||||
.name = "timeSyncTask",
|
||||
|
||||
@@ -249,7 +249,7 @@ flowchart TD
|
||||
## 六、P3:MCU 验证
|
||||
|
||||
1. `@build` → **0 错误 0 警告**(AGENTS.md 强制;有警告看 `MDK-ARM/build_log.txt`)
|
||||
2. `@test`(一键 `test/run_boot_test.py`):
|
||||
2. `@test`(一键 `test/host/run_boot_test.py`):
|
||||
- 采集窗口**先于烧录武装**(脚本 `--flash-cmd` 已保证顺序)
|
||||
- Required:`UI port init: OK;UI menu init: OK` + 本界面定制标记(按屏增补,如页头标题字样)
|
||||
- Forbidden:`FAIL;ERROR;HardFault`
|
||||
|
||||
+155
-155
@@ -2,18 +2,20 @@ digraph refgraph_full {
|
||||
graph [rankdir=LR, bgcolor="white", labelloc=t, label="STM32F4-Base 项目文件引用关系图(项目代码视图)", fontname="Microsoft YaHei", fontsize=18];
|
||||
node [fontname="Microsoft YaHei", fontsize=10, shape=box, style="rounded,filled"];
|
||||
edge [fontname="Microsoft YaHei", fontsize=8];
|
||||
"App/app_cfg.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/app_main.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/app_main.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg_file.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg_file.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg_file_store.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg_file_store_mcu.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/app/app_cfg.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/app/app_main.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/app/app_main.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/app/sys_events.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg/cfg_file.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg/cfg_file.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg/cfg_file_store.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/cfg/cfg_file_store_mcu.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/log/console_log.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/log/console_log.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/log/sys_log.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/log/sys_log_mcu.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/sys_events.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/sync/time_sync.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/sync/time_sync.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/task/adc_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/task/adc_task.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/task/default_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
@@ -24,8 +26,6 @@ digraph refgraph_full {
|
||||
"App/task/rs485_task.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/task/ui_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/task/ui_task.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/time_sync.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/time_sync.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/util/crc.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/util/crc.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"App/util/ringbuf.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
@@ -144,47 +144,48 @@ digraph refgraph_full {
|
||||
"simulator/sim/sim_port.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"simulator/sim/sim_syslog.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"simulator/sim/ui_net_sink_backend_sim.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/ch395f_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/ch395f_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/ch395f_test_task.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/gd5f_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/gd5f_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/net_latency_test.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/net_latency_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/net_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/net_test_task.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/sd2506_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/sd2506_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/storage_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/storage_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/test_config.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/test_config.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/ch395f_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/ch395f_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/ch395f_test_task.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/gd5f_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/gd5f_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/net_latency_test.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/net_latency_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/net_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/net_test_task.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/sd2506_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/sd2506_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/storage_test.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/storage_test_task.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/test_config.c" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"test/board/test_config.h" [fillcolor="#dbeafe", color="#1d4ed8"];
|
||||
"外部/系统头文件" [shape=ellipse, fillcolor="#fef3c7", color="#d97706", fontsize=12];
|
||||
"App/app_main.c" -> "App/app_cfg.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "App/app_main.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "Drivers/BSP/RS485/rs485.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "Drivers/BSP/SD2506/sd2506.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "Drivers/BSP/TPAFE5160/tpafe5160.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app_main.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/cfg_file.c" -> "App/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg_file.c" -> "App/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg_file.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg_file.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg_file.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/cfg_file.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/cfg_file_store.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/cfg_file_store_mcu.c" -> "App/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg_file_store_mcu.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/cfg_file_store_mcu.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/cfg_file_store_mcu.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/app/app_main.c" -> "App/app/app_cfg.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "App/app/app_main.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "Drivers/BSP/RS485/rs485.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "Drivers/BSP/SD2506/sd2506.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "Drivers/BSP/TPAFE5160/tpafe5160.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/app/app_main.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/app/sys_events.h" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/cfg/cfg_file.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg/cfg_file.c" -> "App/cfg/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg/cfg_file.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg/cfg_file.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg/cfg_file.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/cfg/cfg_file.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/cfg/cfg_file_store.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/cfg/cfg_file_store_mcu.c" -> "App/cfg/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/cfg/cfg_file_store_mcu.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/cfg/cfg_file_store_mcu.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/cfg/cfg_file_store_mcu.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/log/console_log.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/log/console_log.c" -> "App/log/console_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/log/console_log.c" -> "App/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/log/console_log.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/log/console_log.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/log/console_log.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
@@ -198,14 +199,20 @@ digraph refgraph_full {
|
||||
"App/log/sys_log_mcu.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/log/sys_log_mcu.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/log/sys_log_mcu.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/sys_events.h" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os2.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/sync/time_sync.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/sync/time_sync.c" -> "App/sync/time_sync.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/sync/time_sync.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/sync/time_sync.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/sync/time_sync.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/sync/time_sync.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/sync/time_sync.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/task/adc_task.c" -> "App/task/adc_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/adc_task.c" -> "Drivers/BSP/TPAFE5160/tpafe5160.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/adc_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/adc_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/task/default_task.c" -> "App/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "App/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "App/task/default_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "Drivers/BSP/GD5F2GQ5UE/nand_ftl.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "Drivers/BSP/NETCFG/net_cfg.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -215,9 +222,9 @@ digraph refgraph_full {
|
||||
"App/task/default_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/task/default_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/task/default_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/task/default_task.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/default_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "App/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "App/task/net_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "Drivers/BSP/NET/net_select.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -225,13 +232,13 @@ digraph refgraph_full {
|
||||
"App/task/net_task.c" -> "Drivers/BSP/NETCFG/net_cfg.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/task/net_task.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/net_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/task/rs485_task.c" -> "App/task/rs485_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/rs485_task.c" -> "Drivers/BSP/RS485/rs485.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/rs485_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/rs485_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/task/ui_task.c" -> "App/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "App/task/ui_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "Drivers/BSP/UI/ui_menu.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -240,16 +247,9 @@ digraph refgraph_full {
|
||||
"App/task/ui_task.c" -> "Drivers/BSP/UI/ui_standby.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"App/task/ui_task.c" -> "test/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/task/ui_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/time_sync.c" -> "App/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/time_sync.c" -> "App/time_sync.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/time_sync.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/time_sync.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/time_sync.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/time_sync.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/time_sync.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/util/crc.c" -> "App/util/crc.h" [color="#2563eb", penwidth=1.0];
|
||||
"App/util/crc.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"App/util/ringbuf.c" -> "App/util/ringbuf.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -298,22 +298,22 @@ digraph refgraph_full {
|
||||
"Drivers/BSP/NET/net_socket.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Drivers/BSP/NET/net_socket.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Drivers/BSP/NET/net_socket.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Drivers/BSP/NET/net_socket.c" -> "test/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NET/net_socket.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NET/net_socket.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NET/net_socket.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NET/net_socket.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Drivers/BSP/NET/net_socket.h" -> "Drivers/BSP/NET/net_types.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NET/net_socket.h" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Drivers/BSP/NET/net_socket.h" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Drivers/BSP/NET/net_types.h" -> "Drivers/BSP/NET/net_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NET/net_types.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Drivers/BSP/NETCFG/net_cfg.c" -> "App/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg.c" -> "Drivers/BSP/NETCFG/net_cfg.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg.c" -> "Drivers/BSP/NETCFG/net_cfg_legacy.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Drivers/BSP/NETCFG/net_cfg.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Drivers/BSP/NETCFG/net_cfg_legacy.c" -> "App/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg_legacy.c" -> "App/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg_legacy.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg_legacy.c" -> "App/cfg/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg_legacy.c" -> "Drivers/BSP/NETCFG/net_cfg.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg_legacy.c" -> "Drivers/BSP/NETCFG/net_cfg_legacy.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/NETCFG/net_cfg_legacy.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -373,8 +373,8 @@ digraph refgraph_full {
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "Drivers/BSP/NET/net_types.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "Drivers/BSP/UI/ui_net_sink.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "Drivers/BSP/UI/ui_net_sink_backend.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "test/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"Drivers/BSP/UI/ui_net_sink.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Drivers/BSP/UI/ui_net_sink.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Drivers/BSP/UI/ui_net_sink_backend.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
@@ -439,10 +439,10 @@ digraph refgraph_full {
|
||||
"Inc/stm32f4xx_hal_conf.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Inc/usart.h" -> "Inc/main.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/dma.c" -> "Inc/dma.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "App/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "App/sync/time_sync.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "App/task/default_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "App/task/net_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "App/time_sync.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "Drivers/BSP/NET/lftpd/lftpd.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Src/freertos.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -451,13 +451,13 @@ digraph refgraph_full {
|
||||
"Src/freertos.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Src/freertos.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Src/freertos.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/task.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Src/freertos.c" -> "test/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "test/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "test/board/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "test/board/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/freertos.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"Src/gpio.c" -> "Inc/gpio.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/i2c.c" -> "Inc/i2c.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/main.c" -> "App/app_main.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/main.c" -> "App/app/app_main.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/main.c" -> "App/util/sys_clock.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/main.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0];
|
||||
"Src/main.c" -> "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -485,8 +485,8 @@ digraph refgraph_full {
|
||||
"Src/system_stm32f4xx.c" -> "Drivers/CMSIS/Device/ST/STM32F4xx/Include/stm32f4xx.h" [color="#94a3b8", penwidth=0.7];
|
||||
"Src/usart.c" -> "Inc/usart.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/dbg_log.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"simulator/main.c" -> "App/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/main.c" -> "App/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/main.c" -> "App/cfg/cfg_file.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/main.c" -> "App/cfg/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/main.c" -> "App/log/sys_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/main.c" -> "Drivers/BSP/NETCFG/net_cfg.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/main.c" -> "Drivers/BSP/UI/ui_menu.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -496,11 +496,11 @@ digraph refgraph_full {
|
||||
"simulator/main.c" -> "simulator/SDL2/SDL2-2.32.10/include/SDL.h" [color="#94a3b8", penwidth=0.7];
|
||||
"simulator/main.c" -> "simulator/sim/sim_port.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/main.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"simulator/sim/cfg_file_store_sim.c" -> "App/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/sim/cfg_file_store_sim.c" -> "App/cfg/cfg_file_store.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/sim/cfg_file_store_sim.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"simulator/sim/net_socket_sim.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/sim/net_socket_sim.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"simulator/sim/sim_latency_stub.c" -> "test/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/sim/sim_latency_stub.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/sim/sim_port.c" -> "Lib/lvgl/lvgl.h" [color="#94a3b8", penwidth=0.7];
|
||||
"simulator/sim/sim_port.c" -> "simulator/SDL2/SDL2-2.32.10/include/SDL.h" [color="#94a3b8", penwidth=0.7];
|
||||
"simulator/sim/sim_port.c" -> "simulator/sim/sim_port.h" [color="#2563eb", penwidth=1.0];
|
||||
@@ -511,77 +511,77 @@ digraph refgraph_full {
|
||||
"simulator/sim/ui_net_sink_backend_sim.c" -> "Drivers/BSP/UI/ui_port.h" [color="#2563eb", penwidth=1.0];
|
||||
"simulator/sim/ui_net_sink_backend_sim.c" -> "Lib/lvgl/lvgl.h" [color="#94a3b8", penwidth=0.7];
|
||||
"simulator/sim/ui_net_sink_backend_sim.c" -> "simulator/sim/sim_port.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/ch395f_test_task.c" -> "App/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "App/task/net_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/ch395f_test_task.c" -> "test/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "test/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "test/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "test/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "test/net_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "test/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "test/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/ch395f_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/gd5f_test.h" -> "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/gd5f_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/gd5f_test_task.c" -> "Drivers/BSP/GD5F2GQ5UE/nand_ftl.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/gd5f_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/gd5f_test_task.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/gd5f_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/gd5f_test_task.c" -> "test/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/gd5f_test_task.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/gd5f_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/net_latency_test.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_latency_test.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_latency_test.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_latency_test.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_latency_test.c" -> "test/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_latency_test.c" -> "test/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_latency_test.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_latency_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/net_latency_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/net_test_task.c" -> "Drivers/BSP/NET/net_select.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "Drivers/BSP/NET/net_types.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/net_test_task.c" -> "test/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "test/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "test/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "test/net_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/net_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/sd2506_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/sd2506_test_task.c" -> "Drivers/BSP/SD2506/sd2506.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/sd2506_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/sd2506_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/sd2506_test_task.c" -> "test/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/sd2506_test_task.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/sd2506_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/storage_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/storage_test_task.c" -> "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/storage_test_task.c" -> "Drivers/BSP/GD5F2GQ5UE/nand_ftl.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/storage_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/storage_test_task.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/storage_test_task.c" -> "Lib/FatFs/diskio.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/storage_test_task.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/storage_test_task.c" -> "test/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/storage_test_task.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/storage_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/test_config.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/test_config.c" -> "test/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.c" -> "test/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.c" -> "test/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.c" -> "test/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.c" -> "test/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.h" -> "test/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.h" -> "test/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.h" -> "test/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.h" -> "test/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/test_config.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/ch395f_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/ch395f_test_task.c" -> "App/app/sys_events.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "App/task/net_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/net_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/ch395f_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/gd5f_test.h" -> "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/gd5f_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/gd5f_test_task.c" -> "Drivers/BSP/GD5F2GQ5UE/nand_ftl.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/gd5f_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/gd5f_test_task.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/gd5f_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/include/FreeRTOS.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/gd5f_test_task.c" -> "test/board/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/gd5f_test_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/gd5f_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/net_latency_test.c" -> "Drivers/BSP/CH395F/ch395f.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_latency_test.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_latency_test.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_latency_test.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_latency_test.c" -> "test/board/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_latency_test.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_latency_test.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_latency_test.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/net_latency_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/net_test_task.c" -> "Drivers/BSP/NET/net_select.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "Drivers/BSP/NET/net_socket.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "Drivers/BSP/NET/net_types.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/net_test_task.c" -> "test/board/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "test/board/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "test/board/net_latency_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "test/board/net_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/net_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/sd2506_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/sd2506_test_task.c" -> "Drivers/BSP/SD2506/sd2506.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/sd2506_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/sd2506_test_task.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/sd2506_test_task.c" -> "test/board/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/sd2506_test_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/sd2506_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/storage_test.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/storage_test_task.c" -> "Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/storage_test_task.c" -> "Drivers/BSP/GD5F2GQ5UE/nand_ftl.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/storage_test_task.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/storage_test_task.c" -> "Inc/main.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/storage_test_task.c" -> "Lib/FatFs/diskio.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/storage_test_task.c" -> "Lib/FatFs/ff.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/storage_test_task.c" -> "test/board/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/storage_test_task.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/storage_test_task.c" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
"test/board/test_config.c" -> "Drivers/BSP/dbg_log.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.c" -> "Middlewares/Third_Party/FreeRTOS/Source/CMSIS_RTOS_V2/cmsis_os.h" [color="#94a3b8", penwidth=0.7];
|
||||
"test/board/test_config.c" -> "test/board/ch395f_test_task.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.c" -> "test/board/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.c" -> "test/board/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.c" -> "test/board/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.c" -> "test/board/test_config.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.h" -> "test/board/ch395f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.h" -> "test/board/gd5f_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.h" -> "test/board/sd2506_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.h" -> "test/board/storage_test.h" [color="#2563eb", penwidth=1.0];
|
||||
"test/board/test_config.h" -> "外部/系统头文件" [color="#f59e0b", penwidth=0.6, style=dashed];
|
||||
}
|
||||
|
||||
+321
-318
File diff suppressed because it is too large
Load Diff
+1758
-1758
File diff suppressed because it is too large
Load Diff
|
Before Width: | Height: | Size: 304 KiB After Width: | Height: | Size: 311 KiB |
@@ -322,7 +322,7 @@ void vApplicationMallocFailedHook(void)
|
||||
- 帧宽榜直接点名宽度大户(自身帧):`s_append` 704 B(FIL 512 + 记录 64 + 时间戳)、`StartDefaultTask` 560 B(探针 `FIL __chk`)、`cfg_store_read`/`cfg_store_write_atomic` 576 B、LVGL 绘制 624/560/400 B——与 §1.4 的整改项对得上。**lftpd 三项已于 2026-09-21 静态化(§1.4),已退出帧宽榜前 15**(原 `handle_control_channel` 1104 B、`receive_file`/`send_file` 1088 B、`send_response` 800 B)。
|
||||
- **静态分析的天然盲区**:递归/互递归(LVGL widget 树、`layout_update_core`、`apply_theme` 等)与间接调用只能按 "Cycle" 近似,armlink 明确标注 `+ Unknown(Cycles, Untraceable Function Pointers)`。因此 uiTask 的 912 B 是**下限**(实测 3824 B),必须靠运行时水位。
|
||||
- testTask 在产品构建里只是 `osDelay` 空循环(168 B);2048 words 是给**存储套件构建**(`TEST_SUITE_STORAGE`)预留的,测套件时应重跑本脚本看该构建的静态值。
|
||||
- **测 ftpTask 的复现配方**:设备就绪后跑 `& '.venv\Scripts\python.exe' test/ftp_speed_test.py --size 128`(STOR 128KB + RETR + 逐字节比对),再按上面命令叠加串口日志出报告。**不要用裸 TCP 工具探测 21 端口**——CH395F 单客户端复用,探测会占掉唯一会话(见 FTP 指南 §8.9)。
|
||||
- **测 ftpTask 的复现配方**:设备就绪后跑 `& '.venv\Scripts\python.exe' test/host/ftp_speed_test.py --size 128`(STOR 128KB + RETR + 逐字节比对),再按上面命令叠加串口日志出报告。**不要用裸 TCP 工具探测 21 端口**——CH395F 单客户端复用,探测会占掉唯一会话(见 FTP 指南 §8.9)。
|
||||
|
||||
#### 阶段 0 验收
|
||||
|
||||
@@ -365,7 +365,7 @@ void vApplicationMallocFailedHook(void)
|
||||
}
|
||||
```
|
||||
|
||||
**风险门禁**:scatter 注释已提示"clone MCU 可能缺 SRAM3",同理 CCM 在克隆芯片上不可靠 → 加编译开关 `APP_CCM_ENABLE`(`App/app_cfg.h`),关闭时 `LV_MEM_ATTR` 等定义退化为空,缓冲全部落回主 SRAM(阶段 1.1 池缩到 16KB 后主 SRAM 也放得下)。真 ST 芯片默认开。
|
||||
**风险门禁**:scatter 注释已提示"clone MCU 可能缺 SRAM3",同理 CCM 在克隆芯片上不可靠 → 加编译开关 `APP_CCM_ENABLE`(`App/app/app_cfg.h`),关闭时 `LV_MEM_ATTR` 等定义退化为空,缓冲全部落回主 SRAM(阶段 1.1 池缩到 16KB 后主 SRAM 也放得下)。真 ST 芯片默认开。
|
||||
|
||||
验证:map 中出现 `RW_CCM` 且 `*(CCM_DATA)` 各对象地址落在 0x10000000~0x100FFFF;`ram_report.py` 同时输出两个 Region 水位。
|
||||
|
||||
@@ -549,7 +549,7 @@ V1 链接视图(map:Grand Totals / Image component sizes / Symbol Table)
|
||||
|
||||
V4 逐项相加须与 V1 的 `Image component sizes` 逐 .o 吻合;不等则以 V1 为准并记录差异原因。
|
||||
|
||||
**数据来源清单**:`STM32F407-Demo.sct`(区域)、`Inc/FreeRTOSConfig.h`(堆/优先级/静态分配开关)、`cmsis_os2.c:472-476`(**栈大小单位 = 字节**:内部 `/ sizeof(StackType_t)`)、`Src/freertos.c`(任务/队列/事件组属性)、`Lib/lv_conf.h`、`Lib/FatFs/ffconf.h`、`App/app_cfg.h` + `test/test_config.h`(构建口径)、`Drivers/BSP/**` + `App/**`(缓冲语义/用途/DMA 归属);**权威数据 = `@build` 重建后的 `.map`**(历史 map 不得用于结论)。
|
||||
**数据来源清单**:`STM32F407-Demo.sct`(区域)、`Inc/FreeRTOSConfig.h`(堆/优先级/静态分配开关)、`cmsis_os2.c:472-476`(**栈大小单位 = 字节**:内部 `/ sizeof(StackType_t)`)、`Src/freertos.c`(任务/队列/事件组属性)、`Lib/lv_conf.h`、`Lib/FatFs/ffconf.h`、`App/app/app_cfg.h` + `test/board/test_config.h`(构建口径)、`Drivers/BSP/**` + `App/**`(缓冲语义/用途/DMA 归属);**权威数据 = `@build` 重建后的 `.map`**(历史 map 不得用于结论)。
|
||||
|
||||
### 8.5 图表与台账重生成
|
||||
|
||||
|
||||
@@ -124,7 +124,7 @@ LVGL 集合明细(均在 SRAM):LVGL 池 40,960B(`lv_mem_core_builtin.o`
|
||||
任何 scatter / CCM / 堆大小变更后,依次通过以下全部关卡方可认定生效:
|
||||
|
||||
1. `@build`(0 错误 0 警告)
|
||||
2. 产品构建 `@test`(`test/run_boot_test.py`):标记校验 PASS,且**零 `[ERR]`**(默认 Forbidden 已含 `[ERR]`)
|
||||
2. 产品构建 `@test`(`test/host/run_boot_test.py`):标记校验 PASS,且**零 `[ERR]`**(默认 Forbidden 已含 `[ERR]`)
|
||||
3. 存储套件(`test_config.h` → `TEST_SUITE_STORAGE`):只读模式实测 **3/3 PASSED**(破坏性关,卷内容不变);开启 `ENABLE_DESTRUCTIVE_TESTS` 后为全量集成用例(2026-09-20 实测 **20/20 PASSED**,含 TC-STO-01/02/03/05/06)
|
||||
4. GD5F 套件(`TEST_SUITE_GD5F`):只读模式实测 **16/16 PASSED**(含只读的守卫负路径 TC-GD5F-704);开启 `ENABLE_DESTRUCTIVE_TESTS` 后 **68/68 PASSED**,并确认日志出现 2 条守卫负路径 `[ERR]`(TC-GD5F-704/705)——破坏性模式运行须放宽 Forbidden(`--forbidden "FAIL;HardFault"`)
|
||||
5. 恢复跑(`ENABLE_STORAGE_RECOVERY_TESTS`):期望 **3/3 PASSED**
|
||||
@@ -139,8 +139,8 @@ LVGL 集合明细(均在 SRAM):LVGL 池 40,960B(`lv_mem_core_builtin.o`
|
||||
| CCM 布局(仅 heap_4.o) | `MDK-ARM/STM32F407-Demo/STM32F407-Demo.sct` |
|
||||
| DMA 阈值 1024B | `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.h`(`GD5F_DMA_THRESHOLD`,公开供测试对齐上下界) |
|
||||
| DMA 可达性运行时守卫 | `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c`(`gd5f_dma_buf_ok`,`gd5f_read_from_cache`/`gd5f_program_load` 两处接入) |
|
||||
| 守卫负路径用例(读/写) | `test/gd5f_test_task.c`(TC-GD5F-704/705) |
|
||||
| 错误级日志纳入自动闭环 | `test/verify_log.py` + `test/run_boot_test.py`(默认 Forbidden 含 `[ERR]`,`[FAIL]` 仍拦截断言失败) |
|
||||
| 守卫负路径用例(读/写) | `test/board/gd5f_test_task.c`(TC-GD5F-704/705) |
|
||||
| 错误级日志纳入自动闭环 | `test/host/verify_log.py` + `test/host/run_boot_test.py`(默认 Forbidden 含 `[ERR]`,`[FAIL]` 仍拦截断言失败) |
|
||||
| LVGL 越界保护带 32B | `Drivers/BSP/UI/ui_port.c`(`UI_DRAW_BUF_GUARD`) |
|
||||
| 栈溢出/分配失败钩子 | `Inc/FreeRTOSConfig.h` + `Src/freertos.c`(`vApplicationStackOverflowHook` / `vApplicationMallocFailedHook`) |
|
||||
| HardFault 现场上报 | `Src/stm32f4xx_it.c`(`HardFault_Handler` → `hard_fault_report`) |
|
||||
|
||||
@@ -292,9 +292,9 @@ uint32_t now = sys_clock_get(); /* Unix 秒,可用于 FatFS 文件时间、
|
||||
| `App/util/sys_clock.c` | 墙钟维护实现(基准法、换算、校时宏) |
|
||||
| `App/util/sys_clock.h` | 对外 API 声明 |
|
||||
| `Drivers/BSP/SD2506/sd2506.c` / `.h` | SD2506 RTC I2C 驱动(`sd2506_get_time` / `sd2506_set_time`) |
|
||||
| `App/app_main.c` | 初始化调用顺序:`sd2506_init()` → `sys_clock_init()` |
|
||||
| `App/time_sync.c` / `time_sync.h` | 时间同步实现(TCP Server,`timeSyncTask`) |
|
||||
| `test/time_sync_server.py` | PC 端时间推送客户端(TCP) |
|
||||
| `App/app/app_main.c` | 初始化调用顺序:`sd2506_init()` → `sys_clock_init()` |
|
||||
| `App/sync/time_sync.c` / `time_sync.h` | 时间同步实现(TCP Server,`timeSyncTask`) |
|
||||
| `test/host/time_sync_server.py` | PC 端时间推送客户端(TCP) |
|
||||
|
||||
---
|
||||
|
||||
@@ -308,9 +308,9 @@ uint32_t now = sys_clock_get(); /* Unix 秒,可用于 FatFS 文件时间、
|
||||
|
||||
| 角色 | 提供方 | 说明 |
|
||||
|------|--------|------|
|
||||
| 时间同步服务端(板子) | `App/time_sync.c` / `time_sync.h` | TCP Server,监听 `TIME_SYNC_PORT`(默认 8888) |
|
||||
| 时间同步服务端(板子) | `App/sync/time_sync.c` / `time_sync.h` | TCP Server,监听 `TIME_SYNC_PORT`(默认 8888) |
|
||||
| 同步任务 | `timeSyncTask`(FreeRTOS 任务) | 独立任务,由 `Src/freertos.c` 创建(优先级 `osPriorityNormal`,栈 2KB) |
|
||||
| 时间推送端(PC) | `test/time_sync_server.py` | Python TCP 客户端,周期推送本机本地时间 |
|
||||
| 时间推送端(PC) | `test/host/time_sync_server.py` | Python TCP 客户端,周期推送本机本地时间 |
|
||||
| 落盘接口 | `sys_clock_set_unix()` | 收到时间包后调用,内部转 `sd2506_time_t` 并写回 SD2506 |
|
||||
|
||||
### 15.2 协议
|
||||
@@ -357,7 +357,7 @@ for (;;) {
|
||||
|
||||
### 15.6 客户端实现要点(避坑)
|
||||
|
||||
PC 端 `test/time_sync_server.py` 发送 8 字节后**必须保持连接打开**,等待板子读取(或短延时)后再 `close()`:
|
||||
PC 端 `test/host/time_sync_server.py` 发送 8 字节后**必须保持连接打开**,等待板子读取(或短延时)后再 `close()`:
|
||||
|
||||
- 若发送后立刻关闭,CH395F 在收到 FIN 时会**丢弃接收缓冲里尚未被板子读出的 8 字节**;
|
||||
- 板子 `net_recv` 经消息队列异步执行(有 ~10ms+ 调度延迟),等它去读时连接已 DISCONNECT、缓冲已清空,`net_recv` 走 CLOSED 分支返回 0,时间包丢失、同步失败;
|
||||
@@ -376,7 +376,7 @@ PC 端 `test/time_sync_server.py` 发送 8 字节后**必须保持连接打开**
|
||||
[TIME_SYNC] time_sync: wall clock updated (epoch=<epoch>)
|
||||
```
|
||||
|
||||
PC 端 `python test/time_sync_server.py` 每 `interval` 秒推送一次,epoch 随电脑本地时间递增即表示同步正常。
|
||||
PC 端 `python test/host/time_sync_server.py` 每 `interval` 秒推送一次,epoch 随电脑本地时间递增即表示同步正常。
|
||||
|
||||
---
|
||||
|
||||
@@ -386,4 +386,4 @@ PC 端 `python test/time_sync_server.py` 每 `interval` 秒推送一次,epoch
|
||||
|------|------|
|
||||
| 2026-09-15 | v1.3:① `sys_clock_get` 30 天惰性再基准化——修复 49.7 天墙钟回绕(§3/§7/§12);② `sys_clock_init` 检查 RTC 读返回值/写回复验,失败降级为默认时间基准并返回 -1——激活"时钟芯片异常"自检(§5/§6/§9);③ 修正未初始化哨兵判断(§12-6);④ 时间同步任务启动/Socket 占用描述同步为事件屏障 + 单连接实现(§15);⑤ 新增日志串用 ASCII——本机 ARMCC 按 CP936 解读无 BOM 源文件,奇数汉字字符串会吞掉结束引号致编译失败(见 AGENTS.md 编码铁律) |
|
||||
|
||||
*文档依据 `App/util/sys_clock.c` / `App/time_sync.c` 实现与《嵌入式C语言代码规范_V1.0》整理。*
|
||||
*文档依据 `App/util/sys_clock.c` / `App/sync/time_sync.c` 实现与《嵌入式C语言代码规范_V1.0》整理。*
|
||||
|
||||
@@ -97,11 +97,11 @@ mac=00:00:00:00:00:00
|
||||
|
||||
### 3.3 存储后端(双端)
|
||||
|
||||
`App/cfg_file_store.h` 定义接口(带路径的文件操作),两平台各一份实现(互斥编译):
|
||||
`App/cfg/cfg_file_store.h` 定义接口(带路径的文件操作),两平台各一份实现(互斥编译):
|
||||
|
||||
| 平台 | 文件 | 位置 |
|
||||
|---|---|---|
|
||||
| MCU | `App/cfg_file_store_mcu.c` | NAND 上 FatFS `/config.ini`(`/config.TMP` + `f_rename` 原子写) |
|
||||
| MCU | `App/cfg/cfg_file_store_mcu.c` | NAND 上 FatFS `/config.ini`(`/config.TMP` + `f_rename` 原子写) |
|
||||
| 模拟器 | `simulator/sim/cfg_file_store_sim.c` | 工作目录本地文件 `sim_config.ini`(`fopen`/`rename`) |
|
||||
|
||||
INI 格式两端一致,文件可互读;mtime 变更令牌:MCU = FAT 打包时间(`fdate<<16\|ftime`,分钟级粒度),模拟器 = 宿主文件 mtime(秒级)。
|
||||
@@ -213,9 +213,9 @@ ENTER 进入选中地址行 → `↑/↓` 调活动字节(0..255 **环绕**)
|
||||
|---|---|
|
||||
| `Drivers/BSP/NETCFG/net_cfg.h/.c` | 配置核心:RAM 副本 + 工厂默认 + 加载/保存编排 + MAC 影子 + IPv4 格式化([network] 段注册) |
|
||||
| `Drivers/BSP/NETCFG/net_cfg_legacy.c` | 旧版 NCFG 二进制格式拥有者:首启一次性迁移(校验 → 物化 → 删旧档) |
|
||||
| `App/cfg_file.h/.c` | 通用配置文件引擎(双端共享核心:解析/校验/外科保存/模板/沉降轮询) |
|
||||
| `App/cfg_file_store.h` | 存储后端接口(带路径的文件操作) |
|
||||
| `App/cfg_file_store_mcu.c` | MCU 后端:FatFS `/config.ini`(`/config.TMP` + `f_rename` 原子写) |
|
||||
| `App/cfg/cfg_file.h/.c` | 通用配置文件引擎(双端共享核心:解析/校验/外科保存/模板/沉降轮询) |
|
||||
| `App/cfg/cfg_file_store.h` | 存储后端接口(带路径的文件操作) |
|
||||
| `App/cfg/cfg_file_store_mcu.c` | MCU 后端:FatFS `/config.ini`(`/config.TMP` + `f_rename` 原子写) |
|
||||
| `simulator/sim/cfg_file_store_sim.c` | 模拟器后端:本地 `sim_config.ini` |
|
||||
| `Drivers/BSP/UI/ui_page_net_cfg.c` | 网口设置内容页(显示 / 编辑 / 保存) |
|
||||
| `Drivers/BSP/UI/ui_pwd_def.h` | 编译期密码(查看 000 / 修改 123) |
|
||||
|
||||
@@ -76,7 +76,7 @@
|
||||
| `Drivers/BSP/UI/ui_standby.h/.c` | 共享 | 空闲检测 + 待机屏(屏幕覆盖层:保存/还原前屏与焦点) |
|
||||
| `Drivers/BSP/UI/ui_page_runlog.h/.c` | 共享 | 运行记录内容页描述符(动态行,数据源 = sys_log API) |
|
||||
| `Drivers/BSP/UI/ui_page_selftest.h/.c` | 共享 | 自检记录内容页描述符(同上) |
|
||||
| `App/app_main.c` | MCU | 埋点:RTC/NAND/ADC 失败 → `syslog_post(SYSLOG_SELFTEST, …)` |
|
||||
| `App/app/app_main.c` | MCU | 埋点:RTC/NAND/ADC 失败 → `syslog_post(SYSLOG_SELFTEST, …)` |
|
||||
| `Src/freertos.c`(defaultTask USER CODE) | MCU | 挂载失败埋点 + **上电/重启分类记录** + 队列排空落盘循环 |
|
||||
| `App/task/net_task.c` | MCU | 埋点:链路超时 → `syslog_post(SYSLOG_SELFTEST, "通讯异常")` |
|
||||
| `Drivers/BSP/UI/ui_page_password.c` | 共享 | R1:错误提示 + 重输 |
|
||||
|
||||
@@ -147,9 +147,9 @@ mac=00:00:00:00:00:00
|
||||
|
||||
| 文件 | 动作 | 端 | 职责 |
|
||||
|---|---|---|---|
|
||||
| `App/cfg_file.h` / `cfg_file.c` | **新增** | 双端 | 配置文件引擎:段注册 / 解析 / 外科保存 / 变更轮询 |
|
||||
| `App/cfg_file_store.h` | **新增** | 双端 | 平台文件后端接口 |
|
||||
| `App/cfg_file_store_mcu.c` | **新增** | MCU | FatFS 后端(`/config.ini`:读 / stat / 原子写 / 删) |
|
||||
| `App/cfg/cfg_file.h` / `cfg_file.c` | **新增** | 双端 | 配置文件引擎:段注册 / 解析 / 外科保存 / 变更轮询 |
|
||||
| `App/cfg/cfg_file_store.h` | **新增** | 双端 | 平台文件后端接口 |
|
||||
| `App/cfg/cfg_file_store_mcu.c` | **新增** | MCU | FatFS 后端(`/config.ini`:读 / stat / 原子写 / 删) |
|
||||
| `simulator/sim/cfg_file_store_sim.c` | **新增** | 模拟器 | 宿主文件后端(`sim_config.ini`) |
|
||||
| `Lib/FatFs/ffsystem.c` | **新增** | MCU | REENTRANT 卷互斥钩子(osMutex)+ `get_fattime`(直引用墙钟,与日志时间戳同源) |
|
||||
| `Lib/FatFs/ffconf.h` | 修改 | MCU | `FF_FS_REENTRANT` 0→1;`FF_FS_NORTC` 1→0 |
|
||||
@@ -347,7 +347,7 @@ DWORD get_fattime(void) {
|
||||
### 6.1 cfg_file 核心 API(双端共享)
|
||||
|
||||
```c
|
||||
/* App/cfg_file.h */
|
||||
/* App/cfg/cfg_file.h */
|
||||
|
||||
/* 段变更回调(重载后在触发重载的任务上下文调用;可空) */
|
||||
typedef void (*cfg_section_cb_t)(void);
|
||||
@@ -367,7 +367,7 @@ void *cfg_file_section_data(const char *p_name); /* 取段 RAM 副本(未注
|
||||
### 6.2 cfg_file_store 后端接口(每端一份实现,互斥编译)
|
||||
|
||||
```c
|
||||
/* App/cfg_file_store.h —— 带路径的文件操作(路径由后端持有,核心不感知平台布局) */
|
||||
/* App/cfg/cfg_file_store.h —— 带路径的文件操作(路径由后端持有,核心不感知平台布局) */
|
||||
typedef struct {
|
||||
uint32_t size; /* 文件长度(字节) */
|
||||
uint32_t mtime; /* 变更令牌(仅等值比较;MCU=FAT 时间打包 / 模拟器=宿主时间) */
|
||||
@@ -498,7 +498,7 @@ void adc_cfg_init(void)
|
||||
|---|---|---|---|
|
||||
| **P1** | 设计文档 + 架构图 | 本文档 + `gen_cfg_arch_svg.py` + SVG | 用户确认 §2 决策 |
|
||||
| **P2** | FS 线程安全 + 时间戳 | `ffconf.h`、`Lib/FatFs/ffsystem.c`(新)、`App/util/sys_clock.c`(sys_clock_get_time;移入中间件层)、`uvprojx`、架构总览 §1.1(sys_clock 改归 ④) | `@build` 0/0;`@test` 启动 PASS(无死锁) |
|
||||
| **P3** ✅ 2026-09-14 | cfg_file 引擎(双端)+ net_cfg 集成 + 旧档迁移 | `App/cfg_file.{h,c}`、`App/cfg_file_store.h`、`App/cfg_file_store_mcu.c`(新)、`simulator/sim/cfg_file_store_sim.c`(新)、`net_cfg.{h,c}`(段注册 + 引擎化 load/save)、`net_cfg_legacy.c`(新,NCFG 迁移)、删 `net_cfg_store*`、`uvprojx`、`CMakeLists.txt` | Keil `@build` 0/0;模拟器生成 `sim_config.ini` 且编辑回读一致;旧档 NCFG 自动迁移三态正确 —— **已实测通过**(工厂模板 / 编辑回读 / 非法键回退 / 迁移三态 / 双端 0 警告;`cfg_file.c` 含中文注释块 → UTF-8 **带 BOM**) |
|
||||
| **P3** ✅ 2026-09-14 | cfg_file 引擎(双端)+ net_cfg 集成 + 旧档迁移 | `App/cfg/cfg_file.{h,c}`、`App/cfg/cfg_file_store.h`、`App/cfg/cfg_file_store_mcu.c`(新)、`simulator/sim/cfg_file_store_sim.c`(新)、`net_cfg.{h,c}`(段注册 + 引擎化 load/save)、`net_cfg_legacy.c`(新,NCFG 迁移)、删 `net_cfg_store*`、`uvprojx`、`CMakeLists.txt` | Keil `@build` 0/0;模拟器生成 `sim_config.ini` 且编辑回读一致;旧档 NCFG 自动迁移三态正确 —— **已实测通过**(工厂模板 / 编辑回读 / 非法键回退 / 迁移三态 / 双端 0 警告;`cfg_file.c` 含中文注释块 → UTF-8 **带 BOM**) |
|
||||
| **P4** | 轮询 + D15 协议 + 测试标记 | `net_task.c`(沉降去抖轮询 + 落盘收敛 + 串口标记)、`lftpd.c`(STOR tmp+rename) | `@build`;`@test` 启动新标记(`cfg file: loaded OK` 等);FTP 上传无半截可见(rename 原子) |
|
||||
| **P5** ✅ 2026-09-14 | 模拟器迁移 | `simulator/sim/cfg_file_store_sim.c`(新)、删 `net_cfg_store_sim.c`、`simulator/main.c`(2s 轮询 + `--cfgtest` 自检)、`CMakeLists.txt` | sim 构建 0 警告 + 4 场景无头 PASS(工厂 / 有效旧档迁移 / 无效旧档保留 / UI 无头);`sim_netcfg.bin` 自动迁移 + 轮询沉降重载 + 外科保存无损回环 —— **已实测通过** |
|
||||
| **P6** | 文档同步 | `网络配置说明.md`(§0/3/6/7 重写)、`AGENTS.md`、`README.md`、`项目架构总览.md` + `gen_arch_svg.py`、`内容页架构.md`、BSD 指南、`simulator/README.md`、`ui_page_net_cfg.c` 头注释、`docs/测试说明/` | pre-commit 全绿;全库无"Flash"旧表述残留 |
|
||||
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
| # | 编号 | 问题 | 影响 | 状态 |
|
||||
|---|------|------|------|------|
|
||||
| 1 | **N-01** | `App/cfg_file.c` 用 C 库 `malloc(4097/5120)`,而本工程 MicroLIB C 堆只有 **512 B**(`startup_stm32f407xx.s:43 Heap_Size EQU 0x200`,map 中 `HEAP` ZI = `0x200`) | 真机上配置**加载/模板生成/外科式保存全部失败**并静默回落工厂默认;PC 模拟器用宿主 CRT 堆 → 掩盖问题 | ✅ **已修复(2026-09-18,L0;台账 P0-1)**,真机 `@test` 正向确认待跑 |
|
||||
| 1 | **N-01** | `App/cfg/cfg_file.c` 用 C 库 `malloc(4097/5120)`,而本工程 MicroLIB C 堆只有 **512 B**(`startup_stm32f407xx.s:43 Heap_Size EQU 0x200`,map 中 `HEAP` ZI = `0x200`) | 真机上配置**加载/模板生成/外科式保存全部失败**并静默回落工厂默认;PC 模拟器用宿主 CRT 堆 → 掩盖问题 | ✅ **已修复(2026-09-18,L0;台账 P0-1)**,真机 `@test` 正向确认待跑 |
|
||||
| 2 | **N-02** | `lftpd.c:367-371 cmd_pass` 对任意口令无条件回 `230` | 局域网内任意主机可读写 `/config.ini`(含 IP/MAC/网关)→ 可远程断网;单连接 CH395F 上还可挤掉 UI/对时服务 | 代码级确凿 |
|
||||
| 3 | **N-03** | 无独立看门狗(IWDG);`configASSERT` 为 `taskDISABLE_INTERRUPTS(); for(;;);`;多处初始化失败即 `for (;;)` 挂死 | 现场死机不可自恢复,且断言时**连日志都没有** | 全局 |
|
||||
| 4 | **N-04** | SRAM1 余 4,488 B(P0-1 修复后 5,008 B)而 **CCM 64 KB 未使用**;**栈水位零观测**(`uxTaskGetStackHighWaterMark` 全库零调用);堆水位原本被链接器整体裁掉,随 P0-1 修复已由 `cfg_store_heap_free` 引入(`load: OK …, heap free NB` 行开始打印实测值) | 任何新功能都会撞 `L6406E`;无法判断栈是过大还是不足 | 量化见 §5 |
|
||||
@@ -155,7 +155,7 @@ Select-String -Path 'MDK-ARM\STM32F407-Demo\STM32F407-Demo.map' -Pattern '__heap
|
||||
|------|------|------|
|
||||
| 根目录散置工作文件 | `待处理内容.md`(仅 2 行的 RAM 待办)、`ui_menu_tree.txt`、`ui_cn_chars.txt` | 菜单树是**生成器输入**,放根目录合理但需在 `docs/` 有权威说明;`待处理内容.md` 内容已被 `docs/内存管理/` 覆盖 → 建议合并后删除 |
|
||||
| `Lib/` 命名 | `Lib/` 下混放 `lvgl/`、`lv_conf.h`、`FatFs/`、`dhara/` | `lv_conf.h` 是**工程配置**不是库文件;建议移到 `Config/lv_conf.h` 并同步 include 路径(低风险、提升可读性) |
|
||||
| 功能开关名存实亡 | `App/app_cfg.h` 的 `APP_NET_ENABLE/APP_ADC_ENABLE/APP_RS485_ENABLE` **全库零引用** | 与台账 **P2-12** 同源。开关不生效比没有开关更糟——评审者会误信"ADC 可裁剪" |
|
||||
| 功能开关名存实亡 | `App/app/app_cfg.h` 的 `APP_NET_ENABLE/APP_ADC_ENABLE/APP_RS485_ENABLE` **全库零引用** | 与台账 **P2-12** 同源。开关不生效比没有开关更糟——评审者会误信"ADC 可裁剪" |
|
||||
| 测试任务无条件创建 | `Src/freertos.c:171` | 与台账 **P2-13** 同源;产品镜像白耗 4 KB 栈 |
|
||||
| 未使用的 CCM | `.sct` 只有 `ER_IROM1` + `RW_IRAM1 0x20000000 0x20000` | 见 §5 |
|
||||
|
||||
@@ -305,7 +305,7 @@ D-2/D-3 的共同根因:**没有任何机械检查**保证"文档说的 = 代
|
||||
| **N-07** | `configCHECK_FOR_STACK_OVERFLOW` 与 `configUSE_MALLOC_FAILED_HOOK` **均未开启** | `Inc/FreeRTOSConfig.h` 无此二宏 | 栈溢出/分配失败静默破坏内存。开销仅每任务几十字节 + 每上下文切换若干指令,**强烈建议立刻开启**(这是 §5 一切内存工作的安全网) |
|
||||
| N-08 | 无 `HardFault_Handler` 自研覆盖(用 startup 默认死循环) | `Src/*.c` 无 | 建议加:把 `SP/PSP/LR/PC/xPSR` + 栈帧 `R0-R3,R12,LR` 打到串口(或写进 CCM 保留区,复位后可读),现场故障可定位 |
|
||||
| P2-13 | testTask 无条件创建(`Src/freertos.c:171`) | | 产品镜像白耗 4 KB;改 `#if defined(TEST_SUITE_*)` 包裹 |
|
||||
| P2-12 | `App/app_cfg.h` 三个 `APP_*_ENABLE` 零引用 | | 开关要么生效要么删 |
|
||||
| P2-12 | `App/app/app_cfg.h` 三个 `APP_*_ENABLE` 零引用 | | 开关要么生效要么删 |
|
||||
|
||||
### 4.2 网络子系统(CH395F + BSD 抽象层)
|
||||
|
||||
@@ -345,7 +345,7 @@ D-2/D-3 的共同根因:**没有任何机械检查**保证"文档说的 = 代
|
||||
| N-15 | 页缓冲重复:`nand_ftl` 3×2,048(`:s_page_buf/s_cache_buf/s_copy_buf`)+ `gd5f` 的 `s_bbt_page_buf[2048]`(仅 init 期使用) | 对象 ZI:nand_ftl 6,216 + gd5f 2,596 | BBT 页缓冲可与 `s_copy_buf` 复用或 init 后归还(§5.3 R-3,省 2–4 KB) |
|
||||
| — | `disk_ioctl GET_BLOCK_SIZE = 1` | `nand_ftl.c` | FatFs 的擦除块提示失效(FAT32 对齐优化拿不到信息);建议返回 64 页(=1 物理块) |
|
||||
|
||||
### 4.4 配置引擎(`App/cfg_file.c`,1,190 行)
|
||||
### 4.4 配置引擎(`App/cfg/cfg_file.c`,1,190 行)
|
||||
|
||||
**设计良好**:描述符 + 段注册表、外科式(surgical)保存、模板生成、首启旧档迁移、2 s 轮询(`cfg_file_poll`)响应 `SYS_EVT_CFG_SAVE`,属主单任务化。这是全项目设计最完整的一个模块。
|
||||
|
||||
@@ -367,7 +367,7 @@ D-2/D-3 的共同根因:**没有任何机械检查**保证"文档说的 = 代
|
||||
|
||||
> **实施记录(2026-09-18,按方案 A 落地,两处必要调整)**:① 分配接口**不写在 `cfg_file.c` 里,而是加到 `cfg_file_store` 后端**(`cfg_store_alloc` / `cfg_store_free` / `cfg_store_heap_free`)——`cfg_file.c` 是双端共享源码,直接写 `pvPortMalloc` 会让 PC 模拟器断链;MCU 后端 = `pvPortMalloc/vPortFree`,模拟器后端 = `malloc/free`。② 编译期峰值约束改用 **typedef 负数组**(`CFG_HEAP_BUDGET = 10,240 B`)——ARMCC 5 只到 C99,**没有 `_Static_assert`**(方案 A 原文此处需修正)。③ 另补 4 条失败路径的 `syslog_post(SYSLOG_SELFTEST, …)` 与 `load: OK …, heap free NB` 实测行。台账:`docs/审查记录/项目审计改进清单.md` **P0-1**;设计文档:`docs/子系统设计/配置文件设计说明.md` §6.2/§8 + v1.11。
|
||||
|
||||
> **诚实标注**:本结论由静态分析得出(映射表 + 启动文件 + 调用图三重证据),**尚未上机确认**。`test/verify_log.ps1:34-35` 的 Forbidden 标记含 `FAIL`,而失败路径会打印 `read: malloc 4097B FAIL` / `template: malloc 5120B FAIL`,因此**一次 `@test` 即可判定**(若近期 `@test` 曾 PASS,需先确认当时是否真的进入了文件读取分支,例如 `/config.ini` 不存在或大小为 0)。**(2026-09-18 已按上述实施;修复后的真机 `@test` 正向确认——`load: OK` 出现且 `FAIL` 零命中——仍待执行。)**
|
||||
> **诚实标注**:本结论由静态分析得出(映射表 + 启动文件 + 调用图三重证据),**尚未上机确认**。`test/host/verify_log.py`(PowerShell 版 `test/verify_log.ps1:34-35` 已删除,2026-09-20 起为纯 Python)的 Forbidden 标记含 `FAIL`,而失败路径会打印 `read: malloc 4097B FAIL` / `template: malloc 5120B FAIL`,因此**一次 `@test` 即可判定**(若近期 `@test` 曾 PASS,需先确认当时是否真的进入了文件读取分支,例如 `/config.ini` 不存在或大小为 0)。**(2026-09-18 已按上述实施;修复后的真机 `@test` 正向确认——`load: OK` 出现且 `FAIL` 零命中——仍待执行。)**
|
||||
|
||||
### 4.5 日志子系统(`App/log/sys_log_mcu.c`)
|
||||
|
||||
@@ -398,7 +398,7 @@ D-2/D-3 的共同根因:**没有任何机械检查**保证"文档说的 = 代
|
||||
|
||||
### 4.8 测试体系
|
||||
|
||||
**设计良好**:`test/test_config.h` 的 `TEST_SUITE_*` 互斥(`#error` 保护)、CH395F 硬件层/NET 层 Phase 互斥、`@test` 一键闭环(烧录→wait-idle→标记校验)、模拟器 `--cfgtest/--logtest`。
|
||||
**设计良好**:`test/board/test_config.h` 的 `TEST_SUITE_*` 互斥(`#error` 保护)、CH395F 硬件层/NET 层 Phase 互斥、`@test` 一键闭环(烧录→wait-idle→标记校验)、模拟器 `--cfgtest/--logtest`。
|
||||
|
||||
**问题**:
|
||||
|
||||
@@ -717,7 +717,7 @@ UI 剩余页面批量落地(U5)、目录级层次迁移(S-1 的物理搬
|
||||
| SRAM1 96.6%、余 4,488 B | map:`Total RW Size (RW Data + ZI Data) 126584 (123.62kB)`;scatter `RW_IRAM1 0x20000000 0x00020000` |
|
||||
| CCM 未使用 | `MDK-ARM/STM32F407-Demo/STM32F407-Demo.sct` 仅两个区域,无 `0x10000000` |
|
||||
| MicroLIB C 堆 = 512 B | map `:17405 0x2001e878 - 0x00000200 Zero RW HEAP startup_stm32f407xx.o`;`__heap_limit 0x2001ea78`;`MDK-ARM/startup_stm32f407xx.s:43 Heap_Size EQU 0x200` |
|
||||
| cfg_file 走 C 库 malloc | map `cfg_file.o(i.s_load_file) refers to malloc.o(i.malloc)`、`(i.s_write_template)`、`(i.cfg_file_save)`;源码 `App/cfg_file.c:19 <stdlib.h>`、`:485/:522/:1038/:1050` |
|
||||
| cfg_file 走 C 库 malloc | map `cfg_file.o(i.s_load_file) refers to malloc.o(i.malloc)`、`(i.s_write_template)`、`(i.cfg_file_save)`;源码 `App/cfg/cfg_file.c:19 <stdlib.h>`、`:485/:522/:1038/:1050` |
|
||||
| lftpd 已迁 FreeRTOS 堆 | map `lftpd_io.o refers to heap_4.o(i.pvPortMalloc)` |
|
||||
| 堆/栈零观测 | 全库 grep `xPortGetFreeHeapSize\|uxTaskGetStackHighWaterMark\|configCHECK_FOR_STACK\|configUSE_MALLOC_FAILED` 在 `App/Src/BSP/test` 零命中;map 中相关库函数标记为 linker-removed |
|
||||
| 任务栈全部动态分配 | `Src/freertos.c:64-105` 的 `osThreadAttr_t` 无 `.stack_mem`;`freertos.o` ZI 仅 1,104 B |
|
||||
@@ -726,7 +726,7 @@ UI 剩余页面批量落地(U5)、目录级层次迁移(S-1 的物理搬
|
||||
| NAND 直接 DMA 调用方缓冲 | `gd5f2gq5ue.c:200`、`:258`(`GD5F_DMA_THRESHOLD = 32`) |
|
||||
| CH395F memcpy 自有缓冲 | `ch395f.c:1132-1190` |
|
||||
| FTP 无鉴权 | `Drivers/BSP/NET/lftpd/lftpd.c:367-371` |
|
||||
| 端口分配 | `App/time_sync.c:25 TIME_SYNC_PORT 8888`;`Drivers/BSP/UI/ui_net_sink.h:29 UI_NET_SINK_PORT 7003`;FTP 21 |
|
||||
| 端口分配 | `App/sync/time_sync.c:25 TIME_SYNC_PORT 8888`;`Drivers/BSP/UI/ui_net_sink.h:29 UI_NET_SINK_PORT 7003`;FTP 21 |
|
||||
| 42 菜单叶子 / 7 内容页 | `Drivers/BSP/UI/ui_menu_tab.c`(生成,42 节点);`ui_content_page.c:84-92 s_defs[]` |
|
||||
| 手写映射 | `ui_menu.c:155/:205 menu_content_page_for()` |
|
||||
| 文档体量 | 工作树字节统计(见 §3.1 表) |
|
||||
|
||||
+10
-10
@@ -26,7 +26,7 @@
|
||||
## P1
|
||||
|
||||
### P1-1 ADC 采样数据路径产品构建中死亡
|
||||
- **位置**:`App/app_main.c:115`(`tpafe5160_start_conv_irq()` 仅启动时调用一次)+ `Drivers/BSP/TPAFE5160/tpafe5160.c`
|
||||
- **位置**:`App/app/app_main.c:115`(`tpafe5160_start_conv_irq()` 仅启动时调用一次)+ `Drivers/BSP/TPAFE5160/tpafe5160.c`
|
||||
- **证据**:启动序列调用一次 `tpafe5160_start_conv_irq()`;全仓库无周期性 CONVST 重触发;`data_ready` / `get_buf` 无任何消费者(`adc_task.c` 是空桩)。
|
||||
- **影响**:上电后仅采集 1 个样本,此后数据永久陈旧;`APP_ADC_ENABLE` 开关又无人引用(见 P2-12),形成"看似启用实则失效"的假象。
|
||||
- **修复建议**:周期 CONVST 重触发(定时器或任务)+ 数据消费任务;若基线版本有意不实现采集,应删除启动调用并以 `APP_ADC_ENABLE` 真实门控。
|
||||
@@ -59,17 +59,17 @@
|
||||
|
||||
| # | 位置 | 问题 | 修复建议 | 置信度 |
|
||||
|---|---|---|---|---|
|
||||
| P2-1 | `App/cfg_file.c` | 受管键行 >127 字符时外科保存产生重复键行(值静默截断,旧行残留;Pass1 匹配仍受 `CFG_LINE_TEST_MAX=127` 限制) | 行长超限时拒绝保存并报错,或整卷重写 | high |
|
||||
| P2-1 | `App/cfg/cfg_file.c` | 受管键行 >127 字符时外科保存产生重复键行(值静默截断,旧行残留;Pass1 匹配仍受 `CFG_LINE_TEST_MAX=127` 限制) | 行长超限时拒绝保存并报错,或整卷重写 | high |
|
||||
| P2-2 | `Drivers/BSP/CH395F/ch395f.c` | `ch395f_spi_dma_transfer` 为 void:DMA 超时/abort 后不向调用方传播错误(调用方当成功继续 → 静默数据损坏) | 超时路径置错误标志并经返回值/查询接口上报 | high |
|
||||
| P2-3 | `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c` `gd5f_bbt_save` | 丢弃 program_load/program_exec/wait_busy 返回值:编程失败仍推进 BBT 版本号并报成功 | 检查返回值,失败不推进版本 | high |
|
||||
| P2-4 | `Drivers/BSP/GD5F2GQ5UE/nand_ftl.c` `dhara_nand_read` | 忽略 `gd5f_read_from_cache` 返回值(DMA 超时 → 返回成功 + 垃圾数据) | 检查返回值并向上报错 | high |
|
||||
| P2-5 | `Drivers/BSP/SD2506/sd2506.c` | 负温度解码 `(int8_t)(val \| 0xF0)` → 所有负温读成错误值(符号-绝对值编码未取补码) | `-(int8_t)(val & 0x7F)` | high |
|
||||
| P2-7 | `Drivers/BSP/NET/net_select.c` `check_socket_readable` | LISTENING 视为恒可读 → 单连接模式下对监听 socket select(readfds) 永久立即返回(当前无调用方,潜在地雷) | LISTENING 仅在写集合/异常集合计数可读,或明确文档化 | high |
|
||||
| P2-8 | `App/time_sync.c` + `Drivers/BSP/NET/net_config.h` | `NET_RECV_TIMEOUT_MS=30000`;且 `time_sync.c:84` 的 `net_recv` 现传 timeout=0(**无限等待**)——静默对端使同步任务永久卡死 | 同步收包单独用短超时(如 3s),与通用收发超时分离 | high |
|
||||
| P2-8 | `App/sync/time_sync.c` + `Drivers/BSP/NET/net_config.h` | `NET_RECV_TIMEOUT_MS=30000`;且 `time_sync.c:84` 的 `net_recv` 现传 timeout=0(**无限等待**)——静默对端使同步任务永久卡死 | 同步收包单独用短超时(如 3s),与通用收发超时分离 | high |
|
||||
| P2-9 | `App/log/sys_log_mcu.c` | 挂载时 mkdir 失败 → `s_fs_ready` 不置位,drain 永久 no-op 无重试(`syslog_mcu_mounted` 仅调用一次) | 周期重试挂载/建目录 | medium |
|
||||
| P2-10 | `App/log/sys_log_mcu.c` | 容量满 unlink 与 UI 读记录(FA_READ)存在竞态窗口 | unlink 前等待读者释放,或双文件轮转 | medium |
|
||||
| P2-11 | `App/task/net_task.c` | RECONFIG 事件用 `osEventFlagsGet`+Clear,非原子(检查与清除间可丢事件) | 改 `osEventFlagsWait` 原子获取 | high |
|
||||
| P2-12 | `App/app_cfg.h` | `APP_NET_ENABLE`/`APP_ADC_ENABLE`/`APP_RS485_ENABLE` 全仓库无 .c 引用,纯装饰 | 真实接入模块门控,或从文档/注释中删除"开关"说法 | high |
|
||||
| P2-12 | `App/app/app_cfg.h` | `APP_NET_ENABLE`/`APP_ADC_ENABLE`/`APP_RS485_ENABLE` 全仓库无 .c 引用,纯装饰 | 真实接入模块门控,或从文档/注释中删除"开关"说法 | high |
|
||||
| P2-13 | `Src/freertos.c:183` | testTask 无条件创建,产品构建空转占 2048 words(8KB,CCM 堆,2026-09-21 口径) | 按 `test_config.h` 门控创建 | high |
|
||||
| P2-15 | `MDK-ARM/download.bat` | 调用 UV4 前不删旧 `download_log.txt`:陈旧 "Application running" 掩盖失败烧录 | 调用前先删旧日志 | high |
|
||||
|
||||
@@ -79,17 +79,17 @@
|
||||
|
||||
| # | 位置 | 问题 |
|
||||
|---|---|---|
|
||||
| P3-1 | `App/cfg_file.c` `s_encode` | STR 型 `len==0` 时 slen 计算回绕 |
|
||||
| P3-2 | `App/cfg_file_store_mcu.c` | 临时文件名硬编码 `/config.TMP`,忽略 `p_path` 参数 |
|
||||
| P3-3 | `App/app_main.c` | `app_main_run()` 定义后无任何调用(死代码) |
|
||||
| P3-1 | `App/cfg/cfg_file.c` `s_encode` | STR 型 `len==0` 时 slen 计算回绕 |
|
||||
| P3-2 | `App/cfg/cfg_file_store_mcu.c` | 临时文件名硬编码 `/config.TMP`,忽略 `p_path` 参数 |
|
||||
| P3-3 | `App/app/app_main.c` | `app_main_run()` 定义后无任何调用(死代码) |
|
||||
| P3-4 | `Drivers/BSP/RS485/rs485.c` | 文件头宣称 DWT µs 延时,实际用 `HAL_Delay(1)`(文档不一致) |
|
||||
| P3-5 | `Drivers/BSP/GD5F2GQ5UE/nand_ftl.c` | 死宏 `FTL_NUM_BLOCKS` |
|
||||
| P3-6 | `Drivers/BSP/CH395F/ch395f.c` `ch395f_get_socket_status` | `p_status` 无 NULL 检查 |
|
||||
| P3-7 | `test/test.txt` | 0 字节空文件(删除或补内容) |
|
||||
| P3-8 | `.opencode/command/build.md` | 退出码契约写 "2+ = 编译错误",`build.bat` 实际只有 0/1 两档(与 AGENTS.md 一致的是后者) |
|
||||
| P3-11 | `App/task/adc_task.c` / `rs485_task.c` | 空桩无注释说明原因(建议注明"预留,未启用") |
|
||||
| P3-12 | `App/time_sync.c` | `len >= 8` 严格判定:TIME 包被 TCP 拆两段时拒绝处理(可容忍,增强为累积到 8 字节再判) |
|
||||
| P3-13 | `test/ch395f_test_task.c` `test_parse_ip` | 门控为 `ENABLE_HW_LAYER_TESTS`,实际引用仅在 Phase 2/5 → 单选阶段(如仅 Phase 1)时 `#177-D` 未引用函数告警(门控应改为 `PHASE2/PHASE5` 析取) |
|
||||
| P3-12 | `App/sync/time_sync.c` | `len >= 8` 严格判定:TIME 包被 TCP 拆两段时拒绝处理(可容忍,增强为累积到 8 字节再判) |
|
||||
| P3-13 | `test/board/ch395f_test_task.c` `test_parse_ip` | 门控为 `ENABLE_HW_LAYER_TESTS`,实际引用仅在 Phase 2/5 → 单选阶段(如仅 Phase 1)时 `#177-D` 未引用函数告警(门控应改为 `PHASE2/PHASE5` 析取) |
|
||||
|
||||
---
|
||||
|
||||
@@ -132,4 +132,4 @@
|
||||
- `Drivers/BSP/UI/ui_net_sink.c`:代次号重建监听、逐字节失步重同步、`RM_MAX_RX_PAYLOAD` 长度防护齐全。
|
||||
- FatFS 卷归属:产品构建单卷拥有者 = defaultTask 的 `f_mount` 实例,lftpd 复用不另 mount;`FF_FS_REENTRANT=1` ✓。
|
||||
- CH395F trap 修复在位:Trap 01(listen 顺序)、Trap 10(xTaskNotify)、Trap 11(单连接 accept)、Trap 20(send 分块 `NET_SEND_CHUNK_MAX`)均核验存在。
|
||||
- 宿主侧:`test/verify_log.py`、`test/run_boot_test.py`、`test/time_sync_server.py`(伪 epoch 与时区处理注释完备)、`tools/menu_gen/gen_menu.py`(自带校验:拒 Tab/缩进非整倍数/节点 >255)、`tools/serial_tool/`(近期已验证)均健康。
|
||||
- 宿主侧:`test/host/verify_log.py`、`test/host/run_boot_test.py`、`test/host/time_sync_server.py`(伪 epoch 与时区处理注释完备)、`tools/menu_gen/gen_menu.py`(自带校验:拒 Tab/缩进非整倍数/节点 >255)、`tools/serial_tool/`(近期已验证)均健康。
|
||||
|
||||
+1
-1
@@ -57,7 +57,7 @@
|
||||
| 文件尾 | 必须以单个换行结束(`end-of-file-fixer`) |
|
||||
| 乱码 | 禁止出现 `U+FFFD`(替换字符,字节序列 `EF BF BD`) |
|
||||
|
||||
> ⚠️ **本仓库 BOM 铁律**(见 `AGENTS.md`):C 源码中 `Drivers/BSP/UI/*`、`App/task/ui_task.c`、`App/cfg_file.c`、`Lib/lv_conf.h` 等**带 BOM**,被工具改写后 BOM 会静默丢失 → ARMCC 改按 CP936 解码 → 中文字面量编译失败。
|
||||
> ⚠️ **本仓库 BOM 铁律**(见 `AGENTS.md`):C 源码中 `Drivers/BSP/UI/*`、`App/task/ui_task.c`、`App/cfg/cfg_file.c`、`Lib/lv_conf.h` 等**带 BOM**,被工具改写后 BOM 会静默丢失 → ARMCC 改按 CP936 解码 → 中文字面量编译失败。
|
||||
> **文档(`.md`)不受此限**,一律用无 BOM UTF-8。但用脚本批量改写文档时,仍须**按原样回写换行符**(本仓库 `core.autocrlf=true` 且无 `.gitattributes`,工作区换行混杂),否则会产生整文件行尾漂移的巨型 diff。
|
||||
|
||||
---
|
||||
|
||||
@@ -540,4 +540,4 @@ if (nand_ftl_format() == 0) {
|
||||
10. **FatFs 严格 8.3 短名** — 详见 AGENTS。补充:含冒号 `:` 的名字被 FatFs 先解析为**盘符前缀** → `f_open` 返回 `FR_INVALID_DRIVE`(11) 而非 `FR_INVALID_NAME`(6);两者都属合法拒绝(测试用例须同时接受)。
|
||||
11. **FA_OPEN_APPEND 陷阱 / 短写** — 详见 AGENTS。追加写必须 `FA_WRITE | FA_OPEN_APPEND`;`f_write` 簇分配失败返回 `FR_OK`+短写(无错误码),判失败必须校验写回字节数。
|
||||
12. **崩溃可观测性(勿屏蔽)** — 已开启 `configCHECK_FOR_STACK_OVERFLOW=2` + `configUSE_MALLOC_FAILED_HOOK` + HardFault 现场报告(`Src/stm32f4xx_it.c`:裸 UART 打印 PC/LR/xPSR + CFSR/HFSR/BFAR/MMFAR 后复位,对照 `.map` 定位符号)。defaultTask **1024** words、testTask **2048** words 是**实测下限,勿降**。开机日志出现 `[ERR] STACK OVERFLOW task=` / `[ERR] HARDFAULT ...` / `MALLOC FAILED` 是精确定位线索,禁止屏蔽或降级。
|
||||
13. **BBT 恢复模式** — 运行期坏块会随 TC-STO-03 注入累积;当介质被**误标脏**(如 DMA 误打 CCM 栈导致随机块被写坏并持久化)时,打开 `test/storage_test.h` 的 `ENABLE_STORAGE_RECOVERY_TESTS` 编译**恢复构建**,testTask 会执行 `gd5f2gq5ue_bbt_rebuild()`(出厂扫描清除运行期误标)+ `nand_ftl_format()` 清账后复位。恢复后容量回到基线(即扣除 BBT 保留池后的正常容量,非出厂裸容量)。
|
||||
13. **BBT 恢复模式** — 运行期坏块会随 TC-STO-03 注入累积;当介质被**误标脏**(如 DMA 误打 CCM 栈导致随机块被写坏并持久化)时,打开 `test/board/storage_test.h` 的 `ENABLE_STORAGE_RECOVERY_TESTS` 编译**恢复构建**,testTask 会执行 `gd5f2gq5ue_bbt_rebuild()`(出厂扫描清除运行期误标)+ `nand_ftl_format()` 清账后复位。恢复后容量回到基线(即扣除 BBT 保留池后的正常容量,非出厂裸容量)。
|
||||
|
||||
@@ -99,7 +99,7 @@ osKernelStart();
|
||||
## 4. 实施步骤
|
||||
|
||||
### Step 1 定义事件组
|
||||
- 新建 `App/sys_events.h`,放入第 3.1 节的 `extern osEventFlagsId_t sys_evtHandle;` 声明与 bit 宏。
|
||||
- 新建 `App/app/sys_events.h`,放入第 3.1 节的 `extern osEventFlagsId_t sys_evtHandle;` 声明与 bit 宏。
|
||||
- 在 **CubeMX** 中配置事件组(推荐,避免手写创建代码):
|
||||
1. 打开 `STM32F407-Demo.ioc` → `Middleware` / `Software Components` → `FREERTOS` → `Configuration`,
|
||||
确认 `Mode` 为 **CMSIS_V2**(本项目即用此接口)。
|
||||
@@ -154,7 +154,7 @@ osEventFlagsSet(sys_evtHandle, SYS_EVT_FTP_READY); /* 自身就绪也广播(
|
||||
```
|
||||
|
||||
### Step 5 start_test_task 改 wait(消费者)
|
||||
将 `test/ch395f_test_task.c` 中 NET 模式的:
|
||||
将 `test/board/ch395f_test_task.c` 中 NET 模式的:
|
||||
```c
|
||||
while (!g_net_ready) { /* 旧:忙等轮询 */
|
||||
osDelay(100);
|
||||
@@ -171,7 +171,7 @@ osEventFlagsWait(sys_evtHandle, need, osFlagsWaitAll | osFlagsNoClear, osWaitFor
|
||||
```
|
||||
|
||||
### Step 6 timeSyncTask 必须等网络就绪(已实现)
|
||||
`timeSyncTask` **依赖网络**,`App/time_sync.c` 中已在入口 `wait SYS_EVT_NET_READY`(`osFlagsWaitAny | osFlagsNoClear, osWaitForever`)后才开始时间同步,取代原先 8s 魔法延时。代码已落地:
|
||||
`timeSyncTask` **依赖网络**,`App/sync/time_sync.c` 中已在入口 `wait SYS_EVT_NET_READY`(`osFlagsWaitAny | osFlagsNoClear, osWaitForever`)后才开始时间同步,取代原先 8s 魔法延时。代码已落地:
|
||||
```c
|
||||
/* 等网络栈真正就绪,确保 netTask 已开始处理消息(NoClear:状态位不得被消费) */
|
||||
if (sys_evtHandle != NULL) {
|
||||
@@ -211,7 +211,7 @@ if (sys_evtHandle != NULL) {
|
||||
5. **测试构建(HW 层模式)的特殊性**:`TEST_SUITE_CH395F` 硬件层模式下 `netTask`(基础线程)入口自挂起(不 bring_up、不轮询、不广播 `SYS_EVT_NET_READY`),`start_test_task` 自己 `net_stack_bring_up()` 独占 CH395F。此时**无人置 `SYS_EVT_NET_READY`**(置位点只在 `net_task_func` 的未挂起路径内)。结果:`ftpTask` / `timeSyncTask` 会一直阻塞在 NET_READY 上——这正符合"硬件层模式不需要 FTP / 网络时间同步、CH395F 被 testTask 独占"的设计,属预期行为,不构成冲突。若将来需要在硬件层模式也起 FTP,可让 `start_test_task` 在 bring-up 成功后自行 `osEventFlagsSet(NET_READY)`。
|
||||
6. **`g_net_ready` 去留**:**已完成淘汰**。`g_net_ready` 原全局标志已从代码中彻底移除(定义、置位、所有消费方均改为 Event Flags 等待),仅保留事件标志表达就绪。
|
||||
7. **⚠ 就绪位被消费 → 永久阻塞(2026-09-21 实测,最隐蔽的一类)**:`osEventFlagsWait` 默认 `xClearOnExit = pdTRUE`(CMSIS 包装见 `cmsis_os2.c:1243-1249`),**唤醒时就把满足条件的位清掉**。修前 `netTask` 等 `STORAGE_READY`(Any,消费 bit1)、`uiTask`/`timeSyncTask` 等 `NET_READY`(Any,消费 bit0),于是 `ftpTask` 的 `WaitAll(bit0|bit1)` 需要"两位同时为 1"的条件**永不可能成立**(bit1 在 netTask 醒来时消失、bit0 在 uiTask/timeSync 醒来时消失)→ 任务永久阻塞,**无日志、无错误码、无超时**(`osWaitForever` + `(void)` 丢返回值 = 完全静默),FTP 21 端口从未监听。
|
||||
- **修法**:所有**状态位**等待加 `osFlagsNoClear`(已改:`Src/freertos.c` 的 ftpTask、`App/task/ui_task.c`、`App/time_sync.c`、`App/task/net_task.c`、`test/ch395f_test_task.c`);**命令位**(`CFG_SAVE`/`NET_RECONFIG`)保持消费型等待。
|
||||
- **修法**:所有**状态位**等待加 `osFlagsNoClear`(已改:`Src/freertos.c` 的 ftpTask、`App/task/ui_task.c`、`App/sync/time_sync.c`、`App/task/net_task.c`、`test/board/ch395f_test_task.c`);**命令位**(`CFG_SAVE`/`NET_RECONFIG`)保持消费型等待。
|
||||
- **工程化防线**:① 关键消费者加"启动超时告警"(如 ftpTask 10s 内未到 listen 就 `DBG_ERROR`);② 用 `scripts/stack_report.py` 看任务栈水位——**某任务水位异常低 = 它根本没干活**(本次正是靠 ftpTask 只有 156B 才发现)。
|
||||
|
||||
---
|
||||
|
||||
+12
-10
@@ -55,7 +55,7 @@
|
||||
| `defaultTask` | 4096 | Normal | FatFS 挂载(无卷 `f_mkfs`)→ 卷健康探针/自愈 → `net_cfg_load`(配置引擎属主)→ 置 `STORAGE_READY`(= 存储+配置就绪)→ 日志落盘(唯一写者,`syslog_drain`)+ 配置保存执行/2s poll + LED 闪烁 + **栈水位观测**(`stack_probe_poll`:首次 5s 后报告,此后仅在出现更深峰值时打印) | `StartDefaultTask` |
|
||||
| `netTask` | 4096 | Normal | 等存储(配置已由 defaultTask 就绪,本任务只读 RAM 副本)→ `net_stack_bring_up()`(不触碰配置文件引擎)→ 置 `NET_READY` → `net_poll` 轮询(CH395F 硬件层测试模式下入口自挂起) | `StartNetTask` |
|
||||
| `ftpTask` | 4096 | Normal | 等网络**且**存储(`WaitAll`)→ `lftpd_start("/", 21)` → 单客户端会话循环(断开后重开监听) | `StartFtpTask` |
|
||||
| `testTask` | 8192 | BelowNormal | 测试套件入口(`test/test_config.h` 选择;产品构建空转) | `start_test_task` |
|
||||
| `testTask` | 8192 | BelowNormal | 测试套件入口(`test/board/test_config.h` 选择;产品构建空转) | `start_test_task` |
|
||||
| `uiTask` | 16384 | BelowNormal | 等网络 → `ui_port_init`/`ui_menu_init`/`ui_standby_init`(空闲 60s 切待机屏)/`ui_net_sink` → 10ms 刷新 | `ui_task_func` |
|
||||
| `timeSyncTask` | 2048 | Normal | 等网络 → TCP :8888 收 PC 推送时间 → 写 RTC | `time_sync_task` |
|
||||
|
||||
@@ -190,7 +190,7 @@ flowchart TB
|
||||
**单连接约束**:CH395F 配置为多 Socket + TCP Server 单连接(`set_fun_para(0x09)`),Socket 0 复用监听与数据通道;FTP / 对时 / 远程显示三个 TCP 服务**串行**占用连接,连接断开后自动回到 LISTEN。
|
||||
|
||||
> **FTP 启动门(2026-09-21 修复)**:`ftpTask` 必须等 `NET_READY` **且** `STORAGE_READY`(两位均 `NoClear`)才 `lftpd_start`——此前就绪位被其它等待者消费,FTP **静默不监听**(详见 §2.2 与 `docs/测试说明/FTP_Test_Guide.md` §8.6)。
|
||||
> **单客户端实测注意**:同一时刻只服务 1 个会话,旧会话异常断开后约 30s 才恢复监听。测试脚本必须内置连接重试(`test/ftp_up_dl_test.py`、`test/ftp_speed_test.py` 已内置),且**不要用裸 TCP 工具探测 21 端口**(探测会占掉唯一会话,见该指南 §8.7)。
|
||||
> **单客户端实测注意**:同一时刻只服务 1 个会话,旧会话异常断开后约 30s 才恢复监听。测试脚本必须内置连接重试(`test/host/ftp_up_dl_test.py`、`test/host/ftp_speed_test.py` 已内置),且**不要用裸 TCP 工具探测 21 端口**(探测会占掉唯一会话,见该指南 §8.7)。
|
||||
> 2026-09-21 实测:登录/TYPE I/PASV/STOR/RETR/LIST/DELE/QUIT 全通,128KB 上传下载逐字节一致(约 49/60 KB/s,低于阶段 5 裸 socket 基线,待查)。
|
||||
|
||||
---
|
||||
@@ -252,12 +252,12 @@ STM32F4-Base/
|
||||
│ ├── freertos.c 6 任务 + netMsgQueue + sys_evt 创建(CubeMX 接线 + 崩溃钩子;任务体在 App/task/)
|
||||
│ └── main.c 入口 → app_main_init → osKernelStart
|
||||
├── App/ 应用层(业务编排,非 CubeMX)
|
||||
│ ├── app_main.c 启动编排(时间子系统优先)
|
||||
│ ├── time_sync.c TCP 对时服务
|
||||
│ ├── sys_events.h 就绪屏障 bit 定义(就绪位等待须 osFlagsNoClear,见 §2.2)
|
||||
│ ├── app_cfg.h 功能编译开关(APP_NET/ADC/RS485_ENABLE)
|
||||
│ ├── app/ 启动编排与全局契约:app_main.c(时间子系统优先)、app_cfg.h、sys_events.h
|
||||
│ ├── task/ default_task / net_task / ui_task / adc_task* / rs485_task*
|
||||
│ ├── log/ sys_log 记录引擎(定长 64B;MCU 后端落盘 /log/*.log)
|
||||
│ ├── cfg/ 配置引擎:cfg_file(静态态单任务收敛于 defaultTask)、store(MCU=FreeRTOS 堆)
|
||||
│ ├── sync/ time_sync(TCP 对时服务)
|
||||
│ ├── protocol/ 协议编解码(MODBUS 等)与帧解析
|
||||
│ └── util/ crc(CRC-16/8)、ringbuf、sys_clock(墙钟)
|
||||
├── Drivers/BSP/ 纯手工驱动/服务(不受 CubeMX 保护)
|
||||
│ ├── CH395F/ 以太网 MAC+PHY
|
||||
@@ -274,6 +274,8 @@ STM32F4-Base/
|
||||
├── MDK-ARM/ Keil 工程(uvprojx + scatter + build/download 脚本)
|
||||
├── simulator/ PC 模拟器(CMake + SDL2,共用 UI 源码 + 无头回归测试)
|
||||
├── test/ 测试套件(test_config.h 互斥选择,产品构建空转)
|
||||
│ ├── board/ 板端套件(.c/.h:CH395F / 存储 / RTC / ADC / RS485 / UI)
|
||||
│ └── host/ 主机侧脚本(.py:烧录闭环、日志校验、UI 回归)
|
||||
├── tools/ font_gen(字体生成)/ menu_gen(菜单表生成)
|
||||
├── scripts/ 代码规范/乱码检查、RAM 报告(ram_report.py)、栈报告(stack_report.py)
|
||||
└── docs/ 设计/测试/问题记录文档
|
||||
@@ -285,7 +287,7 @@ STM32F4-Base/
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
SRC["共享源码<br/>Drivers/BSP/UI/*<br/>Drivers/BSP/NETCFG/net_cfg.c<br/>App/cfg_file.c"]
|
||||
SRC["共享源码<br/>Drivers/BSP/UI/*<br/>Drivers/BSP/NETCFG/net_cfg.c<br/>App/cfg/cfg_file.c"]
|
||||
SRC --> MCU["MCU 端<br/>Keil MDK-ARM (ARMCC v5)<br/>@build → BUILD_OK"]
|
||||
SRC --> SIM["PC 模拟器<br/>CMake + SDL2 (MSVC)<br/>lvgl_sim.exe --keys"]
|
||||
MCU --> TEST["@test:串口采集 + 烧录 + 日志校验"]
|
||||
@@ -297,7 +299,7 @@ flowchart LR
|
||||
| MCU 固件 | Keil MDK-ARM v5(`MDK-ARM/build.bat`) | `@build` 0 错 0 警 → `@test` 串口闭环 |
|
||||
| PC 模拟器 | CMake + SDL2 + MSVC(`simulator/build/`) | `check_menu_rows.py` + `check_content_pages.py`(文本断言 + 像素黄金参考) |
|
||||
|
||||
**功能编译开关**:`App/app_cfg.h`(网络/ADC/RS485);`test/test_config.h` 测试套件互斥选择(产品构建全注释)。
|
||||
**功能编译开关**:`App/app/app_cfg.h`(网络/ADC/RS485);`test/board/test_config.h` 测试套件互斥选择(产品构建全注释)。
|
||||
|
||||
---
|
||||
|
||||
@@ -311,7 +313,7 @@ flowchart LR
|
||||
| 控制台单写者日志(USART1 调试流) | `docs/子系统设计/控制台单写者日志设计说明.md` |
|
||||
| RAM 预算与优化 | `docs/内存管理/RAM使用分析与优化方案.md` |
|
||||
| 栈/内存观测工具 | `scripts/stack_report.py`(Keil 静态调用图 × 串口 `[STACK]` 水位,判定取两者更坏者)· `scripts/ram_report.py`(.map 静态占用)—— 用法与基线见内存方案 §0.6 |
|
||||
| FTP 功能与陷阱 | `docs/测试说明/FTP_Test_Guide.md`(启动门 §8.6 / 单客户端 §8.7)· 脚本 `test/ftp_up_dl_test.py`、`test/ftp_speed_test.py` |
|
||||
| FTP 功能与陷阱 | `docs/测试说明/FTP_Test_Guide.md`(启动门 §8.6 / 单客户端 §8.7)· 脚本 `test/host/ftp_up_dl_test.py`、`test/host/ftp_speed_test.py` |
|
||||
| UI 设计架构 / 内容页 / 菜单 | `docs/UI设计/UI_设计架构.md` · `内容页架构.md` · `菜单页面设计.md` |
|
||||
| UI 自动化测试 | `docs/UI设计/UI_自动化测试流程.md` |
|
||||
| 驱动已知陷阱 | `docs/问题记录/{CH395F,GD5F2GQ5UE,SD2506}_Trap_Records.md` |
|
||||
@@ -335,7 +337,7 @@ flowchart LR
|
||||
| 2026-09-10 | `lftpd` 由 ④ 中间件层移入 **③ 基础服务层**(FTP 视为应用侧服务);中间件层余 `net_socket`·`net_select`·`FatFs`·`nand_ftl`·`LVGL`·`util` |
|
||||
| 2026-09-10 | §2.2 就绪屏障图由 Mermaid 改为**手绘 SVG**(`tools/arch_diagram/gen_barrier_svg.py` → `就绪屏障.svg`):三栏(生产者 / 事件组 / 消费者)+ 水平对齐 + All 汇合点,消除原图 9 条边的交叉;PNG 预览本地渲染、不入库 |
|
||||
| 2026-09-13 | `sys_clock` 由 ③基础服务层改归 **④中间件层**(通用平台时间服务,日志/文件/对时共用;文件移入 `App/util/` 与 crc/ringbuf 同目录,include 路径不变):`FatFs` → `sys_clock` 成为**层内引用**,工程反向依赖消除;同日新增的 §1.2 "反向依赖例外" 条目撤销 |
|
||||
| 2026-09-14 | 通用配置文件(P3):网口配置存储由 `/cfg/netcfg.bin`(NCFG 二进制)迁移至 `/config.ini`(INI `[network] 段`,`App/cfg_file` 引擎 + `cfg_file_store` 双端后端);`net_cfg` 对外 API 不变;旧档首启自动迁移;`cfg_file` 列为 MCU/模拟器共享源码 |
|
||||
| 2026-09-14 | 通用配置文件(P3):网口配置存储由 `/cfg/netcfg.bin`(NCFG 二进制)迁移至 `/config.ini`(INI `[network] 段`,`App/cfg/cfg_file` 引擎 + `cfg_file_store` 双端后端);`net_cfg` 对外 API 不变;旧档首启自动迁移;`cfg_file` 列为 MCU/模拟器共享源码 |
|
||||
| 2026-09-14 | 运行/自检记录:新增 `App/log/sys_log`(定长 64B 文本记录引擎,MCU 后端 `/log/run.log`·`selftest.log`,defaultTask 唯一写者)+ UI 页面插件 `ui_page_runlog`/`ui_page_selftest`(动态列表)+ `ui_standby` 待机屏(空闲超时切入);密码页错误提示;字体 111→122 字(217 字形);详见 `docs/子系统设计/运行与自检记录设计说明.md` |
|
||||
| 2026-09-21 | **§2.2 屏障语义修正 + FTP 永不监听缺陷修复**:`osEventFlagsWait` 默认消费所等位,就绪位(`NET_READY`/`STORAGE_READY`)被 netTask/uiTask/timeSync 先消费后,`ftpTask` 的 `WaitAll(两位)` 永不成立 → 任务永久阻塞、21 端口从未监听(静默);5 处就绪位等待统一加 `osFlagsNoClear`(命令位 `CFG_SAVE`/`NET_RECONFIG` 保持消费型)。同轮新增**栈可观测性**:`Src/freertos.c` 的 `stack_probe_poll`(串口 `[STACK]` 水位)+ `scripts/stack_report.py`(Keil 静态调用图 × 运行时水位,判定取两者更坏者);§2.1 任务表补齐实测栈数据并修正过期的 defaultTask/testTask 栈配置,§3 时序图补 `NoClear` 与 FTP 启动日志,§5 补 FTP 启动门/单客户端实测注意 |
|
||||
| 2026-09-21 | **栈宽整改落地(内存方案 §1.4:lftpd 大局部缓冲静态化)**:`Drivers/BSP/NET/lftpd/lftpd.c` + `lftpd_log.c` 共 **9 处**大局部数组(`message[256]`/`response[512]`/`name[256]`×2/`buffer[1024]`×2/`read_buffer[512]`/`arg_buf[512]`/`client` 会话上下文/日志 `buffer[256]`)改为函数级 `static`(lftpd 单客户端、全部在 ftpTask 内串行);**ftpTask 实测峰值 3480 → 1184 B(余量 15% → 71%,判定 PASS)**,静态调用图 2528 → 472 B,代价静态 BSS +4,616 B(RW_IRAM1 82,048 / 131,072 B,余量仍 ~48 KB);§2.1 栈实测数据同步,原"涨栈到 1600 words"方案取消;FTP 功能回归 10/10 + 128KB 逐字节一致 |
|
||||
|
||||
@@ -80,7 +80,7 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC)
|
||||
|
||||
### 构建模式与执行顺序
|
||||
|
||||
测试固件通过条件编译分为**两种互斥形态**(`test/ch395f_test.h` 中同时启用两层会触发 `#error`):
|
||||
测试固件通过条件编译分为**两种互斥形态**(`test/board/ch395f_test.h` 中同时启用两层会触发 `#error`):
|
||||
|
||||
| 构建模式 | 启用宏 | 固件形态 |
|
||||
|----------|--------|----------|
|
||||
@@ -91,7 +91,7 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC)
|
||||
|
||||
### 启用测试
|
||||
|
||||
编辑 `test/ch395f_test.h`,取消注释对应 `ENABLE_PHASEx_TESTS` 宏(同一模式内 Phase 6/7/8/9/10/11 可共存于 testTask 循环)。**注意:阶段 6 Server 回显为持续监听循环,故 Client 阶段 11 需单独构建(不与 `ENABLE_PHASE6_TESTS` 同时启用),否则 Client 用例不会被执行。**
|
||||
编辑 `test/board/ch395f_test.h`,取消注释对应 `ENABLE_PHASEx_TESTS` 宏(同一模式内 Phase 6/7/8/9/10/11 可共存于 testTask 循环)。**注意:阶段 6 Server 回显为持续监听循环,故 Client 阶段 11 需单独构建(不与 `ENABLE_PHASE6_TESTS` 同时启用),否则 Client 用例不会被执行。**
|
||||
|
||||
---
|
||||
|
||||
@@ -155,7 +155,7 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC)
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试(硬件层) |
|
||||
| **标题** | ch395f TCP Client → PC TCP Server,64 字节收发 |
|
||||
| **前置条件** | PC: `python test/ch395f_socket_test.py tcp_server --port 8081`(PC 作 TCP 回显服务器,收到数据原样回显) |
|
||||
| **前置条件** | PC: `python test/host/ch395f_socket_test.py tcp_server --port 8081`(PC 作 TCP 回显服务器,收到数据原样回显) |
|
||||
|
||||
**测试步骤与判定标准**:
|
||||
|
||||
@@ -250,7 +250,7 @@ MCU: STM32F407ZGTx @ 168MHz, Keil MDK-ARM v5 (ARMCC)
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试(硬件层) |
|
||||
| **标题** | 30 轮 64B UDP 数据报回显 |
|
||||
| **前置条件** | PC: `python test/ch395f_socket_test.py udp_client --ip 192.168.1.100 --port 60000` |
|
||||
| **前置条件** | PC: `python test/host/ch395f_socket_test.py udp_client --ip 192.168.1.100 --port 60000` |
|
||||
|
||||
> **会话结构**(固件单会话,与 udp_client 脚本约定):累计 **60 个有效数据包**后关闭 Socket——第 1~30 轮对应本用例(PC 发 64B),第 31~60 轮对应 TC-302(变长);脚本 `"HELLO"` 就绪探针只回显、**不计数**,不占用用例预算。
|
||||
|
||||
@@ -337,7 +337,7 @@ CH395F PC (dhcp_server)
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试(硬件层) |
|
||||
| **标题** | DISCOVER → OFFER → REQUEST → ACK 全流程获取 IP |
|
||||
| **前置条件** | 管理员 PowerShell: `python test/ch395f_socket_test.py dhcp_server --ip 192.168.1.77 --dhcp-iface 192.168.1.2`(`--ip` 建议 ≠ 静态 IP,以证明确为动态获取) |
|
||||
| **前置条件** | 管理员 PowerShell: `python test/host/ch395f_socket_test.py dhcp_server --ip 192.168.1.77 --dhcp-iface 192.168.1.2`(`--ip` 建议 ≠ 静态 IP,以证明确为动态获取) |
|
||||
|
||||
**测试步骤与判定标准**:
|
||||
|
||||
@@ -459,7 +459,7 @@ MCU (TCP Client, ch395f_* 裸命令) PC (tcp_bulk --port 8081)
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试(硬件层) |
|
||||
| **标题** | 先连续发送 256KB(PC 只收),再连续接收 256KB(PC 回放),逐字节校验 + 总账一致 |
|
||||
| **前置条件** | PC: `python test/ch395f_socket_test.py tcp_bulk --port 8081 --bulk 262144 --chunk 4096`(先启动等待连接) |
|
||||
| **前置条件** | PC: `python test/host/ch395f_socket_test.py tcp_bulk --port 8081 --bulk 262144 --chunk 4096`(先启动等待连接) |
|
||||
|
||||
**测试步骤与判定标准**:
|
||||
|
||||
@@ -762,7 +762,7 @@ sequenceDiagram
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试(NET 层) |
|
||||
| **标题** | net_socket TCP Client → PC TCP Server,64 字节收发 |
|
||||
| **前置条件** | 1. PC: `python ./test/ch395f_socket_test.py tcp_server --port 8081`(TCP 回显服务器)<br>2. `net_init()` 已完成、SYS_EVT_NET_READY 已广播(netTask 周期 `net_poll()` 运行中)<br>3. `ENABLE_PHASE7_TESTS` 已定义,入口为 `net_layer_client_test_main()`(见「构建模式与执行顺序」)<br>4. 建议:硬件层固件中 TC-NET-201/202/203 已通过(跨构建前置,见「构建模式与执行顺序」) |
|
||||
| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_server --port 8081`(TCP 回显服务器)<br>2. `net_init()` 已完成、SYS_EVT_NET_READY 已广播(netTask 周期 `net_poll()` 运行中)<br>3. `ENABLE_PHASE7_TESTS` 已定义,入口为 `net_layer_client_test_main()`(见「构建模式与执行顺序」)<br>4. 建议:硬件层固件中 TC-NET-201/202/203 已通过(跨构建前置,见「构建模式与执行顺序」) |
|
||||
|
||||
**测试步骤与判定标准**:
|
||||
|
||||
@@ -834,7 +834,7 @@ sequenceDiagram
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试 / 并发测试(NET 层) |
|
||||
| **标题** | 同时打开 8 个 Socket 连接 PC Server,各自 64B 收发 |
|
||||
| **前置条件** | 1. PC: `python ./test/ch395f_socket_test.py tcp_server --port 8081 --max-conn 8`(并发回显,`--max-conn` 为并发计数)<br>2. `net_init()` 已置 `FUN_PARA=0x09`(8 Socket 模式),8 个 Socket 缓冲按「CH395F 缓冲架构」分配(每 Socket 接收 2KB + 发送 1KB,MSS=1024)<br>3. `ENABLE_PHASE7_TESTS` 已定义 |
|
||||
| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_server --port 8081 --max-conn 8`(并发回显,`--max-conn` 为并发计数)<br>2. `net_init()` 已置 `FUN_PARA=0x09`(8 Socket 模式),8 个 Socket 缓冲按「CH395F 缓冲架构」分配(每 Socket 接收 2KB + 发送 1KB,MSS=1024)<br>3. `ENABLE_PHASE7_TESTS` 已定义 |
|
||||
|
||||
**测试步骤与判定标准**:
|
||||
|
||||
@@ -860,7 +860,7 @@ sequenceDiagram
|
||||
| **耗时** | 取决于文件大小与速率(100KB 约数秒) |
|
||||
| **入口** | `ENABLE_PHASE8_TESTS` |
|
||||
| **配置** | `PHASE8_FILE_SIZE`(默认 102400 = 100KB);`PHASE8_DIRECTION`(SEND / RECV / ECHO,默认 ECHO) |
|
||||
| **PC 配合** | `python ./test/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(文件发送)<br>`... --op send --file tx_100k.bin --size 102400`(文件接收) |
|
||||
| **PC 配合** | `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(文件发送)<br>`... --op send --file tx_100k.bin --size 102400`(文件接收) |
|
||||
|
||||
> 架构:MCU 为 TCP Server(`net_test_task` 监听 8080,`net_accept` 后 `phase8_run(acc)`);PC 用 `tcp_file` 子命令作 Client 连接 MCU:8080。一次 `phase8_run` 对应一次 PC 连接。
|
||||
|
||||
@@ -883,7 +883,7 @@ sequenceDiagram
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试(文件发送) |
|
||||
| **标题** | MCU 流式发送 100KB 至 PC 并落盘校验 |
|
||||
| **前置条件** | 1. PC: `python ./test/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(先连接等待数据)<br>2. `ENABLE_PHASE8_TESTS`,`PHASE8_FILE_SIZE=102400`,`PHASE8_DIRECTION=SEND`<br>3. `net_init` 完成,MSS=1024 |
|
||||
| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op recv --file rx_100k.bin --size 102400`(先连接等待数据)<br>2. `ENABLE_PHASE8_TESTS`,`PHASE8_FILE_SIZE=102400`,`PHASE8_DIRECTION=SEND`<br>3. `net_init` 完成,MSS=1024 |
|
||||
| **测试步骤** | 1. MCU `net_accept` 建链(PC 已连接)<br>2. 循环填充一个滑动窗口(≤ s_tx_buf)并调用 `net_send`;`net_send` 内部按硬件发送 FIFO(`NET_SEND_CHUNK_MAX`=1KB,见 Trap 20)自动拆分写入,直至 100KB 发完<br>3. PC 接收全部字节写入 `rx_100k.bin`,按递增模式或预置 CRC32 校验 |
|
||||
| **通过标准** | PC 收满 102400B 且逐字节/CRC32 校验一致,MCU 无发送错误 |
|
||||
| **覆盖原则** | DP-04(分块发送、DMA 边界)、缓冲架构(1KB 发送缓冲) |
|
||||
@@ -897,7 +897,7 @@ sequenceDiagram
|
||||
| **优先级** | P0 |
|
||||
| **类型** | 功能测试(文件接收) |
|
||||
| **标题** | PC 流式发送 100KB 文件,MCU 接收并校验 |
|
||||
| **前置条件** | 1. PC: `python ./test/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op send --file tx_100k.bin --size 102400`(先连接并发送;无文件则生成 100KB 递增模式)<br>2. 同 TC-NET-801(`PHASE8_DIRECTION=RECV`) |
|
||||
| **前置条件** | 1. PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op send --file tx_100k.bin --size 102400`(先连接并发送;无文件则生成 100KB 递增模式)<br>2. 同 TC-NET-801(`PHASE8_DIRECTION=RECV`) |
|
||||
| **测试步骤** | 1. MCU `net_accept` 建链(PC 已连接)<br>2. 循环 `net_recv`(≤2KB/次,Trap 13 一次读空)→ 按 offset 字节校验 + 累计 CRC32,直至收满 100KB<br>3. PC 在文件末尾附 4 字节 CRC32(小端);MCU 收齐后比对 CRC32 |
|
||||
| **通过标准** | MCU 收满 102400B,字节校验全过且 CRC32 匹配,无溢出/截断 |
|
||||
| **覆盖原则** | DP-04(接收缓冲 2KB 一次读空)、Trap 13 |
|
||||
@@ -911,7 +911,7 @@ sequenceDiagram
|
||||
| **优先级** | P1 |
|
||||
| **类型** | 恢复/压力测试 |
|
||||
| **标题** | MCU 发 100KB 经 PC 回显原样返回,MCU 收齐校验 |
|
||||
| **前置条件** | MCU: `PHASE8_DIRECTION=ECHO`(net_accept 监听 8080);PC: `python ./test/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op echo`(PC 作 Client 连 MCU 并原样回显) |
|
||||
| **前置条件** | MCU: `PHASE8_DIRECTION=ECHO`(net_accept 监听 8080);PC: `python ./test/host/ch395f_socket_test.py tcp_file --ip 192.168.1.100 --port 8080 --op echo`(PC 作 Client 连 MCU 并原样回显) |
|
||||
| **测试步骤** | MCU 发 100KB → PC 回显 → MCU 收 100KB 字节校验 |
|
||||
| **通过标准** | 100KB 全过,验证 100KB 经回显链路完整 |
|
||||
| **覆盖原则** | DP-01、DP-04 |
|
||||
|
||||
@@ -38,7 +38,7 @@
|
||||
|
||||
- **默认构建即可提供 FTP Server**,无需切换测试套件。
|
||||
- 任何改动后必须执行 `@build`(即 `MDK-ARM/build.bat`),确认 **0 Error(s) 0 Warning(s)** 再烧录(遵循 AGENTS.md 铁律)。
|
||||
- 若需跑**自动化 FTP 文件传输用例**:在 `test/test_config.h` 选择 `TEST_SUITE_CH395F`,并在 `test/ch395f_test.h` 打开 `ENABLE_PHASE8_TESTS`(文件传输阶段),重新编译烧录。
|
||||
- 若需跑**自动化 FTP 文件传输用例**:在 `test/board/test_config.h` 选择 `TEST_SUITE_CH395F`,并在 `test/board/ch395f_test.h` 打开 `ENABLE_PHASE8_TESTS`(文件传输阶段),重新编译烧录。
|
||||
- 烧录后打开串口(115200bps)观察:
|
||||
- `net_init` 完成、PHY link up;
|
||||
- `[FTP] waiting for connection...`(约 3 次重试足够 PHY 稳定);
|
||||
@@ -49,12 +49,12 @@
|
||||
## 4. PC 端脚本手测(主要手段)
|
||||
|
||||
所有脚本支持 `--host`(默认 `192.168.1.100`)、`--port`(默认 21),在 `test/` 目录运行;`ftp_up_dl_test.py` / `ftp_speed_test.py` 内置**连接重试**(单客户端:旧会话未释放时自动等待重试,默认 6 次 × 3s)。
|
||||
推荐入口:`& '.venv\Scripts\python.exe' test/ftp_up_dl_test.py`(功能闭环:登录/TYPE I/PASV/STOR/LIST/RETR/比对/DELE/QUIT)与 `& '.venv\Scripts\python.exe' test/ftp_speed_test.py --size 128`(大文件 + 吞吐);后者同时是 **ftpTask 栈水位测量**的负载(见 `docs/内存管理/RAM使用分析与优化方案.md` §0.6)。
|
||||
推荐入口:`& '.venv\Scripts\python.exe' test/host/ftp_up_dl_test.py`(功能闭环:登录/TYPE I/PASV/STOR/LIST/RETR/比对/DELE/QUIT)与 `& '.venv\Scripts\python.exe' test/host/ftp_speed_test.py --size 128`(大文件 + 吞吐);后者同时是 **ftpTask 栈水位测量**的负载(见 `docs/内存管理/RAM使用分析与优化方案.md` §0.6)。
|
||||
|
||||
### 4.1 冒烟测试:`ftp_test.py`
|
||||
|
||||
- 用途:验证连接、登录、`PWD`、`PASV`、`LIST` 基本链路。
|
||||
- 命令:`python ./test/ftp_test.py --host 192.168.1.100`
|
||||
- 命令:`python ./test/host/ftp_test.py --host 192.168.1.100`
|
||||
- 预期:
|
||||
- 连接成功并读到 `220` 欢迎;
|
||||
- `USER anonymous` / `PASS` 返回 `230`;
|
||||
@@ -66,7 +66,7 @@
|
||||
### 4.2 上传 / 下载 / 比对:`ftp_up_dl_test.py`
|
||||
|
||||
- 用途:验证 `STOR`/`RETR`/`DELE` 与数据一致性(`TYPE I` 二进制 + `PASV`)。
|
||||
- 命令:`python ./test/ftp_up_dl_test.py --host 192.168.1.100`
|
||||
- 命令:`python ./test/host/ftp_up_dl_test.py --host 192.168.1.100`
|
||||
- 流程:登录 → `TYPE I` → `STOR up_test.dat` → `LIST` 校验存在 → `RETR up_test.dat` → 逐字节比对 → `DELE` 清理 → `QUIT`。
|
||||
- 预期:`*** MATCH! Upload/Download success. ***`,且 LIST 中出现 `up_test.dat`。
|
||||
- 判据:上传/下载字节数相等且内容逐字节一致。
|
||||
@@ -74,7 +74,7 @@
|
||||
### 4.3 速度与大数据量:`ftp_speed_test.py`
|
||||
|
||||
- 用途:测量上传/下载吞吐,作回归基线,同时验证大文件不丢字节。
|
||||
- 命令:`python ./test/ftp_speed_test.py --host 192.168.1.100 --size 512`(默认 512KB,`--size` 可调)。
|
||||
- 命令:`python ./test/host/ftp_speed_test.py --host 192.168.1.100 --size 512`(默认 512KB,`--size` 可调)。
|
||||
- 预期:上传/下载均返回 `226`,回读 `MATCH!`,打印 KB/s。
|
||||
- 注意:脚本使用 8.3 文件名 `SPEEDTST.DAT`(**FTP 仅支持 8.3 短文件名**,见 §8.3);以回读比对(MATCH)为最终判据,中间打印的 Sent 字段仅供参考。
|
||||
- 判据:size 一致 + MATCH + 速度稳定(受 SPI2 分频 8 限制,通常约 300~450 KB/s,参见 `CH395F_Test_Guide.md` 阶段 5 吞吐基线)。
|
||||
@@ -146,7 +146,7 @@
|
||||
|
||||
- 现象:串口无 `[FTP] waiting for connection...`、无 `[LFT_INET]` 报错,`[STACK]` 行里 ftpTask 峰值极低(实测 156 B,仅为任务入口),21 端口始终 `connection refused`。
|
||||
- 根因(2026-09-21 定位并修复):`osEventFlagsWait` 默认**消费**所等待的位,而 `SYS_EVT_NET_READY` / `SYS_EVT_STORAGE_READY` 是**状态位**。`netTask` 等 `STORAGE_READY` 时清掉 bit1,`uiTask` / `timeSyncTask` 等 `NET_READY` 时清掉 bit0 → `ftpTask` 的 `WaitAll(bit0|bit1)` 条件永不成立,任务永久阻塞在内核等待队列(无日志、无报错、静默失效)。
|
||||
- 修复:**所有就绪位等待加 `osFlagsNoClear`**(`Src/freertos.c` 的 ftpTask、`App/task/ui_task.c`、`App/time_sync.c`、`App/task/net_task.c`、`test/ch395f_test_task.c`);命令位(`SYS_EVT_CFG_SAVE` / `SYS_EVT_NET_RECONFIG`)保持消费型等待不变。
|
||||
- 修复:**所有就绪位等待加 `osFlagsNoClear`**(`Src/freertos.c` 的 ftpTask、`App/task/ui_task.c`、`App/sync/time_sync.c`、`App/task/net_task.c`、`test/board/ch395f_test_task.c`);命令位(`SYS_EVT_CFG_SAVE` / `SYS_EVT_NET_RECONFIG`)保持消费型等待不变。
|
||||
- 验证:修后串口出现 `[FTP] waiting for connection...`、21 端口可连;ftpTask 的 `[STACK]` 峰值握手后升到 ~2.5KB、128KB 传输后升到 ~3.4KB(该值曾触发余量告警,已在 2026-09-21 把 lftpd 大局部变量静态化后降到 **1184 B / 4096 B,余量 71%**——见内存方案 §1.4/§0.6)。
|
||||
|
||||
### 8.7 单客户端限制:端口"通"但随后连接被拒(旧会话未释放)
|
||||
@@ -175,7 +175,7 @@
|
||||
- **串口日志 + `DBG_*`**:在 `lftpd.c` / `net_socket` 关键路径加 `DBG_ERROR/INFO` 打印(注意编码安全铁律——只用 Edit 改中文源文件,禁止用 `Get/Set-Content` 整文件重写)。
|
||||
- **抓包**:`ftp_capture.py` 或 Wireshark 过滤 `tcp.port==21`。
|
||||
- **编译验证**:`@build` 必须 0/0 再烧录(AGENTS.md 铁律)。
|
||||
- **套件切换**:`test/test_config.h` 改 `TEST_SUITE_CH395F` / `TEST_SUITE_GD5F` / `TEST_SUITE_STORAGE`(三选一,互斥)。
|
||||
- **套件切换**:`test/board/test_config.h` 改 `TEST_SUITE_CH395F` / `TEST_SUITE_GD5F` / `TEST_SUITE_STORAGE`(三选一,互斥)。
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -51,10 +51,10 @@ ECC 状态(`ECCS1:ECCS0`):`00`=无错;`01/10/11`=纠正 1/2/3 bit;`10`
|
||||
|
||||
### 统一测试调度(ch395fTestTask)
|
||||
|
||||
所有测试套件(CH395F / 存储 / GD5F)统一收归 `ch395fTestTask` 线程(`test/ch395f_test_task.c`
|
||||
的 `StartCh395fTestTask`),通过 `test/test_config.h` 中的 `TEST_SUITE_*` 宏在**编译期**选择要跑的套件。
|
||||
所有测试套件(CH395F / 存储 / GD5F)统一收归 `ch395fTestTask` 线程(`test/board/ch395f_test_task.c`
|
||||
的 `StartCh395fTestTask`),通过 `test/board/test_config.h` 中的 `TEST_SUITE_*` 宏在**编译期**选择要跑的套件。
|
||||
选中 `TEST_SUITE_GD5F` 时,`test_config.h` 会自动 `#define ENABLE_GD5F_TESTS` 及**只读阶段**宏
|
||||
(PHASE1/2/10),随后由 `gd5f_test_run()`(`test/gd5f_test_task.c`)按阶段串行执行。
|
||||
(PHASE1/2/10),随后由 `gd5f_test_run()`(`test/board/gd5f_test_task.c`)按阶段串行执行。
|
||||
|
||||
> **破坏性用例开关(2026-09-21 新增,默认关闭)**:`test_config.h` 的 `ENABLE_DESTRUCTIVE_TESTS`
|
||||
> 控制所有**会改变设备持久状态**的用例——写/擦 NAND、`nand_ftl_format`、FatFS 建文件写文件、
|
||||
@@ -64,7 +64,7 @@ ECC 状态(`ECCS1:ECCS0`):`00`=无错;`01/10/11`=纠正 1/2/3 bit;`10`
|
||||
> dhara 把该计数持久化在 journal checkpoint 头里,普通恢复模式清不掉——见下文容量恢复说明),
|
||||
> 故破坏性用例只在**产品首次上电/产线首启**或明确需要时开启。
|
||||
|
||||
`test/test_config.h` 配置示例(三选一,互斥,多选触发 `#error`):
|
||||
`test/board/test_config.h` 配置示例(三选一,互斥,多选触发 `#error`):
|
||||
|
||||
```c
|
||||
// #define TEST_SUITE_CH395F
|
||||
@@ -84,7 +84,7 @@ ECC 状态(`ECCS1:ECCS0`):`00`=无错;`01/10/11`=纠正 1/2/3 bit;`10`
|
||||
|
||||
### 启用测试
|
||||
|
||||
1. 在 `test/test_config.h` 取消注释所需的 `TEST_SUITE_*` 宏(如 `TEST_SUITE_GD5F`),
|
||||
1. 在 `test/board/test_config.h` 取消注释所需的 `TEST_SUITE_*` 宏(如 `TEST_SUITE_GD5F`),
|
||||
需要写/擦类用例时再打开 `ENABLE_DESTRUCTIVE_TESTS`;
|
||||
2. 编译(`@build`)确认 0 错误 0 警告;
|
||||
3. 烧录后串口观察 `mode: ...` 横幅、`[NAND-TEST]` 日志与各 TC 的 `PASS/FAIL`,结尾打印
|
||||
@@ -634,7 +634,7 @@ ECC 状态(`ECCS1:ECCS0`):`00`=无错;`01/10/11`=纠正 1/2/3 bit;`10`
|
||||
## 12. 存储套件测试(TEST_SUITE_STORAGE / storage_test_run)
|
||||
|
||||
> 本套件独立于 GD5F 驱动套件,由 `test_config.h` 的 `TEST_SUITE_STORAGE` 选择,
|
||||
> 入口 `storage_test_run()`(`test/storage_test_task.c`),统一在 `ch395fTestTask` 中调度。
|
||||
> 入口 `storage_test_run()`(`test/board/storage_test_task.c`),统一在 `ch395fTestTask` 中调度。
|
||||
> 当前 `storage_test_run()` 已覆盖 mkfs/mount/文件写读/性能(与阶段 9 FatFs 同类路径),
|
||||
> 并新增下列三项**集成测试**(TC-STO-01~03),覆盖 FTL journal 掉电恢复、大文件/随机访问、坏块注入下的存储可用性。
|
||||
> 三项均已于 STORAGE 套件实测通过(`=== Storage Tests: 11/11 PASSED (failed=0) ===`)。
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
# SD2506_RTC 测试指南
|
||||
|
||||
> 对应驱动:`Drivers/BSP/SD2506/sd2506.c`
|
||||
> 测试代码:`test/sd2506_test_task.c` + `test/sd2506_test.h`
|
||||
> 测试代码:`test/board/sd2506_test_task.c` + `test/board/sd2506_test.h`
|
||||
|
||||
## 1. 概述
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
## 2. 启用与编译
|
||||
|
||||
`test/test_config.h` 中一次只能启用一个 `TEST_SUITE_*`(互斥):
|
||||
`test/board/test_config.h` 中一次只能启用一个 `TEST_SUITE_*`(互斥):
|
||||
|
||||
```c
|
||||
//#define TEST_SUITE_CH395F
|
||||
@@ -31,7 +31,7 @@
|
||||
> 只跑只读用例:init/读时间、BCD 互转、温度、电池电压、ID、走时校验;
|
||||
> 打开后(`mode: DESTRUCTIVE`)全跑并在结尾复原原始时间——**中途断电可能把板子时间留在测试值**。
|
||||
|
||||
`test/sd2506_test.h` 中控制各阶段(默认全开):
|
||||
`test/board/sd2506_test.h` 中控制各阶段(默认全开):
|
||||
|
||||
```c
|
||||
#define ENABLE_RTC_BASIC_TESTS /* Phase 1: 基本读写 / 走时 */
|
||||
|
||||
@@ -9,7 +9,7 @@
|
||||
|---|---|
|
||||
| 日期 | 2026-09-22(设备 RTC 显示 2026-09-21,落后 1 天,仅显示差异;主机时间戳 = 设备 + 4s) |
|
||||
| 台架 | COM6 @115200;目标 192.168.1.100:8080(Phase 13 独占 socket 2) |
|
||||
| 固件 | `test/test_config.h` = `TEST_SUITE_CH395F`;`test/ch395f_test.h` = `ENABLE_PHASE13_TESTS`(仅此一项) |
|
||||
| 固件 | `test/board/test_config.h` = `TEST_SUITE_CH395F`;`test/board/ch395f_test.h` = `ENABLE_PHASE13_TESTS`(仅此一项) |
|
||||
| 构建 | `MDK-ARM\build.bat` → **0 错误 0 警告**(测试构建与产品构建均 0/0) |
|
||||
| 对端 | `.venv\Scripts\python.exe test\latency_peer.py --mode net`(纯标准库,`--wait 170`) |
|
||||
| 会话顺序 | HELLO → L5_RECV → L5_SEND → L3 → L10 → L6 → L7 → DONE |
|
||||
|
||||
@@ -274,7 +274,7 @@ Select-String -Path 'tools\serial_tool\state\serial.log' -Pattern 'App init OK'
|
||||
... serial_tool.py log --tail 0 # 取本轮全量 → 人眼/脚本检查标记
|
||||
```
|
||||
|
||||
自动化版本 = `test/run_boot_test.py`(同一序列 + 烧录 + 标记校验,见 `自动化测试流程.md`)。
|
||||
自动化版本 = `test/host/run_boot_test.py`(同一序列 + 烧录 + 标记校验,见 `自动化测试流程.md`)。
|
||||
|
||||
### 5.3 长时运行监控
|
||||
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
| **B. 容量恢复** | A 再叠加 `STORAGE_RECOVERY_FULL_WIPE` | 擦净 dhara 可见区 **2044 块**(连 journal checkpoint 一起)+ 重建 BBT;随后**断电重启** | 卷内容全失;2044 次块擦除(实测约 4 秒) |
|
||||
| **C. 日常回归** | 只开 `TEST_SUITE_*`,**不开** `ENABLE_DESTRUCTIVE_TESTS` | 只跑只读/参数校验用例,不写不擦不改坏块表 | 无 |
|
||||
|
||||
三个开关都在 `test/test_config.h`(A/B 的根开关在 `test/storage_test.h`),**默认全关**;维护完请重新注释并编译产品构建。
|
||||
三个开关都在 `test/board/test_config.h`(A/B 的根开关在 `test/board/storage_test.h`),**默认全关**;维护完请重新注释并编译产品构建。
|
||||
|
||||
## 2. 为什么"容量"需要单独恢复(根因)
|
||||
|
||||
@@ -29,8 +29,8 @@
|
||||
|
||||
## 3. 操作步骤(以容量恢复为例)
|
||||
|
||||
1. `test/test_config.h`:取消注释 `TEST_SUITE_STORAGE`;
|
||||
2. `test/storage_test.h`:取消注释 `ENABLE_STORAGE_RECOVERY_TESTS` 与 `STORAGE_RECOVERY_FULL_WIPE`;
|
||||
1. `test/board/test_config.h`:取消注释 `TEST_SUITE_STORAGE`;
|
||||
2. `test/board/storage_test.h`:取消注释 `ENABLE_STORAGE_RECOVERY_TESTS` 与 `STORAGE_RECOVERY_FULL_WIPE`;
|
||||
3. `@build`(要求 0 错误 0 警告);
|
||||
4. 采集顺序 `open` → `clear` → 烧录 → `wait-idle`(擦除 2044 块约 4 秒,静默判据给 20~30s);
|
||||
5. 确认日志:
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
| 层 | 名称 | 载体 | 抓住什么 |
|
||||
|---|---|---|---|
|
||||
| L0 | 静态门禁 | pre-commit 钩子(cppcheck / 代码规范 / 乱码 / 空白 / gitlint)+ `@build` | 编码规范、静态缺陷、任何编译警告 |
|
||||
| L1 | 板端测试套件 | testTask + `test/test_config.h` 套件 | 驱动 / 协议功能(串口 `[PASS]/[FAIL]` + `=== ... PASSED` 汇总) |
|
||||
| L1 | 板端测试套件 | testTask + `test/board/test_config.h` 套件 | 驱动 / 协议功能(串口 `[PASS]/[FAIL]` + `=== ... PASSED` 汇总) |
|
||||
| L2 | 主机侧回归 | `@test` 串口日志标记 + LVGL 模拟器像素 / 池水位回归 | 启动序列、UI 渲染、LVGL 内存池水位 |
|
||||
| L3 | 人工目检 | 上机屏幕、PC 端交互工具 | 视觉内容、自动化无法覆盖的场景 |
|
||||
|
||||
@@ -72,11 +72,11 @@ G0~G3 命令详见 §6 / §7;ui-verify 完整命令见 `UI_自动化测试流
|
||||
|
||||
### 3.1 统一入口与套件互斥
|
||||
|
||||
所有测试套件经唯一入口调度:**testTask**(`test/test_config.c` 的 `start_test_task()`),按 `test/test_config.h` 选中的 `TEST_SUITE_*` 分发到套件运行函数:
|
||||
所有测试套件经唯一入口调度:**testTask**(`test/board/test_config.c` 的 `start_test_task()`),按 `test/board/test_config.h` 选中的 `TEST_SUITE_*` 分发到套件运行函数:
|
||||
|
||||
```mermaid
|
||||
flowchart TD
|
||||
T["testTask: start_test_task()(test/test_config.c)"] -->|TEST_SUITE_CH395F| A["ch395f_test_run()<br/>硬件层 1~5 / NET 层 6~11"]
|
||||
T["testTask: start_test_task()(test/board/test_config.c)"] -->|TEST_SUITE_CH395F| A["ch395f_test_run()<br/>硬件层 1~5 / NET 层 6~11"]
|
||||
T -->|TEST_SUITE_STORAGE| B["storage_test_run()<br/>FTL + FatFS"]
|
||||
T -->|TEST_SUITE_GD5F| C["gd5f_test_run()<br/>10 阶段"]
|
||||
T -->|TEST_SUITE_RTC| D["sd2506_test_run()<br/>2 个阶段组"]
|
||||
@@ -169,8 +169,8 @@ static void phaseN_run(void) {
|
||||
### 3.5 新测试文件 / 新套件 checklist
|
||||
|
||||
1. `test/` 下新建 `xxx_test.h` / `xxx_test_task.c`(按 §3.2 模式);
|
||||
2. `test/test_config.h`:补 `TEST_SUITE_XXX` 注释开关 + 互斥 `#error` 加项 + 分发分支(include + `TEST_SUITE_NAME`);
|
||||
3. `test/test_config.c`:`start_test_task()` 加分发分支;
|
||||
2. `test/board/test_config.h`:补 `TEST_SUITE_XXX` 注释开关 + 互斥 `#error` 加项 + 分发分支(include + `TEST_SUITE_NAME`);
|
||||
3. `test/board/test_config.c`:`start_test_task()` 加分发分支;
|
||||
4. **双端注册核查**(`new-source-file` skill):新 `.c` 必须加入 `MDK-ARM/STM32F407-Demo.uvprojx`;test/ 代码仅 MCU 端编译,**不**登记模拟器 CMakeLists(UI / App 共用代码才需双端);
|
||||
5. `@build` → 0 错 0 警;
|
||||
6. 立 `docs/测试说明/<模块>_Test_Guide.md`(§2 模板);
|
||||
@@ -185,10 +185,10 @@ static void phaseN_run(void) {
|
||||
| 工具 | 位置 | 作用 |
|
||||
|---|---|---|
|
||||
| Python 串口助手(serial_tool) | `tools/serial_tool/serial_tool.py`(.venv + pyserial) | 常驻 daemon + 薄 CLI:列端口 / 开关 / 收发 / 全量日志 / wait-idle |
|
||||
| `test/run_boot_test.py` | `test/` | 一键闭环:采集 → 烧录 → 提取日志 → 校验 |
|
||||
| `test/verify_log.py` | `test/` | 日志标记校验(Required / Forbidden → PASS / FAIL) |
|
||||
| `test/host/run_boot_test.py` | `test/host/` | 一键闭环:采集 → 烧录 → 提取日志 → 校验 |
|
||||
| `test/host/verify_log.py` | `test/host/` | 日志标记校验(Required / Forbidden → PASS / FAIL) |
|
||||
| `.opencode/serial_config.json` | 仓库 | **串口端口单一配置源**(当前 COM6 / 115200);换端口只改这个文件 |
|
||||
| `test/ftp_*.py`(4 个)/ `ch395f_socket_test.py` / `time_sync_server.py` | `test/` | PC 端交互测试工具(FTP 客户端 / socket 回显 / 对时推送) |
|
||||
| `test/host/ftp_*.py`(4 个)/ `ch395f_socket_test.py` / `time_sync_server.py` | `test/host/` | PC 端交互测试工具(FTP 客户端 / socket 回显 / 对时推送) |
|
||||
| `simulator/tests/*.py`(4 个) | `simulator/tests/` | LVGL 模拟器回归脚本(见 §5) |
|
||||
|
||||
### 4.2 新工具约定
|
||||
|
||||
@@ -49,7 +49,7 @@
|
||||
|
||||
| 项 | 说明 |
|
||||
|---|---|
|
||||
| 套件宏 | `TEST_SUITE_XXX`(`test/test_config.h` 选择,套件互斥,见 `测试开发标准流程.md` §3.1) |
|
||||
| 套件宏 | `TEST_SUITE_XXX`(`test/board/test_config.h` 选择,套件互斥,见 `测试开发标准流程.md` §3.1) |
|
||||
| 入口函数 | `xxx_test_run()`(由 `start_test_task()` 统一调度) |
|
||||
| 阶段宏 | `ENABLE_XXX_PHASEN_TESTS`(各阶段使能开关,取消注释启用) |
|
||||
| 运行方式 | 独立运行 / 需 PC 配合(逐阶段标注所需 PC 端工具) |
|
||||
|
||||
@@ -10,7 +10,7 @@
|
||||
├─ Step 0 预检 .venv + serial_tool(selftest/ports 确认 COM)
|
||||
├─ Step 1 构建验证 MDK-ARM/build.bat (0 错误 0 警告才继续)
|
||||
├─ Step 2 烧录 + 采集(一条命令编排:开串口 + 清日志 → 烧录 → wait-idle → 提取)
|
||||
│ test/run_boot_test.py (内置 serial_tool + download.bat + verify_log.py)
|
||||
│ test/host/run_boot_test.py (内置 serial_tool + download.bat + verify_log.py)
|
||||
├─ Step 3 判定:
|
||||
│ PASS → 报告,结束
|
||||
│ FAIL → 依据 [MISS]/[HIT] + 日志尾部,修改代码后回到 Step 1
|
||||
@@ -23,9 +23,9 @@
|
||||
| `@build` | `.opencode/command/build.md` | 仅编译验证(0 错误 0 警告) |
|
||||
| `@download` | `.opencode/command/download.md` | 编译并烧录(ST-Link) |
|
||||
| `@test` | `.opencode/command/test.md` | 完整闭环:build → capture+download → verify → iterate |
|
||||
| `test/run_boot_test.py` | `test/run_boot_test.py` | **一键闭环**:open + clear → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 `[RX]` → verify,退出码 0=PASS/1=FAIL/2=采集或烧录错误/3=用法错误 |
|
||||
| `test/host/run_boot_test.py` | `test/host/run_boot_test.py` | **一键闭环**:open + clear → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 `[RX]` → verify,退出码 0=PASS/1=FAIL/2=采集或烧录错误/3=用法错误 |
|
||||
| `tools/serial_tool/serial_tool.py` | `tools/serial_tool/` | Python 串口助手(常驻 daemon + 薄 CLI):ports/open/send/status/log/clear/wait-idle/selftest;全量日志 `state/serial.log`(20MB 自动截头) |
|
||||
| `test/verify_log.py` | `test/verify_log.py` | 对日志做标记校验,输出 PASS/FAIL 并返回退出码 |
|
||||
| `test/host/verify_log.py` | `test/host/verify_log.py` | 对日志做标记校验,输出 PASS/FAIL 并返回退出码 |
|
||||
|
||||
## 判定标准
|
||||
|
||||
@@ -40,11 +40,11 @@
|
||||
|
||||
| 标记 | 来源 |
|
||||
|---|---|
|
||||
| `App init OK` | `App/app_main.c` |
|
||||
| `RS485 init: OK` | `App/app_main.c` |
|
||||
| `NAND init:` | `App/app_main.c` |
|
||||
| `ADC init:` | `App/app_main.c` |
|
||||
| `SD2506 ID:` / `time:` / `temp:` / `battery:` | `App/app_main.c` |
|
||||
| `App init OK` | `App/app/app_main.c` |
|
||||
| `RS485 init: OK` | `App/app/app_main.c` |
|
||||
| `NAND init:` | `App/app/app_main.c` |
|
||||
| `ADC init:` | `App/app/app_main.c` |
|
||||
| `SD2506 ID:` / `time:` / `temp:` / `battery:` | `App/app/app_main.c` |
|
||||
| `Network Init` / `net init: OK` / `MAC:` / `PHY:` | `App/task/net_task.c` |
|
||||
|
||||
**默认 Forbidden 模式**:`FAIL;ERROR;HardFault;[ERR]`
|
||||
@@ -76,7 +76,7 @@
|
||||
|
||||
- **单模块回归**:`@test` 后接 `-Required` 定制,例如网络回归用
|
||||
`-Required "App init OK;Network Init;net init: OK;PHY: 100M FULL"`。
|
||||
- **测试套件构建**:`test/test_config.h` 开启某个 `TEST_SUITE_*` 后,把套件打印的
|
||||
- **测试套件构建**:`test/board/test_config.h` 开启某个 `TEST_SUITE_*` 后,把套件打印的
|
||||
`=== ... Test:` 标题作为 Required 标记,配合 `test/` 下各用例输出判断。
|
||||
**破坏性用例默认不跑**:`test_config.h` 的 `ENABLE_DESTRUCTIVE_TESTS`(默认关闭)控制写/擦 NAND、
|
||||
格式化、坏块注入与 FatFS 写类用例;关闭时套件为只读模式(开机打印 `mode: READ-ONLY`),
|
||||
|
||||
+10
-10
@@ -131,10 +131,10 @@ sequenceDiagram
|
||||
|
||||
| 文件 | 职责 | 注册 |
|
||||
|---|---|---|
|
||||
| `test/net_latency_test.h` | 计时/统计/报告 API + Phase 入口声明 | 头文件随工程包含路径,无需注册 |
|
||||
| `test/net_latency_test.c` | DWT µs 时基 + 统计 + Phase 12/13/14 用例 | **仅 `MDK-ARM/STM32F407-Demo.uvprojx`**(Test 组;模拟器 CMake 不编 `test/*.c`,与现有测试文件一致) |
|
||||
| `test/latency_peer.py` | PC 端 peer(纯标准库):`--mode net`(M2)/`--mode remo`(M3),`--samples N`,`--json out.json` | 无(Python) |
|
||||
| `test/ftp_regression.py` | D20 复现/回归:单会话 7 次数据连接 + 1KB/32KB 往返内容校验,退出码 = 是否全通过 | 无(Python) |
|
||||
| `test/board/net_latency_test.h` | 计时/统计/报告 API + Phase 入口声明 | 头文件随工程包含路径,无需注册 |
|
||||
| `test/board/net_latency_test.c` | DWT µs 时基 + 统计 + Phase 12/13/14 用例 | **仅 `MDK-ARM/STM32F407-Demo.uvprojx`**(Test 组;模拟器 CMake 不编 `test/*.c`,与现有测试文件一致) |
|
||||
| `test/host/latency_peer.py` | PC 端 peer(纯标准库):`--mode net`(M2)/`--mode remo`(M3),`--samples N`,`--json out.json` | 无(Python) |
|
||||
| `test/host/ftp_regression.py` | D20 复现/回归:单会话 7 次数据连接 + 1KB/32KB 往返内容校验,退出码 = 是否全通过 | 无(Python) |
|
||||
| 本文档 | 分段/架构/流程/基线/缺陷现状 | — |
|
||||
|
||||
### 4.2 阶段编号与构建配置(沿用 `ch395f_test.h` 互斥体系)
|
||||
@@ -146,7 +146,7 @@ ENABLE_PHASE14_TESTS [网] 生产路径时延(L8~L11 + Δ)—— 真实 uiT
|
||||
```
|
||||
|
||||
- Phase 12 归 HW 组,13/14 归 NET 组;13 与 14 可同启(13 用 testTask 私有监听 :8080,14 用生产 :7003,Socket 不冲突);
|
||||
- 测试套件总开关 `TEST_SUITE_CH395F`(`test/test_config.h`);**当前工作副本 = 测试构建**(Phase 14 已启用),
|
||||
- 测试套件总开关 `TEST_SUITE_CH395F`(`test/board/test_config.h`);**当前工作副本 = 测试构建**(Phase 14 已启用),
|
||||
产品构建 = `test_config.h` 与 `ch395f_test.h` 的测试宏全部注释;
|
||||
- 探针宏 `TEST_LATENCY_PROBE` = `TEST_SUITE_CH395F` 且(Phase 13 或 14 启用)→ 仅测试构建定义;
|
||||
- 全部非破坏性 → 只读级,**仅限台架**。
|
||||
@@ -234,7 +234,7 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时
|
||||
### 5.1 M1:Phase 12(SPI 层基线,**无需 PC**)
|
||||
|
||||
```powershell
|
||||
# 0) 前置:test/test_config.h 已启用 TEST_SUITE_CH395F + ENABLE_PHASE12_TESTS
|
||||
# 0) 前置:test/board/test_config.h 已启用 TEST_SUITE_CH395F + ENABLE_PHASE12_TESTS
|
||||
# (产品构建 = 全部注释掉)
|
||||
# 1) 构建(0 错 0 警)
|
||||
& "MDK-ARM\build.bat"
|
||||
@@ -253,7 +253,7 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时
|
||||
### 5.2 M2:Phase 13(芯片+队列基线,**需 PC peer**)
|
||||
|
||||
```powershell
|
||||
# 0) 前置:test/test_config.h 启用 TEST_SUITE_CH395F,test/ch395f_test.h 仅启用
|
||||
# 0) 前置:test/board/test_config.h 启用 TEST_SUITE_CH395F,test/board/ch395f_test.h 仅启用
|
||||
# ENABLE_PHASE13_TESTS(Phase 13 必须独占 8080 socket,勿与其他 NET 层 Phase 同启)
|
||||
& "MDK-ARM\build.bat" # 必须 0 错 0 警
|
||||
# 1) 先 clear 再起 peer(顺序不可反:wait-idle 需要看到会话活跃期)
|
||||
@@ -297,7 +297,7 @@ DTU-RemoteLCD 客户端;输出每帧 `req2first / total / recv 批次到达时
|
||||
--samples 30 --ack-fast --json "docs\测试说明\m3_data\m3_tail_ackfast.json" # 关延迟 ACK
|
||||
```
|
||||
|
||||
### 5.4 D20 回归(`test/ftp_regression.py`)
|
||||
### 5.4 D20 回归(`test/host/ftp_regression.py`)
|
||||
|
||||
单会话内 7 次数据连接 + 1KB/32KB 往返内容校验,退出码 = 是否全通过。
|
||||
**D20 的失败窗口在"每次开机后的第一个 FTP 会话"**(稳态会话恒过)→ 复现/验证必须以
|
||||
@@ -666,7 +666,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
||||
| **`relisten` 段 FAIL、断线固定 ~588ms** | **D10** 回归(退回 `osDelay(500)`) | 核对 `net_relisten_try`/`net_relisten_retry_tick` 非阻塞重试在位(§8.1 D10) |
|
||||
| **远端显示整帧卡住十几秒后自恢复** | **E-02** 回归 | 核对 L3 pending 在位:`net_recv_locked` 阻塞分支登记 pending(哨兵 `NET_PENDING_REGISTERED`)+ `net_pending_tick` 在主循环 + 调用方剩余预算循环(lftpd/timeSync)(§8.3 要点 4) |
|
||||
| **INIT 应答帧字节数字段恒为 0** | **D17** 回归 | 核对 `remo_send_init` 发满 8B(§8.1 D17) |
|
||||
| **开机首个 FTP 会话第 2 个数据连接 425** | **D20**(已定位未修,§8.2) | 复现:`test/ftp_regression.py`(复位开边界);现场规避:客户端重试 425(瞬态 4xx);根治方向:数据 Socket 轮换 |
|
||||
| **开机首个 FTP 会话第 2 个数据连接 425** | **D20**(已定位未修,§8.2) | 复现:`test/host/ftp_regression.py`(复位开边界);现场规避:客户端重试 425(瞬态 4xx);根治方向:数据 Socket 轮换 |
|
||||
| **`[LAT]` 多段数值雷同 / 全 0 却 verdict=OK** | **D18/D19**(测试工装) | 核对 `lat_probe_add_seg` 段名过滤 + `lat_time_init` 调用 + `med==0` 判无效 |
|
||||
| **连接建立后 15~30s 无流量即被 RST** | **D13**:芯片空闲超时(芯片行为) | 客户端须容忍并重连(peer `--wait` 重试是正常路径) |
|
||||
| **peer 重连后 MCU 状态滞留、新连接字节被吞** | **D14**:芯片静默回收 Socket | `net_resync_listen`/`net_relisten` 自愈路径核对 |
|
||||
@@ -703,7 +703,7 @@ sock4 auto-relisten ok / relisten retry ok ← 监听器随后自行恢复
|
||||
6. **S4** 发送块配额与 MSS:48 块按实际使用的 3 个 socket 重新分配(各 16 块),MSS → 1460
|
||||
(3209B 从 4 段降到 1~2 段);**约束**:单次写长度必须 ≤ 发送缓冲(Trap 20 铁律),
|
||||
改分配策略需同步 `net_bind` 重复分配路径,改前先读 `CH395F_Trap_Records.md`,改后跑 Phase 8 吞吐用例;
|
||||
**另**:MSS/块配额变更**必须**跑可信用例(`test/ch395f_socket_test.py tcp_client` 全序列 + 新连接独立 4096B 对照),判据 = **客户端侧内容完全匹配**(勿用带固件内读者的台架配方,其短收是读者吞数据不是故障);
|
||||
**另**:MSS/块配额变更**必须**跑可信用例(`test/host/ch395f_socket_test.py tcp_client` 全序列 + 新连接独立 4096B 对照),判据 = **客户端侧内容完全匹配**(勿用带固件内读者的台架配方,其短收是读者吞数据不是故障);
|
||||
7. **S5** 去掉一次 3200B 拷贝(`g_tx` 直接承接位图,省 ~3.2KB 常驻 RAM;改前跑 `scripts/ram_report.py`);
|
||||
8. **S7** uiTask:`ui_net_sink_poll()` 前置到 `ui_port_step` 前 + while 排空(省按键一整拍);
|
||||
9. **S8** 日志改非阻塞(`fputc` → 环形缓冲 + TX 中断/DMA;处理溢出丢弃与 HardFault 冲刷);
|
||||
|
||||
@@ -147,7 +147,7 @@ python tools/font_gen/extract_cn.py # 任意 python3:
|
||||
|---|---|---|
|
||||
| Python 串口助手 | `tools/serial_tool/serial_tool.py`(仓库内置,.venv + pyserial) | 常驻 daemon + 薄 CLI + 全量日志文件;无需单独安装,`pip install -r requirements.txt` 即就绪 |
|
||||
| 调试串口 | USART1(PA9 TX / PA10 RX),115200 8N1 | **端口单一配置源 `.opencode/serial_config.json`**(本机 COM6);换端口只改这个文件 |
|
||||
| 一键测试 | `test\run_boot_test.py`(即 `@test`,`& '.venv\Scripts\python.exe' test/run_boot_test.py`) | 开串口 + 清日志 → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 → 标记校验;默认端口取 `serial_config.json` / 115200,退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法错误 |
|
||||
| 一键测试 | `test\run_boot_test.py`(即 `@test`,`& '.venv\Scripts\python.exe' test/host/run_boot_test.py`) | 开串口 + 清日志 → 烧录 → wait-idle(静默 8s/超时 30s)→ 提取 → 标记校验;默认端口取 `serial_config.json` / 115200,退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法错误 |
|
||||
|
||||
> 采集 = 端口常开 + daemon 全量日志(`tools/serial_tool/state/serial.log`),无采集窗口/first-byte/EOF 重试仪式。
|
||||
> 命令契约与陷阱见 `docs/测试说明/串口助手设计说明.md`、`docs/测试说明/自动化测试流程.md`。
|
||||
@@ -415,16 +415,16 @@ pre-commit run --all-files
|
||||
|---|---|
|
||||
| 下载方式 | `& "MDK-ARM\download.bat"`(Keil 命令行:烧写 + Reset & Run) |
|
||||
| 下载器 | 工程已配 `UL2CM3` 调试驱动 + `STM32F4xx_1024` Flash 算法;**物理下载器按现场选择**(本机为 ST-Link——不占 COM 口,可与串口调试并存);新机器在 Keil `Options for Target → Debug → Settings` 选择与硬件一致的驱动 |
|
||||
| 调试日志 | USART1 115200;抓开机日志必须**先武装采集再复位**(`test/run_boot_test.py --flash-cmd` 已保证顺序) |
|
||||
| 调试日志 | USART1 115200;抓开机日志必须**先武装采集再复位**(`test/host/run_boot_test.py --flash-cmd` 已保证顺序) |
|
||||
|
||||
### 3.5 功能配置开关
|
||||
|
||||
| 开关 | 位置 | 当前值 | 说明 |
|
||||
|---|---|---|---|
|
||||
| `APP_NET_ENABLE` | `App/app_cfg.h` | 开 | 网络(CH395F + 全部 TCP 服务) |
|
||||
| `APP_NET_ENABLE` | `App/app/app_cfg.h` | 开 | 网络(CH395F + 全部 TCP 服务) |
|
||||
| `APP_ADC_ENABLE` | 同上 | 开 | TPAFE5160 采样 |
|
||||
| `APP_RS485_ENABLE` | 同上 | 开 | RS-485 通信 |
|
||||
| `TEST_SUITE_*` | `test/test_config.h` | 全注释(产品构建) | 测试套件**互斥**:一次构建只开一个(CH395F / 存储 / GD5F / RTC);全注释 = 正常产品固件 |
|
||||
| `TEST_SUITE_*` | `test/board/test_config.h` | 全注释(产品构建) | 测试套件**互斥**:一次构建只开一个(CH395F / 存储 / GD5F / RTC);全注释 = 正常产品固件 |
|
||||
|
||||
---
|
||||
|
||||
|
||||
@@ -428,7 +428,7 @@ flowchart LR
|
||||
| C-2 | §3.3-3/§5.1/§6 | 实物抽查 3 脚(25=NRST、23/24=8MHz、73=PB12) | **由数据手册证据直接关闭,免实测**(25=NRST ✓、23/24=PH0/PH1 ✓、73=PB12 ✓) | DS8626 Table 7 |
|
||||
| C-3 | §4.2 | "INT→PA0(pin4)" | pin4 = **PE5**(代码 `CH395_INT` = GPIOE PIN5 佐证) | DS8626 + main.h |
|
||||
| C-4 | §2.2/§4.6/§5.2/§5.3 | "ST_IN 3 线 = PC15/PC14/PC13(pin3/2/1)"、"启用 PC13/14/15 读 EXTKI" | pin 1/2/3 = **PE2/PE3/PE4**(ST_IN_D4/C3/E4);EXTKI 读取须配 PE2/3/4(V0.1 中 PC13/14/15 已被 V15/J3/F3 子板 LED 线占用) | DS8626 Table 7 |
|
||||
| C-5 | §2.2 | "存储:GD5F2GQ5UE + SD 卡(FatFS)" | 两版网表均无 SDIO 引脚;FatFs 卷在 **SPI NAND** 上(`App/cfg_file_store_mcu.c`:"NAND 上 FatFS 文件 /config.ini")——"SD 卡"系误称 | 网表 + 代码 |
|
||||
| C-5 | §2.2 | "存储:GD5F2GQ5UE + SD 卡(FatFS)" | 两版网表均无 SDIO 引脚;FatFs 卷在 **SPI NAND** 上(`App/cfg/cfg_file_store_mcu.c`:"NAND 上 FatFS 文件 /config.ini")——"SD 卡"系误称 | 网表 + 代码 |
|
||||
| C-6 | §1.3/§2.2/§3.1/§4.1/§4.6/§5.3 | "SPI1 MISO/MOSI(U17.77/78,活动信号,与 NAND 共用)→ 子板 EXTKO1/2 受 SPI 流量干扰;V0.1 需改线" | 77/78 = **PD8/PD9,无 SPI1 的 AF**(SPI1_MOSI/MISO 仅 PA7/PB5/PC12,PB5 已用于 NAND SPI1),代码从未配置 → 实为**未配置悬空线**,"SPI 流量干扰"不成立;无需改线,并入 B3 代码侧 13 线安全电平 | DS8626 Table 9 + .ioc |
|
||||
| C-7 | §4.1 | "VDDA(pin32/33 经 L6)" | 精确化:32 = **VREF+**、33 = VDDA(均经 L6 → 3.3V,VREF+=VDDA 为标准接法 ✓);31 = VSSA → AGND ✓;6 = VBAT、143 = PDR_ON → 3.3V(片内 LDO 开启 ✓);71/106 = VCAP1/VCAP2 → C94/C79 → GND(**值未标注,手册要求 1~4.7µF 低 ESR,待核**) | DS8626 Table 7 + 网表 |
|
||||
| C-8 | 新增 **B4** | ——(初版未发现) | **SWD 的 SWCLK 接 104 = PA12(无 JTAG 功能)→ V0.0 实板 SWD 不通**(实测:实板无法调试,飞线至 PA14 调通);同因 SDCKE 占 109 = PA14(两线脚位互换);V0.1 已修复(SWCLK→109 = PA14、SDCKE→28 = PC2) | DS8626 Table 7/9 + 用户实测 |
|
||||
|
||||
@@ -290,7 +290,7 @@ VDD50、5V、C3.3V、CGND、AVDDL(成员同,仅 C3 封装变)、STM_VDDA
|
||||
| §4.1 / §5.3 | SWCLK = U17.104 | pin 104 = **PA12(无 JTAG 功能,AF 为 USART1_RTS/CAN1_TX/OTG_DP)**;实测证实 **V0.0 实板 SWD 不通**(用户飞线至 PA14=109 后方可调试)→ **V0.0 真实设计缺陷(B4)**,V0.1 已更正 |
|
||||
| §4.7 / §1.6 | "ADC17→U17.46" 列为正常通道 | pin 46 = **PB0,非 ADC 输入脚**(F407 ADC 输入仅 PA0~PA7、PC0~PC7)→ V0.0 的"ADC17"(V_ZL2)通道**电气上无效**(潜伏缺陷,代码当时未读该通道);V0.1 改接 44 = PC4 = ADC12_IN12,缺陷修复 |
|
||||
|
||||
另:V0.0 报告 §2.2 存储项"GD5F2GQ5UE + SD 卡(FatFs)"表述有误——两版网表均无 SDIO 引脚,代码 FatFs 卷在 **SPI NAND** 上(`App/cfg_file_store_mcu.c` 头部:"NAND 上 FatFS 文件 /config.ini(卷根)"),主板本无 SD 卡/SDIO。
|
||||
另:V0.0 报告 §2.2 存储项"GD5F2GQ5UE + SD 卡(FatFs)"表述有误——两版网表均无 SDIO 引脚,代码 FatFs 卷在 **SPI NAND** 上(`App/cfg/cfg_file_store_mcu.c` 头部:"NAND 上 FatFS 文件 /config.ini(卷根)"),主板本无 SD 卡/SDIO。
|
||||
|
||||
### 11.3 V0.1 换脚引脚逐脚核对(30 网全部"电气成立")
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ Python DHCP Server 收到 DISCOVER 包后无法匹配 Offer/Ack 的 xid,握手
|
||||
- magic cookie:`data[236:240]`
|
||||
|
||||
### 对应文件
|
||||
`test/ch395f_socket_test.py` → DHCP server 模式
|
||||
`test/host/ch395f_socket_test.py` → DHCP server 模式
|
||||
|
||||
### 发现时间
|
||||
Phase 6, 2025-07
|
||||
@@ -414,7 +414,7 @@ MobaXterm 上传文件时 CH395F 收到数据(`s1 int=0x04` RECV_OK 持续触
|
||||
2. **反核实**:依据中断做结论前,用 `GET_SOCKET_STATUS` 验证实际状态一致(如"负向事件 vs ESTABLISHED"矛盾时以状态为准)。
|
||||
|
||||
### 参考
|
||||
`test/ch395f_test_task.c: phase2_tc203()`(双保险实现);同类思路见 Phase 1 入口的 PHY_CHANGE 预清。
|
||||
`test/board/ch395f_test_task.c: phase2_tc203()`(双保险实现);同类思路见 Phase 1 入口的 PHY_CHANGE 预清。
|
||||
|
||||
---
|
||||
|
||||
@@ -431,7 +431,7 @@ DHCP 状态位仅代表协商流程完成;IP/MASK/GW 寄存器的提交与状
|
||||
2. **交叉比对**:PC 端将收到的宣告 IP 与所分配租约比对,不一致即报错兜底。
|
||||
|
||||
### 参考
|
||||
`test/ch395f_test_task.c: phase4_run()`;`docs/测试说明/CH395F_Test_Guide.md` 阶段 4 风险表 #4。
|
||||
`test/board/ch395f_test_task.c: phase4_run()`;`docs/测试说明/CH395F_Test_Guide.md` 阶段 4 风险表 #4。
|
||||
|
||||
---
|
||||
|
||||
@@ -456,7 +456,7 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报
|
||||
- 回读类命令(GET_REMOT_IPP / GET_IP_INF 等)若文档标注"低字节在前",打印时务必先按小端重组再格式化,否则会误判。
|
||||
|
||||
### 对应文件
|
||||
`Drivers/BSP/NET/net_socket.c`(`net_connect_locked` 提取 `remote_ip_arr` 大端;`net_send_locked` UDP 目的 IP 同样修正;`[CONN]` 回读按小端重组);`Drivers/BSP/NET/net_types.h`(`remote_ip_arr` 注释改为大端);`test/ch395f_test_task.c`(`test_parse_ip` 可作为大端构建范本)。
|
||||
`Drivers/BSP/NET/net_socket.c`(`net_connect_locked` 提取 `remote_ip_arr` 大端;`net_send_locked` UDP 目的 IP 同样修正;`[CONN]` 回读按小端重组);`Drivers/BSP/NET/net_types.h`(`remote_ip_arr` 注释改为大端);`test/board/ch395f_test_task.c`(`test_parse_ip` 可作为大端构建范本)。
|
||||
|
||||
### 发现时间
|
||||
阶段 7 NET 层 TCP Client 上板实测,2026-08-25。
|
||||
@@ -508,7 +508,7 @@ NET 层 TCP Client(阶段 7)`net_connect()` 返回 0,但 `net_poll()` 报
|
||||
- `net_poll` 用 `GET_GLOB_INT_STATUS_ALL`(2 字节,支持 0~7)并遍历 0~7,Socket n 中断位即 `bit(n+4)`(Socket 0~3→bit4~7,Socket 4~7→bit8~11),原代码正确无需改动。
|
||||
|
||||
### 对应文件
|
||||
`Drivers/BSP/NET/net_socket.c`(`net_init` FUN_PARA + 缓冲分配 + MSS);`test/net_test_task.c`(新增 TC704 八 Socket 并发回显);`test/ch395f_socket_test.py`(`tcp_server` 并发 + `--max-conn`)。
|
||||
`Drivers/BSP/NET/net_socket.c`(`net_init` FUN_PARA + 缓冲分配 + MSS);`test/board/net_test_task.c`(新增 TC704 八 Socket 并发回显);`test/host/ch395f_socket_test.py`(`tcp_server` 并发 + `--max-conn`)。
|
||||
|
||||
### 发现时间
|
||||
阶段 7 扩展 8 Socket 测试,2026-08-25。
|
||||
|
||||
@@ -47,9 +47,9 @@
|
||||
|---|---|
|
||||
| `f8d6e90` | lftpd 侧:新增 `net_recv_to` 接口(片长经 `msg.timeout_ms` 入队、片超时独立返回码 -2);`lftpd_inet_read_line`/`lftpd_inet_read` 改 5ms 分片 + 30s 总预算 + 片间 `vTaskDelay(1)` 让出;M3 压力档复验(17.7s 尖峰 → med 65.0ms/max 133.5ms/零尖峰) |
|
||||
| `4a1605b` | timeSync 侧:`time_sync_handle_conn` 同模式改造(5ms 片/30s 总预算/跨片累积容忍 TCP 分段/超时留痕 `time_sync: no TIME packet in 30s, drop conn`);产品构建 `@test` 闭环 PASS |
|
||||
| `3b28c56` | 审计闭环留档 + 专项回归探针 `test/e02_probe.py` |
|
||||
| `3b28c56` | 审计闭环留档 + 专项回归探针 `test/host/e02_probe.py` |
|
||||
|
||||
**A/B 台架实证**(`test/e02_probe.py`,2026-09-22,设备 192.168.1.100):挂起对时客户端连 :8888
|
||||
**A/B 台架实证**(`test/host/e02_probe.py`,2026-09-22,设备 192.168.1.100):挂起对时客户端连 :8888
|
||||
不发数据,2s 后 PC 测 FTP(:21) banner 时延 = 队列响应性——旧固件 **28554ms**(设备日志实证芯片侧
|
||||
握手与 MCU 侧处理相隔 27s;旧代码 30s 后静默拆连零日志)vs 修复后 **109ms**(产品构建)/ **75ms**
|
||||
(测试构建)。30s 预算拆连与监听恢复行为两侧同构(~8s,2 次 Trap 09 重试)。
|
||||
@@ -212,8 +212,8 @@ B 类(LwIP netconn)的三个构件在本项目的对应物:
|
||||
|
||||
1. CH395F NET 层全套件(Phase 6-14);
|
||||
2. M3 基线重锁:L5 队列往返(预期 ~1ms 量级)、L3/L7 生产路径 Δ;
|
||||
3. `test/e02_probe.py` A/B 回归(队列响应性应优于 5ms 片方案);
|
||||
4. `test/ftp_regression.py`(D20)+ E-06 假 425 场景;
|
||||
3. `test/host/e02_probe.py` A/B 回归(队列响应性应优于 5ms 片方案);
|
||||
4. `test/host/ftp_regression.py`(D20)+ E-06 假 425 场景;
|
||||
5. UI 远端推流压力(ui_net_sink 100Hz);
|
||||
6. timeSync 三场景(挂起 / 部分包 / 正常包);
|
||||
7. 产品构建 `@test` 闭环 + ST-LINK 全片回读;
|
||||
|
||||
@@ -98,7 +98,7 @@
|
||||
|
||||
| 编号 | 位置 | 危害 | 闭环 |
|
||||
|---|---|---|---|
|
||||
| **E-01** | `App/cfg_file.c` | `cfg_file_poll` 的"超长=损坏"检查是**死代码**(读长被钉死在阈值)→ >4096B 配置被截断当有效解析 → 界外内容静默回工厂默认 → 基线粘住错误状态 → 下次开机 load 守卫判"损坏" → **用户配置文件整体销毁** | `d030cb0` + 关联 `70f1cc8`(`f_rename` 不覆盖既有目标) |
|
||||
| **E-01** | `App/cfg/cfg_file.c` | `cfg_file_poll` 的"超长=损坏"检查是**死代码**(读长被钉死在阈值)→ >4096B 配置被截断当有效解析 → 界外内容静默回工厂默认 → 基线粘住错误状态 → 下次开机 load 守卫判"损坏" → **用户配置文件整体销毁** | `d030cb0` + 关联 `70f1cc8`(`f_rename` 不覆盖既有目标) |
|
||||
| **E-31** | `nand_ftl.c` / `journal.c` | 扫描读失败被**覆盖为 `TOO_BAD`** → 非空白卷在 I/O 故障下被误判"全新"→ 直接 `clear` → 映射表整体丢失 | `da1a6e8` |
|
||||
| **E-02** | `net_socket.c` / `lftpd` / `time_sync` | 一条空闲 FTP 控制连接把 netTask 独占 30s → **全体消费者队列停摆**(实测冻结远端显示 17.7s) | `f8d6e90`+`4a1605b`(分片)→ `f16dc9a`(L3 pending 化,结构性消灭) |
|
||||
|
||||
@@ -333,7 +333,7 @@ E-57(`int` / `int32_t` 混用)。
|
||||
|
||||
#### E-16 `cfg_file` 生成文档的边界余量绑死 `snprintf` 返回语义 — **P2** | 模式 P4
|
||||
|
||||
- **位置**:`App/cfg_file.c:469` / `:481`(`s_gen_document`)、
|
||||
- **位置**:`App/cfg/cfg_file.c:469` / `:481`(`s_gen_document`)、
|
||||
同族丢弃点 `:252` / `:256` / `:261`(`s_encode`)、`:642` / `:663` / `:683`(行生成)
|
||||
- **机制**:`off += (size_t)snprintf(...)` —— 直接丢弃返回值。`snprintf` 返回**本应写入的长度**,
|
||||
截断时该值 **> 剩余容量**,`off` 会**跳过缓冲末尾**(越界),而不是停在边界;
|
||||
@@ -381,7 +381,7 @@ E-57(`int` / `int32_t` 混用)。
|
||||
#### E-27 / E-28 socket 表裸指针跨上下文读 — **P2** | 模式 P2 / P7
|
||||
|
||||
- **位置**:`Drivers/BSP/NET/net_socket.c`(`net_get_sock()` 返回裸指针)、
|
||||
`App/time_sync.c` / `Drivers/BSP/NET/lftpd/lftpd.c`(代次号读取)
|
||||
`App/sync/time_sync.c` / `Drivers/BSP/NET/lftpd/lftpd.c`(代次号读取)
|
||||
- **机制**:`net_get_sock()` 把 socket 控制块**裸指针**交给调用方,调用方随后读
|
||||
`p_sock->state`;netTask 可能在同一时刻改写该结构。
|
||||
- **后果**:读到中间态的 `state`(例如"刚 `CLOSED` 但字段未清")。
|
||||
@@ -555,7 +555,7 @@ E-57(`int` / `int32_t` 混用)。
|
||||
|
||||
超时参数(`net_config.h`):`NET_SEND_TIMEOUT_MS=1000`、`NET_RECV_TIMEOUT_MS=30000`。
|
||||
|
||||
## 附录 B:事件位表(`App/sys_events.h`)
|
||||
## 附录 B:事件位表(`App/app/sys_events.h`)
|
||||
|
||||
| 位 | 名称 | 语义 | 置位者 | 消费者 |
|
||||
|---|---|---|---|---|
|
||||
|
||||
@@ -171,7 +171,7 @@ def read_doc(path: pathlib.Path):
|
||||
"""读文档,返回 (文本, 原换行符, 是否有 BOM)。
|
||||
|
||||
本仓库 core.autocrlf=true 且无 .gitattributes,工作区换行混杂
|
||||
(README=LF、AGENTS=CRLF);带 BOM 文件(App/cfg_file.c 等)另有铁律。
|
||||
(README=LF、AGENTS=CRLF);带 BOM 文件(App/cfg/cfg_file.c 等)另有铁律。
|
||||
--write 必须**按原样回写**,否则整文件行尾/BOM 漂移 → 巨型无意义 diff。
|
||||
"""
|
||||
raw = path.read_bytes()
|
||||
|
||||
+1
-1
@@ -47,7 +47,7 @@ simulator/
|
||||
| `sim/sim_port.c` | 创建 SDL 窗口显示设备(`lv_sdl_window_create`)、初始化 **mono 主题**(`lv_theme_mono_init`,1bpp 必需)、创建键盘输入设备并挂默认输入组。**不创建鼠标**(纯键盘导航,与 MCU 端 keypad 一致)。`sim_port_get_screen_mono()` 经 `SDL_RenderReadPixels` 读回屏幕像素转 1bpp,供推流取帧 |
|
||||
| `sim/net_socket_sim.c` | 网络后端:Winsock 实现 `net_*` BSD Socket API(`socket`/`bind`/`listen`/`accept`/`recv`/`send`/`close`),替代 MCU 端 `Drivers/BSP/NET/net_socket.c`(CH395F) |
|
||||
| `sim/ui_net_sink_backend_sim.c` | RemoDispBus 平台 backend:`ui_net_sink_get_lcdmem`→`sim_port_get_screen_mono`、`ui_net_sink_inject_key`→`lv_group_send_data`;配合**共享** `Drivers/BSP/UI/ui_net_sink.c`(协议服务端,双端同一份,TCP 7003) |
|
||||
| `sim/cfg_file_store_sim.c` | 通用配置文件存储后端:本地文件 `sim_config.ini`(`fopen`/`rename` 原子写),替代 MCU 端 `App/cfg_file_store_mcu.c`(FatFS);旧档 `sim_netcfg.bin` 首启自动迁移进 `sim_config.ini` |
|
||||
| `sim/cfg_file_store_sim.c` | 通用配置文件存储后端:本地文件 `sim_config.ini`(`fopen`/`rename` 原子写),替代 MCU 端 `App/cfg/cfg_file_store_mcu.c`(FatFS);旧档 `sim_netcfg.bin` 首启自动迁移进 `sim_config.ini` |
|
||||
| `lv_conf.h` | 模拟器专用 LVGL 配置。与 MCU 端 `Lib/lv_conf.h` 的关键差异见 §3.3 |
|
||||
| `dbg_log.h` | MCU 版 `dbg_log.h` 依赖 `sys_clock.h`(RTC 时间戳),PC 无法编译。此 stub 把 `DBG_INFO/ERROR/DEBUG` 映射到 `printf`;因 `simulator/` 在 include 路径最前,**优先生效**覆盖 MCU 版 |
|
||||
| `build_sim.bat` / `build_sim.ps1` | 一键构建入口:vswhere 探测本机 VS 大版本(16=2019 / 17=2022 / 18=2026,取已装最高)→ 映射 CMake 生成器;`build/` 缓存生成器与本机不符(换机/升级 VS)时自动删除重建(带重试,抗文件锁)。**构建入口一律走它,文档/命令中勿写死生成器版本**;`.bat` 仅负责绕过 PowerShell 执行策略并转交 `.ps1` |
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
* 模块名称:sim_latency_stub
|
||||
* 模块功能:链路时延探针(net_latency_test.h)的宿主空实现——探针打点站点位于
|
||||
* 双端共享核心(ui_net_sink.c,TEST_LATENCY_PROBE 使能时编译),
|
||||
* MCU 端符号由 test/net_latency_test.c 提供(DWT CYCCNT 时基,
|
||||
* MCU 端符号由 test/board/net_latency_test.c 提供(DWT CYCCNT 时基,
|
||||
* MCU 专属、宿主不可编译);模拟器构建在此以空操作满足链接,
|
||||
* 不计时、不出报告(时延测量属台架能力,模拟器无意义)
|
||||
* 适用平台:PC 模拟器(仅 simulator 构建编译本文件)
|
||||
|
||||
+14
-28
@@ -1,41 +1,24 @@
|
||||
# test/ — 测试代码与主机端脚本
|
||||
|
||||
> 测试分两部分:**板端测试套件**(`.c/.h`,编入固件由 testTask 执行)与
|
||||
> **主机端脚本**(`.py`,PC 侧驱动板子并判读结果)。
|
||||
> 测试分两部分,**物理隔离**在两个子目录:
|
||||
> - **`board/`** —— 板端测试套件(`.c/.h`,编入固件由 testTask 执行)
|
||||
> - **`host/`** —— 主机端脚本(`.py`,PC 侧驱动板子并判读结果)
|
||||
|
||||
## 板端测试套件(编入固件)
|
||||
## 目录结构
|
||||
|
||||
| 文件 | 测试对象 |
|
||||
|---|---|
|
||||
| `test_config.c/h` | 测试任务配置(启用哪些套件) |
|
||||
| `ch395f_test_task.c/h` + `ch395f_test.h` | CH395F 以太网(硬件层 + NET 层) |
|
||||
| `gd5f_test_task.c/h` + `gd5f_test.h` | GD5F2GQ5UE SPI NAND 存储 |
|
||||
| `sd2506_test_task.c/h` + `sd2506_test.h` | SD2506 RTC |
|
||||
| `storage_test_task.c/h` + `storage_test.h` | 存储性能 |
|
||||
| `net_test_task.c/h` + `net_latency_test.c/h` | 网络层 / 链路时延 |
|
||||
| `nand_ftl_test.c`(如有) | FTL 层 |
|
||||
|
||||
## 主机端脚本(PC 侧)
|
||||
|
||||
| 脚本 | 作用 |
|
||||
|---|---|
|
||||
| `run_boot_test.py` | **`@test` 一键闭环**:开串口+清日志 → 烧录 → wait-idle → 校验(退出码 0=PASS) |
|
||||
| `verify_log.py` | 日志标记校验(Required/Forbidden 标记) |
|
||||
| `ch395f_socket_test.py` | Socket 通信测试 |
|
||||
| `ftp_test.py` / `ftp_up_dl_test.py` / `ftp_speed_test.py` | FTP 功能 / 上传下载 / 速度 |
|
||||
| `ftp_capture.py` / `ftp_regression.py` | FTP 抓包 / 回归 |
|
||||
| `e02_probe.py` | E-02 专项探针 |
|
||||
| `latency_peer.py` | 链路时延对端(PC peer) |
|
||||
| `time_sync_server.py` | 时间同步推送服务 |
|
||||
| 目录 | 内容 | README |
|
||||
|---|---|---|
|
||||
| `board/` | 板端测试套件(编入 Keil 工程,占 RAM) | [`board/README.md`](board/README.md) |
|
||||
| `host/` | PC 端测试/判读脚本(Python) | [`host/README.md`](host/README.md) |
|
||||
|
||||
## 运行方式
|
||||
|
||||
```bash
|
||||
# @test 一键闭环(推荐)
|
||||
& '.venv\Scripts\python.exe' test/run_boot_test.py
|
||||
& '.venv\Scripts\python.exe' test/host/run_boot_test.py
|
||||
|
||||
# 单独校验日志
|
||||
& '.venv\Scripts\python.exe' test/verify_log.py <日志文件>
|
||||
& '.venv\Scripts\python.exe' test/host/verify_log.py <日志文件>
|
||||
```
|
||||
|
||||
退出码约定:`0`=PASS / `1`=FAIL / `2`=采集或烧录错误 / `3`=用法或预检错误。
|
||||
@@ -43,7 +26,10 @@
|
||||
## ⚠️ 注意
|
||||
|
||||
- 本目录**被 pre-commit 门禁排除**(测试代码不受 C 规范约束)
|
||||
- 板端套件占用 RAM,启用前先核算预算(见 `docs/内存管理/`)
|
||||
- `board/` 套件占用 RAM,启用前先核算预算(见 `docs/内存管理/`)
|
||||
- **Keil 工程已同步**:`board/` 下 7 个 `.c` 编入 `MDK-ARM/STM32F4-Demo.uvprojx`,
|
||||
IncludePath 含 `../test/board`;移动文件须同步改工程文件
|
||||
- 套件选择开关:`board/test_config.h` 的 `TEST_SUITE_*`(互斥,一次只启用一个)
|
||||
- 测试缓冲用**分 Phase 复用静态缓冲**(避免 `L6406E` 溢出)
|
||||
|
||||
## 相关文档
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
# test/board/ — 板端测试套件
|
||||
|
||||
> ⚠️ **编入固件**的测试代码(由 testTask 执行)。这些 `.c` 已注册到 Keil 工程
|
||||
> `MDK-ARM/STM32F4-Demo.uvprojx`,占用 MCU 的 RAM/Flash。
|
||||
|
||||
## 文件一览
|
||||
|
||||
| 文件 | 测试对象 / 作用 |
|
||||
|---|---|
|
||||
| `test_config.c/h` | **测试任务配置**:`TEST_SUITE_*` 套件选择开关(互斥)+ `ENABLE_DESTRUCTIVE_TESTS` |
|
||||
| `ch395f_test_task.c/h` + `ch395f_test.h` | CH395F 以太网(硬件层 Phase 1~5 / NET 层 Phase 6~11) |
|
||||
| `gd5f_test_task.c/h` + `gd5f_test.h` | GD5F2GQ5UE SPI NAND 存储 |
|
||||
| `sd2506_test_task.c/h` + `sd2506_test.h` | SD2506 RTC |
|
||||
| `storage_test_task.c/h` + `storage_test.h` | 存储性能 |
|
||||
| `net_test_task.c/h` | 网络层测试 |
|
||||
| `net_latency_test.c/h` | 链路时延探针(DWT CYCCNT 时基,MCU 专属) |
|
||||
|
||||
## ⚠️ 构建约束(`AGENTS.md` 详述)
|
||||
|
||||
- **套件互斥**:`test_config.h` 的 `TEST_SUITE_CH395F/STORAGE/GD5F/RTC` 一次只能启用一个
|
||||
(违反则 `#error`);**全部注释 = 产品构建**
|
||||
- **破坏性用例默认关闭**:`ENABLE_DESTRUCTIVE_TESTS`(默认注释)控制写/擦 NAND、格式化、
|
||||
坏块注入。关闭时为**只读模式**(横幅 `mode: READ-ONLY`),可随时在在用设备上跑
|
||||
- ⚠️ 实测一轮破坏性 GD5F 运行即让 dhara **多记一个坏块**(容量下降且需全片擦除恢复)——
|
||||
只在产线首启或明确需要时打开
|
||||
- CH395F 套件:硬件层与 NET 层模式互斥
|
||||
- **总线独占**:CH395F 硬件层模式下 netTask 自挂起,testTask 独占 CH395F
|
||||
|
||||
## 添加新测试套件
|
||||
|
||||
1. 在 `test_config.h` 加开关(并入互斥 `#error` 检查)
|
||||
2. 新建 `<模块>_test_task.c/h`
|
||||
3. **注册进 Keil 工程**(`<FilePath>..\test\board\xxx.c</FilePath>`)
|
||||
4. 跑回归:`@test`(`test/host/run_boot_test.py`)
|
||||
|
||||
## 相关文档
|
||||
|
||||
- 测试指南:`docs/测试说明/CH395F_Test_Guide.md`、`GD5F2GQ5UE_Test_Guide.md`、`SD2506_Test_Guide.md`、`FTP_Test_Guide.md`
|
||||
- 套件配置:`AGENTS.md`「测试与验证」章
|
||||
- 容量恢复:`docs/测试说明/存储维护与容量恢复.md`
|
||||
@@ -0,0 +1,52 @@
|
||||
# test/host/ — 主机端测试脚本
|
||||
|
||||
> PC 侧的测试驱动与判读脚本(Python,跑在开发机上,经串口/网络与目标板交互)。
|
||||
|
||||
## 文件一览
|
||||
|
||||
### 流程与判读
|
||||
|
||||
| 脚本 | 作用 |
|
||||
|---|---|
|
||||
| `run_boot_test.py` | **`@test` 一键闭环**:开串口+清日志 → 烧录 → wait-idle → `verify_log` 校验(退出码 0=PASS) |
|
||||
| `verify_log.py` | **日志标记校验**:Required / Forbidden 标记 → PASS / FAIL |
|
||||
| `e02_probe.py` | E-02 专项探针(错误码传播审计) |
|
||||
|
||||
### 网络 / FTP
|
||||
|
||||
| 脚本 | 作用 |
|
||||
|---|---|
|
||||
| `ch395f_socket_test.py` | Socket 通信测试(回显服务器 / 文件收发) |
|
||||
| `ftp_test.py` | FTP 基本功能测试 |
|
||||
| `ftp_up_dl_test.py` | FTP 上传下载测试 |
|
||||
| `ftp_speed_test.py` | FTP 传输速度测试 |
|
||||
| `ftp_capture.py` | FTP 流量抓取 |
|
||||
| `ftp_regression.py` | FTP 回归套件 |
|
||||
|
||||
### 时间 / 时延
|
||||
|
||||
| 脚本 | 作用 |
|
||||
|---|---|
|
||||
| `latency_peer.py` | 链路时延测试的 PC 对端(peer) |
|
||||
| `time_sync_server.py` | 时间同步推送服务(对时源) |
|
||||
|
||||
## 运行方式
|
||||
|
||||
```bash
|
||||
# @test 一键闭环(推荐)
|
||||
& '.venv\Scripts\python.exe' test/host/run_boot_test.py
|
||||
```
|
||||
|
||||
> 串口端口配置在 `.opencode/serial_config.json`(单一配置源,当前 COM6/115200)。
|
||||
|
||||
## ⚠️ 注意
|
||||
|
||||
- **PYTHONPATH/路径敏感**:脚本按仓库根相对路径读写,**从仓库根执行**
|
||||
- 本目录**被 pre-commit 门禁排除**
|
||||
- 台架探针族(TCP 复连 / FTP 中止等)在 `MDK-ARM/*.py`,与本目录分工不同
|
||||
|
||||
## 相关文档
|
||||
|
||||
- `docs/测试说明/自动化测试流程.md` — `@test` 细节与失败模式
|
||||
- `docs/测试说明/测试开发标准流程.md` — 测试分层与门禁
|
||||
- `docs/测试说明/CH395F_Test_Guide.md`、`FTP_Test_Guide.md`
|
||||
@@ -12,7 +12,7 @@ net 层当作"刚建立就断开"释放。修复见 net_socket.c handle_disconne
|
||||
内容校验;任一环节失败即退出码 1。
|
||||
|
||||
用法:
|
||||
& '.venv\\Scripts\\python.exe' test/ftp_regression.py --host 192.168.1.100
|
||||
& '.venv\\Scripts\\python.exe' test/host/ftp_regression.py --host 192.168.1.100
|
||||
"""
|
||||
|
||||
import argparse
|
||||
@@ -31,7 +31,7 @@ import sys
|
||||
import threading
|
||||
import time
|
||||
|
||||
# --- Protocol constants (mirror test/net_latency_test.c Phase 13 defines) ---
|
||||
# --- Protocol constants (mirror test/board/net_latency_test.c Phase 13 defines) ---
|
||||
HELLO = b"\x5a\xa5\x58\x01"
|
||||
OP_L5_RECV = 0x01
|
||||
OP_L5_SEND = 0x02
|
||||
@@ -19,7 +19,7 @@
|
||||
- 烧录带超时(默认 180s;旧版无超时,坏 SWD 连接会永久挂起)
|
||||
|
||||
用法:
|
||||
& '.venv\\Scripts\\python.exe' test/run_boot_test.py
|
||||
& '.venv\\Scripts\\python.exe' test/host/run_boot_test.py
|
||||
[--port COM7] [--baud-rate 115200] [--settle-ms 8000] [--max-wait-ms 30000]
|
||||
[--flash-cmd MDK-ARM\\download.bat] [--flash-timeout 180]
|
||||
[--required "App init OK;Network Init;net init: OK"]
|
||||
@@ -8,7 +8,7 @@
|
||||
板子端在 timeSyncTask 中以 TCP Server 方式监听端口,收到后调用
|
||||
sys_clock_set_unix() 更新系统墙钟并写回 SD2506 RTC,使板子时间 == 你电脑的时间。
|
||||
|
||||
协议(板子端实现见 App/time_sync.c 的 time_sync_handle_conn):
|
||||
协议(板子端实现见 App/sync/time_sync.c 的 time_sync_handle_conn):
|
||||
字节 0..3 : 魔术字 "TIME" (0x54 0x49 0x4D 0x45)
|
||||
字节 4..7 : 本地 Unix 时间戳,uint32,大端(主机字节序转换后由板子分解)
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
输出结构化判定(格式与旧 PowerShell 版逐字一致,下游文档/习惯不受影响)。
|
||||
|
||||
用法:
|
||||
& '.venv\\Scripts\\python.exe' test/verify_log.py --log-path <file>
|
||||
& '.venv\\Scripts\\python.exe' test/host/verify_log.py --log-path <file>
|
||||
[--required 'marker1;marker2']
|
||||
[--forbidden 'FAIL;ERROR;HardFault;assert;[ERR]']
|
||||
[--show-tail-lines 40]
|
||||
@@ -15,7 +15,7 @@
|
||||
1 = FAIL(缺 Required 或命中 Forbidden)
|
||||
2 = ERROR(日志文件不存在/不可读)
|
||||
|
||||
默认 Required 标记对应 STM32F4-Base 启动序列(见 App/app_main.c + App/task/net_task.c),
|
||||
默认 Required 标记对应 STM32F4-Base 启动序列(见 App/app/app_main.c + App/task/net_task.c),
|
||||
按测试用例覆盖,例如:
|
||||
--required 'App init OK;net init: OK;PHY: 100M FULL'
|
||||
--forbidden 'FAIL;ERROR;HardFault;assert;[ERR]'
|
||||
@@ -59,7 +59,7 @@ L_FILE = dict(
|
||||
"设备写:tmp + rename(原子);变更识别:size + mtime"],
|
||||
)
|
||||
L_ENGINE = dict(
|
||||
title="cfg_file(配置文件引擎)", sub="App/cfg_file.c · 双端共享", color="#2563eb", bg="#eff6ff",
|
||||
title="cfg_file(配置文件引擎)", sub="App/cfg/cfg_file.c · 双端共享", color="#2563eb", bg="#eff6ff",
|
||||
chips=["INI 解析 / 序列化(逐键校验 · 容错 · 自愈)",
|
||||
"外科手术式保存(保留注释 / 未知段 → 降级安全)",
|
||||
"2s 变更轮询(f_stat)+ 段变更回调",
|
||||
|
||||
Reference in New Issue
Block a user