diff --git a/App/README.md b/App/README.md new file mode 100644 index 00000000..1230a264 --- /dev/null +++ b/App/README.md @@ -0,0 +1,49 @@ +# App/ — 应用层 + +> **自研代码**(非 CubeMX 生成、非第三方库)。本目录是项目的**应用层**:任务编排、业务逻辑、 +> 日志与配置引擎、工具函数。所有文件遵循 `docs/代码规范/嵌入式C语言代码规范_V1.0.md`。 + +## 职责 + +`Src/main.c`(CubeMX 初始化)→ `app_main_init`(本目录 `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/` | 通信协议(预留) | — | + +## 关键约束 + +- **配置引擎单任务收敛**:`cfg_file` 为静态态、属主是 defaultTask;UI 保存请求经 + `SYS_EVT_CFG_SAVE` 事件唤醒,netTask/uiTask **不得直接触碰**配置引擎 +- **syslog 唯一写者**:`/log/*` 只由 defaultTask 写入 +- 新增任务/缓冲/栈前**必须先核算 RAM 余量**(`docs/内存管理/`) + +## 相关文档 + +- 架构全景:`docs/架构设计/项目架构总览.md` +- 启动顺序:`docs/架构设计/项目启动顺序管理.md` +- 配置引擎:`docs/子系统设计/配置文件设计说明.md` +- 日志:`docs/子系统设计/控制台单写者日志设计说明.md`、`docs/子系统设计/运行与自检记录设计说明.md` diff --git a/App/log/README.md b/App/log/README.md new file mode 100644 index 00000000..a456f949 --- /dev/null +++ b/App/log/README.md @@ -0,0 +1,34 @@ +# App/log/ — 日志子系统 + +> 两类日志:**持久化运行日志**(`sys_log`,落 NAND)与**控制台日志**(`console_log`,走串口)。 +> 两者都遵循**单写者**模型,避免多任务交错输出。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `sys_log.h` | **日志接口(平台无关)**:定长 64B 记录写入 `/log/run.log`·`selftest.log` | +| `sys_log_mcu.c` | `sys_log` 的 MCU 端后端实现(NAND + FatFs) | +| `console_log.c/h` | **控制台单写者日志**:多任务日志经队列汇入唯一写者,避免串口输出交错 | + +## 关键机制 + +### syslog(运行/自检记录) + +- **唯一写者 = defaultTask**;其它任务只投递,不直接写盘 +- **单记录定长 64 B**,循环写;待机页可显示记录 +- **内核启动前的日志**走**无锁静态缓冲** `s_preboot[8]` 暂存(因为内核启动前不能建队列), + 内核启动后由 `syslog_drain` 惰性创建真队列并排空 +- ⚠️ 写盘必须校验 `f_write` 返回的**字节数**(该 FatFs 移植在簇分配失败时返回 `FR_OK` + 短写, + 不报错误码);追加写必须 `FA_WRITE|FA_OPEN_APPEND`(`FA_OPEN_APPEND` 单独用**不含写位**) + +### console_log(控制台单写者) + +- 多任务的生产者 → **单写者消费者**,消除任务间日志行交错 +- 设计详见 `docs/子系统设计/控制台单写者日志设计说明.md` + +## 相关文档 + +- `docs/子系统设计/控制台单写者日志设计说明.md` +- `docs/子系统设计/运行与自检记录设计说明.md` +- FatFs 陷阱:`AGENTS.md`「平台约束」 diff --git a/App/protocol/README.md b/App/protocol/README.md new file mode 100644 index 00000000..9871a636 --- /dev/null +++ b/App/protocol/README.md @@ -0,0 +1,12 @@ +# App/protocol/ — 通信协议(预留) + +> **占位目录**:规划用于存放自定义通信协议实现(解析 / 组帧 / 状态机)。 +> 当前为空(仅 `.gitkeep`),协议相关实现暂分散在: +> - RS-485 侧:`App/task/rs485_task.c` + `App/util/crc.c` + `App/util/ringbuf.c` +> - 网络侧:`Drivers/BSP/NET/` +> - 远端显示:`docs/UI设计/RemoDispBus协议与接收设计说明.md` + +## 何时使用本目录 + +当出现**跨接口复用的协议逻辑**(如统一的帧编解码器、协议状态机)时,落到此处, +避免散落到各 task 里。新增后请在本 README 补一行说明。 diff --git a/App/task/README.md b/App/task/README.md new file mode 100644 index 00000000..f30d2078 --- /dev/null +++ b/App/task/README.md @@ -0,0 +1,39 @@ +# App/task/ — FreeRTOS 任务实现 + +> 6 个任务的入口函数与任务体。任务创建在 `Src/freertos.c`(`MX_FREERTOS_Init`), +> **栈大小/优先级的唯一事实源也是 `Src/freertos.c`**;本目录只放任务**实现**。 + +## 任务清单 + +| 文件 | 任务 | 优先级 | 职责 | +|---|---|---|---| +| `default_task.c/h` | defaultTask | Normal | FTL + FatFS 挂载、配置引擎属主、syslog 唯一写者、LED 指示 | +| `net_task.c/h` | netTask | Normal | `net_stack_bring_up` → 置 NET_READY → 循环 `net_poll` + `net_process_messages` | +| `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 | 墙钟时间同步(实现不在本目录) | + +> 上表栈大小/优先级以 `Src/freertos.c` 为准(`README.md`/`AGENTS.md` 的任务表由 +> `scripts/gen_task_table.py` 生成,勿手抄)。 + +## 就绪屏障(重要) + +任务间**不用魔法延时**,改用 `App/sys_events.h` 的 Event Flags: + +- `SYS_EVT_NET_READY` / `SYS_EVT_STORAGE_READY` 等是**状态位**——等待时必须 + `osFlagsWaitAny|osFlagsNoClear`,**不能用默认消费型等待**(否则先到的消费者会清掉位, + 导致 `ftpTask` 的 `WaitAll(两位)` 永不成立 → FTP 静默不监听) +- `SYS_EVT_CFG_SAVE` / `SYS_EVT_NET_RECONFIG` 等**命令位**保持消费型等待 + +## 平台约束(改本目录前必读) + +- **内核启动前禁止任何 FreeRTOS/CMSIS-RTOS API 调用**(`osMessageQueueNew` 等会杀死启动) +- 就绪屏障位一律用 `osFlagsNoClear` +- 内存预算紧张,改栈/缓冲前先核算(`docs/内存管理/`) + +## 相关文档 + +- 启动顺序与屏障:`docs/架构设计/项目启动顺序管理.md` +- 内存与定栈规则:`docs/内存管理/RAM使用分析与优化方案.md` +- 栈水位实测:`scripts/stack_report.py` diff --git a/App/util/README.md b/App/util/README.md new file mode 100644 index 00000000..7d54139c --- /dev/null +++ b/App/util/README.md @@ -0,0 +1,29 @@ +# App/util/ — 通用工具函数 + +> 平台无关的纯工具模块(无 FreeRTOS 依赖、无硬件依赖),可在 MCU 与 PC 模拟器中共用。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `crc.c/h` | 校验算法(CRC16/CRC32 等,供 RS-485 协议与数据校验使用) | +| `ringbuf.c/h` | 环形缓冲(SPSC 无锁环形队列,用于串口/数据流收发) | +| `sys_clock.c/h` | **墙钟时间管理**:RTC 基准、tick 回绕防护、每 30 天惰性再基准化 | + +## 设计要点 + +### sys_clock + +- 以 SD2506 RTC 为基准,HAL tick 计数补齐亚秒精度 +- **49.7 天 tick 回绕防护**:每 30 天惰性再基准化(`sys_clock_get` 内部触发) +- RTC 故障时降级到默认时间基准并返回 -1,触发"时钟芯片异常"自检上报 +- 设计详见 `docs/子系统设计/系统墙钟时间维护说明.md` + +### ringbuf + +- 单生产者单消费者(SPSC)无锁设计,配合 DMA/中断收发 +- 容量为 2 的幂,用掩码取模(避免除法开销) + +## 相关文档 + +- `docs/子系统设计/系统墙钟时间维护说明.md` diff --git a/Drivers/BSP/CH395F/README.md b/Drivers/BSP/CH395F/README.md new file mode 100644 index 00000000..770d8cfe --- /dev/null +++ b/Drivers/BSP/CH395F/README.md @@ -0,0 +1,34 @@ +# Drivers/BSP/CH395F/ — CH395F 以太网控制器驱动 + +> CH395F 是 SPI 接口的 10/100M 以太网 MAC+PHY 控制器。本目录是其**底层寄存器级驱动**, +> 上层的 BSD Socket 抽象见 `../NET/`。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `ch395f.c/h` | SPI 命令收发、寄存器读写、芯片初始化、通道/中断管理 | + +## 关键点 + +- **SPI 接口**:SPI2(PB12 CS / PB13 SCK / PB14 MISO / PB15 MOSI) +- **每次 SPI 事务必须 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹** +- **SPI 分频系数必须为 8**(PCB 信号完整性约束,**勿"优化"改快**) +- 芯片最多 8 个 socket,本层用**事件中断 + 周期轮询**驱动 +- PHY 强制 **100M 全双工**(`net_task` 中配置) + +## ⚠️ 改本驱动前必读陷阱(Trap Records) + +| Trap | 问题 | 状态 | +|---|---|---| +| Trap 21 | TC-NET-604 "RX 窗口冻结" 判定为**非缺陷**(原报告系测试程序自吞数据 + 判读工具误判) | ✅ 结案 | +| Trap 22 | **快速复连丢 CONNECT/DISCONNECT 中断 → 监听静默死亡**;修复 = `net_reconcile_tick()` 周期对账自愈 | ✅ 已修 | +| Trap 23 | **上传中止后首笔复连被静默截断(≤2048B)并误报成功**;修复 = 异常释放后复监听隔离排空 | ✅ 已修 | + +> 完整台账与复现配方见 `docs/问题记录/CH395F_Trap_Records.md`(**改驱动前必读**)。 + +## 相关文档 + +- 测试指南:`docs/测试说明/CH395F_Test_Guide.md` +- 上层抽象:`../NET/README.md` +- 台架探针:`MDK-ARM/tcp_reconnect_probe.py`、`MDK-ARM/ftp_abort_probe.py` diff --git a/Drivers/BSP/GD5F2GQ5UE/README.md b/Drivers/BSP/GD5F2GQ5UE/README.md new file mode 100644 index 00000000..f09710f3 --- /dev/null +++ b/Drivers/BSP/GD5F2GQ5UE/README.md @@ -0,0 +1,46 @@ +# Drivers/BSP/GD5F2GQ5UE/ — GD5F2GQ5UE SPI NAND 驱动 + FTL + +> 256MB SPI NAND Flash 驱动,以及之上的 **FTL(Flash 转换层,`nand_ftl.c`)**—— +> 提供逻辑块映射、坏块管理、磨损均衡。再上层是 dhara(坏块/磨损算法)与 FatFs。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `gd5f2gq5ue.c/h` | NAND 芯片底层驱动:读/写/擦除、页/块管理、ID 与状态查询 | +| `nand_ftl.c/h` | **FTL 层**:逻辑地址 → 物理地址映射、坏块表、磨损均衡 | + +## 硬件接口 + +- **SPI1**:PE0 CS / PB3 SCK / PB4 MISO / PB5 MOSI / PB8 WP / PE1 HOLD + +## 三层存储栈 + +``` +FatFs(文件系统) + ↓ +dhara(坏块管理 + 磨损均衡算法,Lib/dhara/) + ↓ +nand_ftl.c(本目录,FTL 适配) + ↓ +gd5f2gq5ue.c(本目录,芯片驱动) + ↓ +GD5F2GQ5UE 芯片 +``` + +## ⚠️ 改本驱动前必读陷阱 + +| 陷阱 | 说明 | +|---|---| +| **FatFs 打开模式** | `FA_OPEN_APPEND`(0x30) **不含 `FA_WRITE`(0x02)**——追加写必须 `FA_WRITE\|FA_OPEN_APPEND`,否则 `f_write` 恒返 `FR_DENIED`(7) | +| **FatFs 文件名** | 严格 8.3 短名、**不得以点开头**(`.fschk` 会 `FR_INVALID_NAME`,纯 RAM 判定不碰盘);自愈逻辑**严禁**把名字类错误归入"卷损坏"触发集 | +| **`f_write` 簇分配失败返回 `FR_OK` + 短写** | 判失败必须**校验写回字节数**(无错误码) | +| **禁用 C 库堆分配** | MicroLIB 堆仅 512B,`malloc` 必返回 NULL;用 `pvPortMalloc/vPortFree` | + +> 完整台账见 `docs/问题记录/GD5F2GQ5UE_Trap_Records.md`。 + +## 相关文档 + +- 存储架构:`docs/架构设计/STM32F4-Base存储架构说明.md` +- 测试指南:`docs/测试说明/GD5F2GQ5UE_Test_Guide.md` +- 容量恢复:`docs/测试说明/存储维护与容量恢复.md` diff --git a/Drivers/BSP/NET/README.md b/Drivers/BSP/NET/README.md new file mode 100644 index 00000000..786da781 --- /dev/null +++ b/Drivers/BSP/NET/README.md @@ -0,0 +1,64 @@ +# Drivers/BSP/NET/ — 网络抽象层(BSD Socket API) + +> 在 CH395F 硬件驱动之上提供 **BSD Socket 风格 API**,使上层(FTP 服务、时间同步、UI 推流) +> 以标准 socket 语义编程,无需关心芯片细节。核心是**阻塞模型 + 事件驱动 + 周期对账自愈**。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `net_socket.c/h` | **BSD Socket API 实现**:`net_socket` / `net_connect` / `net_send` / `net_recv` / `net_close` / `net_listen` / `net_accept`,含 L3 挂起(pending)与错误码 | +| `net_select.c/h` | `select`/`poll` 多路复用(基于芯片中断事件 + 周期轮询) | +| `net_types.h` | 网络层公共类型定义 | +| `net_config.h` | 网络层编译期配置(缓冲区大小、超时、对账周期等) | +| `lftpd/` | **轻量 FTP 服务器**(第三方移植,见其子目录) | + +## 核心机制 + +### 阻塞模型(L3 pending) + +- 一期(RECV)已落地:`net_recv` 等支持带超时的阻塞(`pending` 挂起 + tick 唤醒) +- 二期(ACCEPT + SEND)待做 → `docs/待处理内容.md` N-4 + +### 周期对账自愈(Trap 22 修复) + +- `net_reconcile_tick()`(200ms)回读芯片状态修正三类失同步: + 本层 ESTABLISHED 而芯片已断 → 断开;本层 LISTENING 而芯片已握手 → 补 accept; + 本层 LISTENING 而芯片监听消失 → 重建 +- **去抖(连续 2 次)+ 冷却(1s)**——单次状态读的重建动作**必须去抖**, + 否则"刚 listen 未生效"瞬态会反复重建直至 `relisten give up`(三监听口全死) + +### 异常复监听隔离(Trap 23 修复) + +- 异常释放(TIMEOUT)的 socket 复监听前隔离:排空 RX 残渣 + 主动 close + 等 CLOSED +- 400ms 起、800ms 上限强制放行(上限须 < 重试放弃时限 2000ms) +- 仅异常路径生效,正常 FIN 路径零改动 + +### 错误码(E-03 修复) + +- **按任务隔离**:`s_net_errno_slots[8]`(每槽 `{任务句柄, err}`),替代原全局 `s_net_errno` +- `net_get_errno()` 只读本任务槽位,**对外语义不变**(成功不清零) + +## 依赖关系 + +``` +上层(FTP / timeSync / UI 推流) + ↓ BSD Socket API + net_socket.c ←→ net_select.c + ↓ ch395f_* 接口 + Drivers/BSP/CH395F/ +``` + +## ⚠️ 改本模块前必读 + +- 就绪屏障位(`SYS_EVT_NET_READY` 等)等待必须 `osFlagsNoClear`,**不能用默认消费型** +- 每次 CH395F SPI 事务须 `ch395f_spi_begin()/end()` 包裹 +- **改任何自愈/重建逻辑必须去抖**,否则会引发重建风暴 +- 相关陷阱:`docs/问题记录/CH395F_Trap_Records.md` Trap 21/22/23 + +## 相关文档 + +- 上层用法:`docs/网络/BSD_Socket_API_使用指南.md` +- 内部调用关系:`docs/网络/BSD_Socket_API_函数调用关系.md` +- 演进方案:`docs/问题记录/Net层阻塞模型业界对照与演进方案.md` +- 测试:`docs/测试说明/CH395F_Test_Guide.md`、`docs/测试说明/FTP_Test_Guide.md` diff --git a/Drivers/BSP/NET/lftpd/README.md b/Drivers/BSP/NET/lftpd/README.md new file mode 100644 index 00000000..77a7d3bb --- /dev/null +++ b/Drivers/BSP/NET/lftpd/README.md @@ -0,0 +1,41 @@ +# Drivers/BSP/NET/lftpd/ — 轻量 FTP 服务器(第三方移植) + +> ⚠️ **第三方开源库移植**(lftpd,许可证见 [`LICENSE.txt`](LICENSE.txt)),**非自研代码**。 +> 本目录 README 仅说明其在本项目中的**定位与对接方式**;库内部逻辑请参考上游。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `lftpd.c/h` | FTP 服务器主体(命令解析、状态机、数据通道) | +| `lftpd_io.c` | I/O 适配层(**本项目对接 FatFs 的关键所在**) | +| `lftpd_inet.c` | 网络适配(对接本项目的 BSD Socket API) | +| `lftpd_log.c` | 日志输出适配 | +| `lftpd_string.c` | 字符串工具 | +| `private/*.h` | 内部头文件 | +| `LICENSE.txt` | 上游许可证 | + +## 在本项目中的对接 + +``` +ftpTask(App/ 侧创建) + ↓ 等待 SYS_EVT_NET_READY + SYS_EVT_STORAGE_READY(osFlagsNoClear!) +lftpd(本目录) + ├── lftpd_inet.c → Drivers/BSP/NET/net_socket.c(BSD Socket API) + └── lftpd_io.c → Lib/FatFs(文件读写) +``` + +## ⚠️ 项目相关注意 + +- **ftpTask 就绪屏障**:`osEventFlagsWait` 等两位就绪必须加 `osFlagsNoClear`, + 否则位被先到的消费者清掉 → FTP 21 端口静默不监听(无日志无报错) +- **lftpd 大局部缓冲**:已按 `docs/内存管理/RAM使用分析与优化方案.md` §1.4 静态化 9 处 + 大局部缓冲(BSS +4.6KB),使 ftpTask 栈峰值从 3480B 降到 1184B——**勿改回局部变量** +- **上传中止截断**:FTP STOR 中途断开后首笔复连被截断(Trap 23)已在 `net_socket.c` 侧修复 +- 本目录受 pre-commit 的**部分排除**(第三方代码) + +## 相关文档 + +- 测试指南:`docs/测试说明/FTP_Test_Guide.md` +- 台架探针:`MDK-ARM/ftp_abort_probe.py`、`MDK-ARM/ftp_freeze_probe.py` +- 内存优化:`docs/内存管理/RAM使用分析与优化方案.md` §1.4 diff --git a/Drivers/BSP/NETCFG/README.md b/Drivers/BSP/NETCFG/README.md new file mode 100644 index 00000000..dccc01e8 --- /dev/null +++ b/Drivers/BSP/NETCFG/README.md @@ -0,0 +1,36 @@ +# Drivers/BSP/NETCFG/ — 网络配置 + +> 网络参数的**加载 / 保存 / 旧档迁移**(IP、掩码、网关等)。 +> 本模块是**网络配置的持久化层**,与 `App/cfg_file.c`(配置引擎)配合工作。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `net_cfg.c/h` | 网络配置加载(`net_cfg_load`)/ 保存(`net_cfg_save_run`)+ RAM 副本管理 | +| `net_cfg_legacy.c/h` | **旧版配置档迁移**(首启时把旧格式转换为当前格式) | + +## 工作流 + +``` +defaultTask:net_cfg_load(含旧档迁移)→ 置 STORAGE_READY + ↓ (网络配置在屏障前已加载) +netTask:只读 RAM 副本 → net_stack_bring_up(不在 netTask 里读盘) + ↓ +UI 改配置 → SYS_EVT_CFG_SAVE 事件 → defaultTask 执行 net_cfg_save_run + cfg_file_poll + ↓ +netTask 消费 SYS_EVT_NET_RECONFIG → 立即重建网络(新 IP 免重启生效) +``` + +## ⚠️ 约束 + +- **网络配置在 `STORAGE_READY` 屏障之前由 defaultTask 加载完毕**,netTask 只读 RAM 副本 +- UI 保存请求经 `SYS_EVT_CFG_SAVE` 事件交由 **defaultTask**(配置引擎属主)执行, + **netTask/uiTask 不得直接触碰配置引擎**(`cfg_file` 是静态态、单任务收敛) +- 网络代次号(generation)用于各 TCP 服务判断是否需重建监听 + +## 相关文档 + +- `docs/子系统设计/网络配置说明.md` — 网口设置页与即时生效机制 +- `docs/子系统设计/配置文件设计说明.md` — 配置引擎 +- `docs/架构设计/项目启动顺序管理.md` — 就绪屏障 diff --git a/Drivers/BSP/README.md b/Drivers/BSP/README.md new file mode 100644 index 00000000..a75fcc93 --- /dev/null +++ b/Drivers/BSP/README.md @@ -0,0 +1,46 @@ +# Drivers/BSP/ — 板级支持包(纯手工自研代码) + +> **本目录全部为手工编写的板级驱动与中间层**(非 CubeMX 生成、非第三方库、非 ST HAL)。 +> 每个芯片/子模块一个子目录。改驱动前**必读对应模块的 Trap Records**(见下)。 + +## 子模块一览 + +| 目录 | 芯片/模块 | 接口 | 职责 | 关键文档 | +|---|---|---|---|---| +| `CH395F/` | CH395F 以太网控制器 | SPI2 | 以太网 MAC/PHY 控制器底层驱动 | `docs/问题记录/CH395F_Trap_Records.md` | +| `GD5F2GQ5UE/` | GD5F2GQ5UE SPI NAND | SPI1 | NAND 驱动 + FTL(`nand_ftl.c`) | `docs/问题记录/GD5F2GQ5UE_Trap_Records.md` | +| `TPAFE5160/` | TPAFE5160 高精度 ADC | 并行 16 位 | ADC 采样驱动(CONVST/BUSY 时序) | — | +| `SD2506/` | SD2506 RTC | I2C | 实时时钟驱动 | `docs/问题记录/SD2506_Trap_Records.md` | +| `RS485/` | RS-485 半双工 | UART5 | 收发方向控制(DE 引脚)+ 时序 | — | +| `NET/` | BSD Socket 网络抽象层 | — | Socket API + select + 轻量 FTP 服务器 | `docs/网络/`、`docs/问题记录/Net层阻塞模型业界对照与演进方案.md` | +| `NETCFG/` | 网络配置 | — | `/config.ini` 网络段的加载/保存 + 旧档迁移 | `docs/子系统设计/网络配置说明.md` | +| `UI/` | LVGL UI 组件 | — | 菜单/内容页/组件/中文字体 | `docs/UI设计/` | + +## 根级文件 + +| 文件 | 作用 | +|---|---| +| `dbg_log.h` | **调试日志宏**(`DBG_INFO` 等),编译期开关 | +| `dbg_cfg.h` | 调试配置项 | + +## 子模块 README + +- [`NET/README.md`](NET/README.md) — 网络抽象层(Socket / select / FTP) +- [`UI/README.md`](UI/README.md) — LVGL UI 组件 + +## ⚠️ 改驱动前必读(踩坑速查) + +| 模块 | 陷阱 | +|---|---| +| CH395F | SPI 事务须 `ch395f_spi_begin()/end()` 包裹;分频系数**必须为 8**(PCB 约束,勿"优化");快速复连会丢中断致监听死亡(Trap 22 已修);上传中止后首笔复连截断(Trap 23 已修) | +| GD5F2GQ5UE | FatFs 移植版打开模式陷阱(`FA_OPEN_APPEND` 不含写位);文件名严格 8.3 短名、不得以点开头;`f_write` 簇分配失败返 `FR_OK` + 短写,须校验字节数 | +| NET | 就绪屏障位必须 `osFlagsNoClear`;`s_net_errno` 已按任务隔离(勿改回全局) | +| 通用 | 自研代码**禁用 C 库堆分配**(MicroLIB 堆仅 512 B),动态内存只用 `pvPortMalloc/vPortFree` | + +> 完整平台约束见根 `AGENTS.md`「平台约束」章,以及各模块的 Trap Records。 + +## 相关文档 + +- 架构全景:`docs/架构设计/项目架构总览.md` +- 存储栈:`docs/架构设计/STM32F4-Base存储架构说明.md` +- 测试指南:`docs/测试说明/*_Test_Guide.md` diff --git a/Drivers/BSP/RS485/README.md b/Drivers/BSP/RS485/README.md new file mode 100644 index 00000000..e2acb64c --- /dev/null +++ b/Drivers/BSP/RS485/README.md @@ -0,0 +1,26 @@ +# Drivers/BSP/RS485/ — RS-485 半双工通信驱动 + +> RS-485 半双工收发驱动:DE(发送使能)方向控制 + 收发时序管理。 +> 配合 `App/task/rs485_task.c` 与 `App/util/crc.c`、`App/util/ringbuf.c` 组成完整协议栈。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `rs485.c/h` | 驱动初始化、DE 引脚方向切换、收发缓冲管理 | + +## 硬件接口 + +- **UART5**:PC12 TX / PD2 RX / **PD0 DE**(发送使能,低=接收、高=发送) + +## 关键点 + +- **半双工**:发送前拉高 DE 并等待发送完成,发送后立即拉低 DE 切回接收 +- 方向切换时序与波特率相关——切换过快会截断末字节,过慢会阻塞总线 +- 接收经 `ringbuf`(SPSC 无锁环形缓冲)缓冲,供协议层解析 + +## 相关文档 + +- 协议工具:`App/util/crc.c`、`App/util/ringbuf.c` +- 任务实现:`App/task/rs485_task.c` +- 硬件引脚:根 `README.md`「外设接口」 diff --git a/Drivers/BSP/SD2506/README.md b/Drivers/BSP/SD2506/README.md new file mode 100644 index 00000000..db061346 --- /dev/null +++ b/Drivers/BSP/SD2506/README.md @@ -0,0 +1,28 @@ +# Drivers/BSP/SD2506/ — SD2506 RTC 驱动 + +> SD2506 实时时钟芯片驱动(I2C 接口):时间读写、温度、电池状态、诊断。 +> 是 `sys_clock`(墙钟)的**硬件时间基准**。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `sd2506.c/h` | RTC 初始化、时间读写、ID/温度/电池读取、诊断 | + +## 硬件接口 + +- **I2C**(具体引脚见根 `README.md` 与 `Inc/main.h`) + +## 关键点 + +- **时间子系统优先初始化**:`app_main_init` 中最先调用 `sd2506_init` + + `sys_clock_init`,使后续日志都带时间戳 +- 开机执行 **SD2506 诊断**(ID / 时间 / 温度 / 电池),失败触发"时钟芯片异常"自检上报 +- RTC 故障时 `sys_clock_init` **降级到默认时间基准并返回 -1** +- 时间源同步由 `App/time_sync.c`(timeSyncTask)负责 + +## 相关文档 + +- 墙钟维护:`docs/子系统设计/系统墙钟时间维护说明.md` +- 测试指南:`docs/测试说明/SD2506_Test_Guide.md` +- 陷阱台账:`docs/问题记录/SD2506_Trap_Records.md` diff --git a/Drivers/BSP/TPAFE5160/README.md b/Drivers/BSP/TPAFE5160/README.md new file mode 100644 index 00000000..4fa0d445 --- /dev/null +++ b/Drivers/BSP/TPAFE5160/README.md @@ -0,0 +1,32 @@ +# Drivers/BSP/TPAFE5160/ — TPAFE5160 高精度 ADC 驱动 + +> TPAFE5160 是**并行 16 位**接口的高精度 ADC。本目录为寄存器级驱动: +> 转换启动(CONVST)、忙信号(BUSY)、数据读取(RD)时序管理。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `tpafe5160.c/h` | ADC 初始化、转换启动(轮询 + 中断)、16 位并行数据读取 | + +## 硬件接口 + +- **并行 16 位**:PG0–PG15 数据总线 / **PD3 RD**(读选通)/ **PD4 CONVST**(转换启动)/ **PD7 BUSY**(转换中) +- 部分引脚为 GPIO 模拟时序(非硬件 SPI/FSMC) + +## 关键点 + +- **首次转换在 `app_main_init` 末尾由 `tpafe5160_start_conv_irq` 启动**(中断驱动) +- 采样数据由 `App/task/adc_task.c` 消费处理 +- CONVST→BUSY→RD 三段时序对**建立/保持时间敏感**,改动需对照芯片手册 +- ⚠️ 本项目 ADC 相关功能**新增任务/缓冲前须核算 RAM**(见 `docs/内存管理/`) + +## 已知问题 + +- `docs/问题记录/TPAFE5160.md` 有 **16 张图片断链**(文档引用了但图从未入库)——已登记,暂缓处理 + +## 相关文档 + +- 芯片手册转录:`docs/芯片手册/TPAFE5160.md`(注:其配图有断链) +- 任务实现:`App/task/adc_task.c` +- 硬件引脚:根 `README.md`「外设接口」 diff --git a/Drivers/BSP/UI/README.md b/Drivers/BSP/UI/README.md new file mode 100644 index 00000000..79792d21 --- /dev/null +++ b/Drivers/BSP/UI/README.md @@ -0,0 +1,57 @@ +# Drivers/BSP/UI/ — LVGL UI 组件 + +> 基于 LVGL 的界面实现:菜单树、内容页、通用组件、中文字库、待机页。 +> **与 PC 模拟器共用同一套 UI 源码**(`simulator/` 只提供平台层)。 + +## 结构 + +### 核心 / 框架 + +| 文件 | 作用 | +|---|---| +| `ui_port.c/h` | **LVGL 移植层**:显示驱动、输入设备、tick 注册 | +| `ui_menu.c/h` | 菜单框架(树结构与导航) | +| `ui_menu_view.c/h` | 菜单视图渲染 | +| `ui_menu_tab.c/h` | 页签组件 | +| `ui_deco.c/h` | 界面装饰元素(图标、边框等) | +| `ui_standby.c/h` | 待机页 | +| `ui_pwd_def.h` | 密码页默认值定义 | +| `ui_font_cn_12.c` | **中文字库**(由 `tools/font_gen/` 生成,勿手改) | + +### 内容页 + +| 文件 | 作用 | +|---|---| +| `ui_content_page.c/h` | 内容页框架 | +| `ui_page_ac.c/h` | 交流量页 | +| `ui_page_dc.c/h` | 直流量页 | +| `ui_page_device_info.c/h` | 设备信息页 | +| `ui_page_net_cfg.c/h` | 网口设置页 | +| `ui_page_password.c/h` | 密码页 | +| `ui_page_runlog.c/h` | 运行日志页 | +| `ui_page_selftest.c/h` | 自检页 | + +### 数据汇入(推流) + +| 文件 | 作用 | +|---|---| +| `ui_net_sink.c/h` | 远端显示总线(RemoDispBus)数据汇入口 | +| `ui_net_sink_backend.h` | 后端抽象接口(MCU / 模拟器分别实现) | +| `ui_net_sink_backend_mcu.c` | MCU 端后端实现 | + +## ⚠️ 编码注意(本目录含中文字符串) + +- 本目录文件**带 UTF-8 BOM**(`.c` 内含中文字符串字面量,BOM 使 ARMCC 按 UTF-8 解码) +- **Edit 工具会剥掉 BOM**:改完必须核对并按原样补回 3 字节 `EF BB BF`, + 否则 ARMCC 改按 CP936 解读 → `#870-D: invalid multibyte character sequence` +- UI 改动一律走 **`ui-verify` skill 五步门禁** +- 含新汉字的文案提交前先跑 **`font-regen` skill** 重生成 `ui_font_cn_12.c` + +## 相关文档 + +- UI 架构:`docs/UI设计/UI_设计架构.md` +- 菜单设计:`docs/UI设计/菜单页面设计.md`、`docs/UI设计/内容页架构.md` +- 字体:`docs/UI设计/UI_中文字体生成与配置.md` +- 模拟器:`docs/UI设计/LVGL模拟器部署与使用说明.md` +- 自动化测试:`docs/UI设计/UI_自动化测试流程.md` +- 协议:`docs/UI设计/RemoDispBus协议与接收设计说明.md` diff --git a/Inc/README.md b/Inc/README.md new file mode 100644 index 00000000..488b821b --- /dev/null +++ b/Inc/README.md @@ -0,0 +1,33 @@ +# Inc/ — CubeMX 生成的头文件 + +> ⚠️ **本目录文件由 STM32CubeMX 生成**(`.ioc` 重生成会覆盖),**不是自研代码**。 +> 允许在 `USER CODE BEGIN/END` 标记区之间写自定义内容。 + +## 文件一览 + +| 文件 | 生成 | 作用 | +|---|---|---| +| `main.h` | CubeMX | 主头文件:引脚宏定义(`xxx_Pin` / `xxx_GPIO_Port`) | +| `FreeRTOSConfig.h` | CubeMX | **FreeRTOS 内核配置**(堆大小、tick、优先级位数等) | +| `stm32f4xx_hal_conf.h` | CubeMX | HAL 模块裁剪开关(启用/禁用各外设 HAL 模块) | +| `stm32f4xx_it.h` | CubeMX | 中断服务函数声明 | +| `gpio.h` / `dma.h` / `spi.h` / `i2c.h` / `usart.h` | CubeMX | 各外设初始化函数声明 | + +## ⚠️ 修改约定 + +- 自定义内容只写 `USER CODE BEGIN xxx` / `USER CODE END xxx` 标记区之间 +- 引脚宏(如 `CH395F_CS_Pin`)在 `main.h` 中定义,**改引脚须在 CubeMX 中改后重新生成** + +## 关键配置速查 + +| 配置 | 值 | 位置 | +|---|---|---| +| FreeRTOS 堆 | `configTOTAL_HEAP_SIZE`(已迁 CCM) | `FreeRTOSConfig.h` | +| 栈溢出检查 | `configCHECK_FOR_STACK_OVERFLOW = 2` | `FreeRTOSConfig.h` | +| HAL 时基 | TIM7(`HAL_TIMEBASE` 覆盖) | `stm32f4xx_hal_conf.h` + `Src/` | +| NVIC 分组 | 4 位优先级 | CubeMX 配置 | + +## 相关文档 + +- 内存/堆预算:`docs/内存管理/RAM使用分析与优化方案.md` +- 硬件引脚:根 `README.md`「外设接口」表 diff --git a/MDK-ARM/README.md b/MDK-ARM/README.md new file mode 100644 index 00000000..9d7bae30 --- /dev/null +++ b/MDK-ARM/README.md @@ -0,0 +1,69 @@ +# MDK-ARM/ — Keil MDK-ARM v5 工程与构建/烧录/探针脚本 + +> **唯一工具链**:Keil MDK-ARM v5(ARMCC,C99)。本目录含工程文件、启动文件、 +> 命令行构建/烧录脚本,以及**台架探针与判读脚本**。 + +## 关键文件 + +| 文件/目录 | 作用 | +|---|---| +| `STM32F407-Demo.uvprojx` | **Keil 工程文件**(源文件清单、编译选项、目标配置) | +| `STM32F407-Demo.uvoptx` | Keil 用户选项(调试器、断点等) | +| `startup_stm32f407xx.s` | 启动文件(**`Heap_Size EQU 0x200`(512B)在此限定**) | +| `build.bat` | **`@build` 命令行编译**(退出码 0=0 错 0 警;日志 `build_log.txt`) | +| `download.bat` | 烧录(UV4 路径) | +| `reset.bat` | **复位/烧录**(`ST-LINK_CLI`,见下) | + +## 构建与烧录 + +```bash +# 编译(相对路径,勿用绝对路径) +& "MDK-ARM\build.bat" # 退出码 0 = 0 errors, 0 warnings + +# 烧录 + 复位运行(推荐路径) +& "MDK-ARM\reset.bat" flash <文件.hex|.bin> + +# 仅复位 +& "MDK-ARM\reset.bat" +``` + +### ⚠️ 烧录铁律 + +- `reset.bat flash` = `ST-LINK_CLI -c SWD -P <文件> -Rst -Run`——**`-Rst -Run` 不可省略**! + 裸 `-P` 会报 `Programming Complete`,但目标核处于异常状态时写入并不落地(芯片内容不变) +- 烧录后**必须回读校验**:`ST-LINK_CLI -c SWD -CmpFile <文件> 0x08000000`(`No difference found` 才算真写入) +- 本机 3 线接线(nRST 未接),**只重启不烧录**用 `reset.bat` 无参 + +## 台架探针与判读脚本 + +| 脚本 | 作用 | +|---|---| +| `bench_verdict.py` | 台架判读(把运行结果判为 PASS/FAIL) | +| `ftp_freeze_probe.py` | FTP 上传+回读哈希(真实路径冻结探针) | +| `ftp_abort_probe.py` | FTP 中止场景探针(Trap 23) | +| `ftp_retr_abort_probe.py` | FTP RETR 中止探针 | +| `tcp_reconnect_probe.py` | TCP 快速复连探针(Trap 22) | +| `audit_runs.py` / `audit_tcpclient.py` | 运行记录审计 / TCP 客户端审计 | +| `check_crecipe_content.py` | 检查创建配方内容 | + +## 子目录 + +| 目录 | 内容 | +|---|---| +| `RTE/` | Keil Run-Time Environment 配置 | +| `DebugConfig/` | 调试会话配置 | +| `STM32F407-Demo/` | 构建输出(`.o`/`.axf`/`.map` 等,**产物不提交**) | +| `bench_diag/` | 台架诊断数据 | +| `retracted_bench_20260922/` | 已撤回的台架数据(存证) | + +## ⚠️ 注意 + +- `build.bat` **硬编码本机 Keil 路径** `C:\Keil_v5\UV4\UV4.exe`(换机需改) +- 本目录被 pre-commit 门禁**排除** +- 启动文件的 `Heap_Size = 512B` 是**自研代码禁用 `malloc` 的根因**(见 `AGENTS.md`) + +## 相关文档 + +- 烧录/复位:`docs/测试说明/ST-LINK_CLI_复位使用说明.md` +- 构建与验证:根 `AGENTS.md`「构建与验证」章 +- 测试流程:`docs/测试说明/自动化测试流程.md` diff --git a/README.md b/README.md index d45060e7..447bfc5c 100644 --- a/README.md +++ b/README.md @@ -93,6 +93,9 @@ main.c ## 目录结构 +> **每个自建代码目录都有 `README.md`**(说明目录职责、文件清单与改前须知)—— +> 下表是全局地图,各目录 README 是局部细节。约定见 [`docs/文档规范.md`](docs/文档规范.md) §1.1b。 + ``` STM32F4-Base/ ├── Src/ # CubeMX 生成的源文件(USER CODE 区域可编辑) diff --git a/Src/README.md b/Src/README.md new file mode 100644 index 00000000..dda5f72a --- /dev/null +++ b/Src/README.md @@ -0,0 +1,35 @@ +# Src/ — CubeMX 生成的源文件 + +> ⚠️ **本目录文件由 STM32CubeMX 生成**(`.ioc` 重生成会覆盖),**不是自研代码**。 +> 但允许在 `USER CODE BEGIN/END` 标记区之间写自定义代码。 + +## 文件一览 + +| 文件 | 生成 | 作用 | +|---|---|---| +| `main.c` | CubeMX | 程序入口:`HAL_Init` → `SystemClock_Config` → 外设初始化 → `app_main_init` → `osKernelStart` | +| `freertos.c` | CubeMX | **FreeRTOS 任务创建**(`MX_FREERTOS_Init`)+ 任务栈/优先级定义 | +| `gpio.c` / `dma.c` / `spi.c` / `i2c.c` / `usart.c` | CubeMX | 各外设 `MX_xxx_Init` | +| `stm32f4xx_hal_msp.c` | CubeMX | HAL 外设底层初始化(时钟使能、NVIC、引脚复用) | +| `stm32f4xx_hal_timebase_tim.c` | 自研覆盖 | **HAL 时基改用 TIM7**(非 SysTick),tick = 1ms | +| `stm32f4xx_it.c` | CubeMX | 中断服务函数(ISR) | +| `system_stm32f4xx.c` | CMSIS | 系统时钟初始化(`SystemInit`) | + +## ⚠️ 修改约定(铁律) + +- **自定义代码只写 `USER CODE BEGIN xxx` / `USER CODE END xxx` 标记区之间**—— + 标记区外的内容在 CubeMX 重新生成时会被**无条件覆盖丢失** +- 本目录被 pre-commit 的 C 代码规范检查**排除**(因是生成代码,风格不受控) +- `Drivers/BSP/` 才是纯手工代码区;应用逻辑放 `App/` + +## 关键点 + +- **HAL 时基 = TIM7**,不是 SysTick;FreeRTOS 用 SysTick 之外的方式,tick = 1ms +- NVIC 4 位优先级分组;**外设中断优先级 ≥ 5**(0~4 预留给 FreeRTOS) +- 时钟:HSE 8MHz → PLL M=4/N=168/P=2 → 168MHz + +## 相关文档 + +- 架构全景:`docs/架构设计/项目架构总览.md` +- 启动顺序:`docs/架构设计/项目启动顺序管理.md` +- 任务表(唯一事实源 = `freertos.c`):根 `README.md` diff --git a/docs/文档规范.md b/docs/文档规范.md index 5c0ef720..2d4d0199 100644 --- a/docs/文档规范.md +++ b/docs/文档规范.md @@ -16,6 +16,23 @@ | **按领域归入子目录** | 顶层不放散落 `.md`;新领域先建无空格子目录,再在 [`README.md`](README.md) 登记 | | 现有目录 | `架构设计/` `子系统设计/` `网络/` `测试说明/` `代码规范/` `内存管理/` `问题记录/` `审查记录/` `环境与部署/` `UI设计/` `硬件平台/` `芯片手册/` `images/` | +### 1.1b 代码目录的 README.md + +**每个自建代码目录**(非第三方库、非 HAL/CMSIS 生成)**必须有一份 `README.md`**, +说明该目录的职责、文件清单与关键约束,让新接手者不必读遍代码即可建立认知。 + +| 规则 | 说明 | +|---|---| +| **覆盖范围** | `App/`(含 `log/` `task/` `util/`)、`Drivers/BSP/`(含各芯片子目录)、`Src/`、`Inc/`、`scripts/`、`tools/`(含各子工具)、`test/`、`MDK-ARM/`、`simulator/`(含 `sim/` `tests/`)、`docs/` | +| **排除** | 第三方库与生成代码:`Drivers/CMSIS/`、`Drivers/STM32F4xx_HAL_Driver/`、`Middlewares/Third_Party/`、`Lib/`(FatFs/dhara/lvgl)、`simulator/SDL2/`、构建产物目录 | +| **必备内容** | ① 一句话定位 + 是否自研 ② 文件/子目录清单表(每个一句话作用)③ 关键约束或陷阱(改前须知)④ 指向 `docs/` 权威文档的链接 | +| **命名** | 一律 `README.md`(大写),放该目录根部 | +| **链接** | 目录间互链用**同级相对路径**(如 `../NET/README.md`);指向 `docs/` 用**仓库根相对路径** | +| **门禁** | README 内所有链接受 `doc-links` 钩子检查;新增/改名目录或文件后须同步更新对应 README | + +> 目的:**目录即文档的入口**。根 `README.md` 给全局地图,各目录 `README.md` 给局部细节, +> 二者构成"地图 + 地标"的导航体系(避免所有信息堆在单一 README)。 + ### 1.2 文件名 | 规则 | 说明 | diff --git a/scripts/README.md b/scripts/README.md new file mode 100644 index 00000000..f875ead3 --- /dev/null +++ b/scripts/README.md @@ -0,0 +1,51 @@ +# scripts/ — 开发脚本(提交门禁 + 报告生成) + +> 本目录是 **pre-commit 门禁脚本**与**报告生成脚本**的存放处。 +> 与 `tools/`(面向开发者的功能工具)区别:本目录服务于**质量门禁与工程度量**。 + +## 文件一览 + +### 提交门禁(接入 `.pre-commit-config.yaml`) + +| 脚本 | 钩子名 | 作用 | +|---|---|---| +| `check_coding_standard.py` | `C coding standard` | C 代码规范机械检查(命名前缀/常量右置/头文件保护宏等) | +| `check_mojibake.py` | `Forbid U+FFFD mojibake` | 扫描 `U+FFFD` 乱码(`EF BF BD` 字节) | +| `check_doc_links.py` | `doc-links` | **文档链接存在性** + 命名规范(D-3/D-7) | +| `gen_task_table.py` | `task-table` | FreeRTOS 任务表以 `Src/freertos.c` 为**唯一事实源**生成/校验(D-2/D-7) | +| `check_mem_numbers.py` | `mem-numbers` | 内存/Flash 数字以 `.map` 为唯一事实源校验(D-7 体积档) | + +### 报告生成(非门禁) + +| 脚本 | 作用 | +|---|---| +| `ram_report.py` | 从 `.map` 生成**静态 RAM/Flash 占用**报告(→ `docs/内存管理/data/`) | +| `stack_report.py` | 从 Keil 静态调用图 + 串口 `[STACK]` 水位生成**每任务最坏链**报告 | + +## 使用方式 + +```bash +# 全库跑门禁 +& 'C:\ProgramData\anaconda3\python.exe' -m pre_commit run --all-files + +# 单个脚本 +& '.venv\Scripts\python.exe' scripts/check_doc_links.py --all +& '.venv\Scripts\python.exe' scripts/gen_task_table.py --check # 或 --write / --diff +& '.venv\Scripts\python.exe' scripts/check_mem_numbers.py --check +& '.venv\Scripts\python.exe' scripts/ram_report.py +& '.venv\Scripts\python.exe' scripts/stack_report.py -s tools\serial_tool\state\serial.log +``` + +## ⚠️ 脚本编写约定 + +- **保真回写**:改文件前先探测原换行符(LF/CRLF)与 BOM,按原样回写(本仓库各文件换行混杂) +- **受管区锚点**:改文档中的数值/表格时用 `` 锚点,只替换锚点内内容 +- 脚本**输出文件绝不能落在自身扫描范围内**(否则会"自我污染",见 `docs-tree-reorg` skill) +- 生成器与校验器**共用同一套正则/口径**,避免两处数字打架 + +## 相关文档 + +- `docs/代码规范/pre-commit使用说明.md` — 门禁完整说明与排除项 +- `docs/代码规范/cppcheck使用说明.md` +- `docs/文档规范.md` — 文档门禁三档 +- `docs/内存管理/RAM使用分析与优化方案.md` — RAM/栈报告口径 diff --git a/simulator/sim/README.md b/simulator/sim/README.md new file mode 100644 index 00000000..ead35d35 --- /dev/null +++ b/simulator/sim/README.md @@ -0,0 +1,36 @@ +# simulator/sim/ — 模拟器平台层 + +> PC 端 LVGL 模拟器的**平台适配层**:把 MCU 侧的硬件/RTOS 接口替换成 PC 实现, +> 使 **UI 源码(`Drivers/BSP/UI/`)与固件共用同一套代码**。 + +## 文件一览 + +| 文件 | 替换的 MCU 侧实现 | 作用 | +|---|---|---| +| `sim_port.c/h` | `ui_port.c` | **显示/输入移植层**:SDL 窗口 → LVGL 显示驱动 + 键鼠/触摸输入 | +| `net_socket_sim.c` | `net_socket.c` | 网络 Socket 的 PC 实现(宿主 BSD socket) | +| `cfg_file_store_sim.c` | `cfg_file_store_mcu.c` | 配置存储的 PC 后端(宿主堆) | +| `sim_syslog.c` | `sys_log_mcu.c` | 日志的 PC 实现(写文件而非 NAND) | +| `ui_net_sink_backend_sim.c` | `ui_net_sink_backend_mcu.c` | 推流后端的 PC 实现 | +| `sim_latency_stub.c` | — | 时延打桩(模拟链路延迟,供测试) | + +## 设计模式 + +MCU 与模拟器**共用核心逻辑,仅后端不同**: + +``` + 共享核心(无分配符号) + ├── cfg_file.c(配置引擎) + └── ui_*(LVGL UI) + ↓ 后端抽象接口 + ┌─────────┴─────────┐ +MCU 后端(本工程 *_mcu.c) PC 后端(本目录 *_sim.c) +``` + +> 配置引擎后端:MCU = FreeRTOS 堆、模拟器 = 宿主堆,**共享核心零分配符号**。 + +## 相关文档 + +- 模拟器总说明:`../README.md` +- UI 架构与移植要点:`docs/UI设计/UI_设计架构.md` +- 模拟器部署:`docs/UI设计/LVGL模拟器部署与使用说明.md` diff --git a/simulator/tests/README.md b/simulator/tests/README.md new file mode 100644 index 00000000..b49739fd --- /dev/null +++ b/simulator/tests/README.md @@ -0,0 +1,36 @@ +# simulator/tests/ — UI 模拟器无头回归测试 + +> PC 端**无头**(headless)UI 像素回归测试:在模拟器中渲染各页面,与**黄金参考图**比对, +> 检测 UI 改动是否引入像素级回归。属于 `ui-verify` skill 五步门禁的一部分。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `check_menu_rows.py` | **菜单像素回归**:渲染菜单行 → 与黄金参考比对 | +| `check_content_pages.py` | **内容页回归**:各内容页渲染比对 | +| `check_remo_sink.py` | **推流(RemoDispBus)回归**:接收端渲染比对 | +| `regen_ref_png.py` | **重建黄金参考**:UI 有意变更后,重新生成基准图 | +| `ref/` | 黄金参考图(基准 PNG) | + +## 使用方式 + +```bash +# 跑回归(按 ui-verify skill 流程) +& '.venv\Scripts\python.exe' simulator/tests/check_menu_rows.py +& '.venv\Scripts\python.exe' simulator/tests/check_content_pages.py + +# UI 有意变更、确认无误后重建基准 +& '.venv\Scripts\python.exe' simulator/tests/regen_ref_png.py +``` + +## ⚠️ 注意 + +- **重建黄金参考前必须确认变更是有意的**——否则会把 bug 固化成"基准" +- UI 改动一律走 **`ui-verify` skill 五步门禁**(regression 是其中一步) +- 依赖模拟器已构建(`simulator/build_sim.bat`) + +## 相关文档 + +- `docs/UI设计/UI_自动化测试流程.md` — ui-verify 五步门禁 +- `docs/UI设计/LVGL模拟器部署与使用说明.md` diff --git a/test/README.md b/test/README.md new file mode 100644 index 00000000..ebf77fbc --- /dev/null +++ b/test/README.md @@ -0,0 +1,54 @@ +# test/ — 测试代码与主机端脚本 + +> 测试分两部分:**板端测试套件**(`.c/.h`,编入固件由 testTask 执行)与 +> **主机端脚本**(`.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` | 时间同步推送服务 | + +## 运行方式 + +```bash +# @test 一键闭环(推荐) +& '.venv\Scripts\python.exe' test/run_boot_test.py + +# 单独校验日志 +& '.venv\Scripts\python.exe' test/verify_log.py <日志文件> +``` + +退出码约定:`0`=PASS / `1`=FAIL / `2`=采集或烧录错误 / `3`=用法或预检错误。 + +## ⚠️ 注意 + +- 本目录**被 pre-commit 门禁排除**(测试代码不受 C 规范约束) +- 板端套件占用 RAM,启用前先核算预算(见 `docs/内存管理/`) +- 测试缓冲用**分 Phase 复用静态缓冲**(避免 `L6406E` 溢出) + +## 相关文档 + +- `docs/测试说明/测试开发标准流程.md` — L0~L3 分层与门禁决策表 +- `docs/测试说明/自动化测试流程.md` — `@test` 细节与失败模式 +- 各模块测试指南:`docs/测试说明/*_Test_Guide.md` +- `docs/测试说明/链路延迟测试说明.md` diff --git a/tools/README.md b/tools/README.md new file mode 100644 index 00000000..6dab651c --- /dev/null +++ b/tools/README.md @@ -0,0 +1,44 @@ +# tools/ — 开发工具 + +> 面向开发者的**功能性工具**(生成器 / 转换器 / 交互工具)。 +> 与 `scripts/`(质量门禁与度量)分工不同:本目录产出**资产**(图、字体、代码、知识库)。 + +## 工具一览 + +| 目录 | 工具 | 产物 | 文档 | +|---|---|---|---| +| `arch_diagram/` | 架构图 SVG 生成器 | `docs/images/*.svg` | `docs/架构设计/图形绘制流程.md` | +| `font_gen/` | 中文字库生成 | `Drivers/BSP/UI/ui_font_cn_12.c` | `docs/UI设计/UI_中文字体生成与配置.md` | +| `menu_gen/` | 菜单树代码生成 | UI 菜单代码 | `docs/UI设计/菜单页面设计.md` | +| `netlist_semantics/` | 网表语义分析 | 引脚知识库 JSON + 网表报告 | `docs/硬件平台/` | +| `refgraph/` | 文件引用关系图 | `docs/images/引用关系图.*` | `docs/架构设计/引用关系图说明.md` | +| `serial_tool/` | Python 串口助手 | 日志状态(`state/`) | `docs/测试说明/串口助手使用指南.md` | + +## 使用方式 + +```bash +# 架构图(精确布局) +& '.venv\Scripts\python.exe' tools/arch_diagram/gen_memory_svg.py + +# 中文字体(含新汉字文案后必须重跑) +& '.venv\Scripts\python.exe' tools/font_gen/make_font.py + +# 引用关系图 +& 'tools\refgraph\gen_refgraph.bat' + +# 串口助手(常驻 daemon) +& '.venv\Scripts\python.exe' tools/serial_tool/serial_tool.py +``` + +## ⚠️ 约定 + +- **生成器的产物与脚本一并提交**(如 SVG);本地预览产物(如 PNG)不提交 +- 图表选型:精确布局图用 `arch_diagram/` 生成器;拓扑图(流程/时序/状态机)用 Mermaid; + **勿手绘 ASCII 框图**(见 `docs/架构设计/图形绘制流程.md`) +- 涉及 UI 改动:走 `ui-verify` skill 五步门禁;涉及字体:走 `font-regen` skill + +## 相关文档 + +- `docs/架构设计/图形绘制流程.md` — 配图规范与选型 +- `docs/架构设计/引用关系图说明.md` +- `docs/测试说明/串口助手使用指南.md`、`docs/测试说明/串口助手设计说明.md` diff --git a/tools/arch_diagram/README.md b/tools/arch_diagram/README.md new file mode 100644 index 00000000..da9f7993 --- /dev/null +++ b/tools/arch_diagram/README.md @@ -0,0 +1,35 @@ +# tools/arch_diagram/ — 架构图 SVG 生成器 + +> 用 Python 脚本**精确生成**架构类 SVG 图(分层、内存布局、协议帧、屏障等), +> 产物放 `docs/images/`。用于"必须精确布局"的图;拓扑图(流程/时序/状态机)改用 Mermaid。 + +## 脚本一览 + +| 脚本 | 产物 | 用途 | +|---|---|---| +| `gen_arch_svg.py` | 架构分层图 | 六层分层结构 | +| `gen_memory_svg.py` | 内存布局图 | RAM / Flash 分区 | +| `gen_storage_stack_svg.py` | 存储栈图 | FTL / dhara / FatFs 三层栈 | +| `gen_net_stack_svg.py` | 网络栈图 | BSD 网络栈分层 | +| `gen_barrier_svg.py` | 就绪屏障图 | Event Flags 屏障模型 | +| `gen_frame_svg.py` | 协议帧格式图 | RemoDispBus 帧结构 | +| `gen_cfg_arch_svg.py` | 配置引擎架构图 | 配置分层与持久化 | +| `gen_partition_svg.py` | 分区图 | 存储分区 | + +## 使用方式 + +```bash +& '.venv\Scripts\python.exe' tools/arch_diagram/gen_memory_svg.py +``` + +产物统一输出到 `docs/images/`;**脚本与生成的 `.svg` 一并提交**。 + +## ⚠️ 约定 + +- 颜色/字体遵循 `docs/架构设计/图形绘制流程.md` 的规范 +- 中文用 SVG `` 直接写(需注意字体族声明) +- 改图**改脚本再重跑**,不手改 SVG(保证可复现) + +## 相关文档 + +- `docs/架构设计/图形绘制流程.md` — 配图规范、选型与检查清单 diff --git a/tools/font_gen/README.md b/tools/font_gen/README.md new file mode 100644 index 00000000..b4231720 --- /dev/null +++ b/tools/font_gen/README.md @@ -0,0 +1,30 @@ +# tools/font_gen/ — 中文字库生成 + +> 从**字符集清单**生成 LVGL 用的中文字库 C 文件(子集化,只嵌入用到的汉字以节省 Flash)。 + +## 脚本一览 + +| 脚本 | 作用 | +|---|---| +| `extract_cn.py` | **提取汉字**:扫描 UI 源码的字符串字面量,输出字符集清单 `ui_cn_chars.txt` | +| `make_font.py` | **生成字库**:按字符集从 TTF 生成 `Drivers/BSP/UI/ui_font_cn_12.c` | + +## 使用方式 + +```bash +# 新增含汉字的 UI 文案后:先提取字符集,再生成字库 +& '.venv\Scripts\python.exe' tools/font_gen/extract_cn.py +& '.venv\Scripts\python.exe' tools/font_gen/make_font.py +``` + +## ⚠️ 注意 + +- **含新汉字的 UI 文案提交前必须重跑**(走 `font-regen` skill)——否则新字显示为空白/方块 +- 产物 `ui_font_cn_12.c` **带 UTF-8 BOM**,勿手改(由脚本生成) +- 字库大小直接影响 Flash 占用,只嵌入实际使用的字符 +- 依赖 `fontTools` / `Pillow`(已装在 `.venv`) + +## 相关文档 + +- `docs/UI设计/UI_中文字体生成与配置.md` +- `docs/UI设计/UI_设计架构.md` diff --git a/tools/menu_gen/README.md b/tools/menu_gen/README.md new file mode 100644 index 00000000..a98a5182 --- /dev/null +++ b/tools/menu_gen/README.md @@ -0,0 +1,28 @@ +# tools/menu_gen/ — 菜单代码生成 + +> 从**菜单树定义**生成 UI 菜单的 C 代码,保证菜单结构与页面注册一致、避免手写遗漏。 + +## 脚本一览 + +| 脚本 | 作用 | +|---|---| +| `gen_menu.py` | 读取菜单树定义(见 `ui_menu_tree.txt`)→ 生成菜单代码 | + +## 使用方式 + +```bash +& '.venv\Scripts\python.exe' tools/menu_gen/gen_menu.py +``` + +菜单树输入的权威副本:仓库根 `ui_menu_tree.txt`。 + +## ⚠️ 注意 + +- 生成产物**勿手改**(会被下次生成覆盖);要改菜单结构改**定义源**后重跑 +- 中文字符串字面量须为**纯 ASCII 安全**(见 `AGENTS.md` 编码铁律)——生成后的文案 + 如需汉字,须配套重跑字体生成(`tools/font_gen/`) + +## 相关文档 + +- `docs/UI设计/菜单页面设计.md` +- `docs/UI设计/内容页架构.md` diff --git a/tools/netlist_semantics/README.md b/tools/netlist_semantics/README.md new file mode 100644 index 00000000..b2ce3c72 --- /dev/null +++ b/tools/netlist_semantics/README.md @@ -0,0 +1,29 @@ +# tools/netlist_semantics/ — 网表语义分析 + +> 把电路**网表文件**(`.tel`)解析成"有语义的引脚知识库",供生成引脚表与网表分析报告。 + +## 脚本一览 + +| 脚本 | 作用 | +|---|---| +| `netlist_sem.py` | 网表解析核心(把 `.tel` 网表 → 结构化的网络/引脚连接) | +| `gen_kb.py` | 生成**引脚知识库** `pinout_kb.json` | +| `pinout_kb.json` | 引脚知识库产物(MCU 引脚 ↔ 网络 ↔ 外设的映射) | + +## 使用方式 + +```bash +& '.venv\Scripts\python.exe' tools/netlist_semantics/netlist_sem.py <网表.tel> +& '.venv\Scripts\python.exe' tools/netlist_semantics/gen_kb.py +``` + +## 输入 / 产物 + +- **输入**:硬件网表 `.tel`(位于 `docs/硬件平台/`,如 `V0.0.tel`、`V0.1.tel`) +- **产物**:`pinout_kb.json` + `docs/硬件平台/V0.0_网表详细分析报告.md`、`docs/硬件平台/V0.0_网表语义图.md` + +## 相关文档 + +- `docs/硬件平台/V0.0_网表详细分析报告.md` +- `docs/硬件平台/V0.0_网表语义图.md` +- 硬件引脚表:根 `README.md`「外设接口」 diff --git a/tools/refgraph/README.md b/tools/refgraph/README.md new file mode 100644 index 00000000..a9b904a2 --- /dev/null +++ b/tools/refgraph/README.md @@ -0,0 +1,35 @@ +# tools/refgraph/ — 文件引用关系图 + +> 扫描全仓库 `.c/.h` 的 `#include` 关系,生成**文件级 + 模块级引用关系图**(Graphviz)。 + +## 文件一览 + +| 文件 | 作用 | +|---|---| +| `gen_refgraph.bat` | 一键入口(调用 `gen_refgraph.py` + Graphviz 渲染) | +| `gen_refgraph.py` | 扫描 `#include` → 生成 `.dot` → 渲染 `.svg` / `.json` | + +## 使用方式 + +```bash +& 'tools\refgraph\gen_refgraph.bat' +``` + +## 产物(放 `docs/images/`) + +| 产物 | 内容 | +|---|---| +| `引用关系图.dot` | Graphviz 源 | +| `引用关系图.svg` / `.png` | 渲染图(`.svg` 提交,`.png` 本地预览不提交) | +| `引用关系图.json` | 结构化引用数据 | + +## ⚠️ 注意 + +- **项目文件变化后重跑**更新(新增/删除源文件、改 include 关系) +- 渲染依赖 **Graphviz**(`winget install graphviz` 可装) +- 脚本与 `.dot`/`.svg`/`.json` **一并提交** + +## 相关文档 + +- `docs/架构设计/引用关系图说明.md` +- `docs/架构设计/项目架构总览.md` diff --git a/tools/serial_tool/README.md b/tools/serial_tool/README.md new file mode 100644 index 00000000..dde2c732 --- /dev/null +++ b/tools/serial_tool/README.md @@ -0,0 +1,41 @@ +# tools/serial_tool/ — Python 串口助手 + +> **常驻 daemon + CLI** 架构的串口工具:后台持续收串口日志,CLI 按需查询/发送, +> 避免反复开关串口导致日志丢失(台架与测试的主力观测工具)。 + +## 文件一览 + +| 文件/目录 | 作用 | +|---|---| +| `serial_tool.py` | 串口助手主程序(daemon 与 CLI 合一) | +| `state/` | **运行时状态目录** | +| `state/serial.log` | 串口原始日志(`stack_report.py -s` 的输入之一) | +| `state/daemon.log` | daemon 自身运行日志 | +| `state/meta.json` | daemon 元数据(端口、状态等) | + +## 使用方式 + +```bash +# 启动 daemon / 打开串口 +& '.venv\Scripts\python.exe' tools/serial_tool/serial_tool.py open COM6 + +# 查询日志 / 发送命令 +& '.venv\Scripts\python.exe' tools/serial_tool/serial_tool.py tail +& '.venv\Scripts\python.exe' tools/serial_tool/serial_tool.py send "<命令>" + +# 关闭 +& '.venv\Scripts\python.exe' tools/serial_tool/serial_tool.py close +``` + +> 具体子命令以 `--help` 为准。 + +## ⚠️ 注意 + +- **单写者**:串口同一时刻只能被一个进程占用——别同时用本工具和其它串口程序 +- `state/serial.log` 是 `[STACK]` 运行时水位的来源,`scripts/stack_report.py -s` 直接读它 +- `state/` 是运行时数据,**不入库** + +## 相关文档 + +- `docs/测试说明/串口助手使用指南.md` — 命令用法 / 工作流 / 排障 +- `docs/测试说明/串口助手设计说明.md` — 契约 / daemon 行为 / 陷阱