就绪屏障与配置引擎重构,新增串口助手、V0.0网表分析报告及芯片手册,同步更新文档
This commit is contained in:
@@ -1,185 +1,99 @@
|
||||
# STM32F4-Base
|
||||
|
||||
> **编译验证:所有代码修改后必须执行 `@build` 验证编译通过(0 错误 0 警告),否则不要提交。**
|
||||
STM32F407ZGTx @168MHz(HSE 8MHz → PLL M=4/N=168/P=2);**仅 Keil MDK-ARM v5 (ARMCC, C99) 工具链**;FreeRTOS V10.3.1 / CMSIS-RTOS2;192KB SRAM / 1MB Flash。
|
||||
|
||||
## 构建
|
||||
**任何代码修改后必须先 `@build` 验证(0 错误 0 警告)再提交;硬件闭环用 `@test`。**
|
||||
|
||||
- **仅支持 Keil MDK-ARM v5 (ARMCC)**,无其他工具链
|
||||
- 命令行编译:`@build`(执行 `MDK-ARM/build.bat`,从仓库根目录用**相对路径**调用)
|
||||
- `build.bat` 硬编码 Keil 路径 `C:\Keil_v5\UV4\UV4.exe`(本机已验证存在;换机器需改)
|
||||
- 退出码:0 = 0 错误 0 警告 | 1 = 有警告或错误(查看 `MDK-ARM/build_log.txt`)
|
||||
- ⚠️ **旧绝对路径陷阱**:仓库曾位于 `D:\Code\DTU 程序\STM32F4-Base`,`.opencode/command/*.md` 与 `test/run_boot_test.ps1` 中若出现该路径一律视为失效,改用仓库相对路径(如 `& "MDK-ARM\build.bat"`)
|
||||
## 铁律:源码编辑与编码
|
||||
|
||||
## Python 环境(跑脚本用)
|
||||
- 改代码**只用 Edit 工具**(精确子串替换);批量替换用 Edit 的 replaceAll。**绝不用 `Get-Content`/`Set-Content`/`cmd` 重写含中文的文件**——整文件重写会按系统默认编码重解码 → `U+FFFD` 乱码且不可逆
|
||||
- **字符串字面量必须纯 ASCII**(2026-09-15 实测):本机 ARMCC 对**无 BOM** 源文件按 CP936 解读,字符串内含**奇数个**汉字时末尾高字节吞掉结束引号 → 编译错(偶数个汉字侥幸通过);中文只写注释(注释不参与解析)。带 BOM 的 UI 系文件(`Drivers/BSP/UI/*`、`App/task/ui_task.c`、`Lib/lv_conf.h`)经 BOM 按 UTF-8 解码,不受此条限制
|
||||
- 确需脚本级重写:工程源码为 UTF-8(多数文件无 BOM,UI 系带 BOM),按原样同编码回写、保持 BOM 状态;拿不准就别碰
|
||||
- 发现乱码:先统计 `EF BF BD` 字节数确认真损坏(勿信终端/Read 渲染);**不要急著 `git checkout`**(会丢弃全部未提交工作)——先用 Edit 只修坏行
|
||||
|
||||
- **统一入口:仓库内 `.venv\Scripts\python.exe`**(Python 3.12.4,fontTools + Pillow 已装),所有依赖第三方库的脚本一律用它;依赖清单 `requirements.txt`(仓库根目录)
|
||||
- 重建/换机:`& 'C:\ProgramData\anaconda3\python.exe' -m venv .venv; & '.venv\Scripts\python.exe' -m pip install -r requirements.txt`(种子解释器可用任意带 venv 的 python ≥3.10;`.venv/` 已 gitignore,不入库)
|
||||
- `requirements.txt` 必须**纯 ASCII**:Windows 下 pip 按系统代码页(GBK)解码该文件,中文注释会 UnicodeDecodeError(2026-09-09 实测)
|
||||
- PATH 默认 `python` 是 msys64 的(`C:\msys64\ucrt64\bin\python.exe`),**不要用它**跑依赖第三方库的脚本;纯标准库脚本(回归测试、`extract_cn.py`、`gen_menu.py`)任意 python3 均可
|
||||
- 字体生成:`& '.venv\Scripts\python.exe' tools/font_gen/make_font.py`
|
||||
## 构建与验证
|
||||
|
||||
## 硬件
|
||||
- `@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.ps1` 一键闭环:开串口+清日志 → 烧录(`MDK-ARM/download.bat`,下载后 Reset&Run)→ wait-idle(等 RX 静默 8s,超时 30s)→ `test/verify_log.ps1` 标记校验;退出码 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 程序\...` 出现即失效(仓库已搬迁),一律改用仓库相对路径
|
||||
|
||||
## Python 环境
|
||||
|
||||
- 统一入口 `& '.venv\Scripts\python.exe'`(3.12,fontTools/Pillow 已装);PATH 默认 `python` 是 msys64 的,**不要用它**跑依赖第三方库的脚本;纯标准库脚本任意 python3 均可
|
||||
- 重建/换机:`& 'C:\ProgramData\anaconda3\python.exe' -m venv .venv` + `pip install -r requirements.txt`(`.venv/` 已 gitignore)
|
||||
- `requirements.txt` 必须**纯 ASCII**(Windows 下 pip 按 GBK 代码页解码,中文注释会 UnicodeDecodeError)
|
||||
|
||||
## 提交门禁(pre-commit)
|
||||
|
||||
- 任一失败即拦截:cppcheck(warning/performance/portability/style)+ C 代码规范机械检查 + U+FFFD 乱码检查 + gitlint;范围仅项目代码(第三方 `Lib/`/`Middlewares/`/CMSIS/HAL/`lftpd`/`dhara`/`MDK-ARM`/`test/` 排除;规范检查另排除 CubeMX 生成的 `Src/`/`Inc/`)
|
||||
- 提交信息:**单行中文标题 <100 字符**(gitlint),UTF-8 无 BOM + `git commit -F <文件>`(防终端转码破坏)
|
||||
- 代码规范 V1.0:小写下划线命名(`g_`/`s_`/`p_`/`a_` 前缀)、头文件保护宏 `XXX_H`、常量在右、文件头模块注释块 → `docs/代码规范/`
|
||||
- 全库扫描 `pre-commit run --all-files`;详见 `docs/代码规范/pre-commit使用说明.md`
|
||||
|
||||
## 平台约束
|
||||
|
||||
- `Inc/`/`Src/` 中 CubeMX 生成文件带 `USER CODE BEGIN/END` 标记:自定义代码**只写标记区之间**;`Drivers/BSP/` 为纯手工代码
|
||||
- FreeRTOS V10.3.1(CMSIS-RTOS V2);HAL 时基 = TIM7(非 SysTick),tick = 1ms;NVIC 4 位优先级分组,外设中断优先级 ≥ 5
|
||||
- CH395F SPI:每次事务须 `ch395f_spi_begin()/end()` 包裹;分频系数**必须为 8**(PCB 约束,勿"优化")
|
||||
- **内存预算紧张**:新增任何任务/缓冲/栈前必须先核算 RAM 余量(`docs/内存管理/`、`待处理内容.md`)
|
||||
|
||||
| Task | 栈 (words) | 优先级 |
|
||||
|---|---|---|
|
||||
| defaultTask | 512 | Normal |
|
||||
| netTask | 1024 | Normal |
|
||||
| ftpTask | 1024 | Normal |
|
||||
| testTask | 1024 | BelowNormal |
|
||||
| uiTask | 4096 | BelowNormal |
|
||||
| timeSyncTask | 512 | Normal |
|
||||
|
||||
(实际值以 `Src/freertos.c` 为准,六任务栈合计 32KB;改动栈/缓冲前先核对此表与实测)
|
||||
|
||||
## 架构要点
|
||||
|
||||
`Src/main.c`(CubeMX 初始化)→ `app_main_init` → `osKernelStart` → 6 任务
|
||||
|
||||
- `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` 阻塞等待
|
||||
- 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)→ 网络配置加载(`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 栈 / 目录组织)
|
||||
|
||||
## 硬件引脚
|
||||
|
||||
| 外设 | 接口 | 引脚 |
|
||||
|------|------|------|
|
||||
| CH395F 以太网 | SPI2 | PB12 CS, PB13 SCK, PB14 SDO, PB15 SDI |
|
||||
| GD5F2GQ5UE NAND | SPI1 | PE0 CS, PB3 SCK, PB4 MISO, PB5 MOSI, PB8 WP, PE1 HOLD |
|
||||
| TPAFE5160 ADC | 并行16位 | PG0-PG15 数据, PD3 RD, PD4 CONVST, PD7 BUSY |
|
||||
| USART1 | 串口 | PA9 TX, PA10 RX (115200bps) |
|
||||
| USART1 调试串口 | UART | PA9 TX, PA10 RX (115200) |
|
||||
| RS-485 | UART5 | PC12 TX, PD2 RX, PD0 DE(半双工) |
|
||||
| 6x LED | GPIO | PC4, PC5, PB1, PB2, PF11, PF12(低电平点亮) |
|
||||
|
||||
MCU: STM32F407ZGTx @ 168MHz (HSE 8MHz → PLL M=4/N=168/P=2,见 `*.ioc`/`stm32f4xx_hal_conf.h`)
|
||||
## 模块约定
|
||||
|
||||
## 架构
|
||||
- **CH395F 单连接 socket**:监听与数据通道复用同一 Socket(CONNECT 后转数据通道,DISCONNECT/TIMEOUT 后重开 → LISTEN);所有 CH395F 中断在 `net_poll()` 内经 `GET_GLOB_INT_STATUS` 集中读取并清除,**不得**在 ISR 或其他地方单独处理
|
||||
- 所有 `net_*` socket 操作经 `netMsgQueue` 消息队列在 netTask 串行执行(线程安全);非 netTask 任务直接调 `net_*` API,勿直接碰 CH395F 驱动
|
||||
- 网口配置:`/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`);全部注释 = 产品构建;CH395F 套件 `test/ch395f_test.h`:硬件层 Phase 1~5 与 NET 层 Phase 6~11 互斥;CH395F 硬件层模式下 netTask(基础线程:无条件创建、全构建唯一实例)入口自挂起(不运行),testTask 独占 CH395F
|
||||
- **改驱动前先读对应 `docs/问题记录/*_Trap_Records.md`**(CH395F / GD5F2GQ5UE / SD2506);各模块测试指南见 `docs/测试说明/`
|
||||
|
||||
```
|
||||
Src/main.c → CubeMX 外设初始化 → app_main_init → osKernelStart
|
||||
→ [FreeRTOS tasks: defaultTask, netTask, ftpTask, testTask, uiTask, timeSyncTask]
|
||||
```
|
||||
## 串口助手 serial_tool
|
||||
|
||||
- **app_main_init 顺序**(时间子系统优先,使后续日志带时间戳):`sd2506_init` → `sys_clock_init`(墙钟基准)→ `rs485_init` → `gd5f2gq5ue_init` → `tpafe5160_init` → SD2506 诊断 → `tpafe5160_start_conv_irq`
|
||||
- **就绪屏障**(`App/sys_events.h` Event Flags,取代魔法延时/全局轮询):`SYS_EVT_NET_READY`(bit0, netTask 置位) / `SYS_EVT_STORAGE_READY`(bit1, defaultTask 置位) / `SYS_EVT_FTP_READY`(bit2) / `SYS_EVT_TIMESYNC_READY`(bit3);消费者用 `osEventFlagsWait` 阻塞等待
|
||||
- **defaultTask**:FatFS 挂载(`f_mount` forced,无卷自动 `f_mkfs` FAT32)→ 置 `SYS_EVT_STORAGE_READY` → LED 闪烁循环
|
||||
- **netTask**:等 `SYS_EVT_STORAGE_READY`(≤10s)→ `net_stack_bring_up()`(`net_cfg_load` 读网口配置(`/config.ini` [network] 段,首启自动迁旧档 NCFG)→ `net_init(ip,mask,gw,mac)` + PHY 强制 100M 全双工 + 等链路 ≤3s → 回写芯片实际 MAC 影子 → 递增网络代次号)→ 置 `SYS_EVT_NET_READY` → 循环 `net_poll()` + `net_process_messages()` + `osDelay(1)`(tick=1ms);循环内消费 `SYS_EVT_NET_RECONFIG`(UI 保存网口配置后请求)→ 立即重建网络(新 IP 生效,无需重启;各 TCP 服务据代次号重建监听)
|
||||
- **ftpTask**:`osEventFlagsWait(NET_READY | STORAGE_READY, WaitAll)` 后 `lftpd_start("/", 21, &ftp)`(已无 7s 魔法延时)
|
||||
- **testTask**:测试套件入口(`test/test_config.h` 选择;产品构建下空转)
|
||||
- **uiTask**:等 `SYS_EVT_NET_READY` 后 `ui_port_init` → `ui_menu_init` → 启动 UI net sink
|
||||
- **timeSyncTask**:TCP 墙钟时间同步(PC 推送)
|
||||
- 功能编译开关:`App/app_cfg.h`(`APP_NET_ENABLE` / `APP_ADC_ENABLE` / `APP_RS485_ENABLE`)
|
||||
- **全景架构图**:`docs/项目架构总览.md`(六层分层 / 任务与就绪屏障 / 启动时序 / 存储·网络·UI 栈 / 目录组织)
|
||||
|
||||
### 任务栈
|
||||
|
||||
| Task | 栈大小(words) | 优先级 |
|
||||
|---|---|---|
|
||||
| defaultTask | 2048 | Normal |
|
||||
| netTask | 4096 | Normal |
|
||||
| ftpTask | 4096 | Normal |
|
||||
| testTask | 4096 | BelowNormal |
|
||||
| uiTask | 16384 | BelowNormal |
|
||||
| timeSyncTask | 2048 | Normal |
|
||||
|
||||
## CH395F 设计原则
|
||||
|
||||
- **单连接 socket**:Socket 0 复用监听和数据通道,收到 CONNECT 后切换为数据通道,DISCONNECT/TIMEOUT 后重新 OPEN → LISTEN
|
||||
- **中断统一处理**:所有 CH395F 中断在 `net_poll()` 中通过 `GET_GLOB_INT_STATUS` 集中读取并清除,不得在 ISR 或其他地方单独处理
|
||||
|
||||
## NET 网络层
|
||||
|
||||
- `net_socket.h/c` — BSD Socket API;**单连接模式**(`ch395f_set_fun_para(0x09)`:多 Socket + TCP Server 单连接 + 手动关闭),连接停留在 Socket 0
|
||||
- `net_select.h/c` — select/poll I/O 多路复用
|
||||
- 线程安全通过消息队列(`netMsgQueue`)实现,所有 CH395F 操作在 netTask 中串行处理
|
||||
- `net_init` 顺序:check_exist → reset → `set_fun_para(0x09)` → MSS/重传/KeepAlive → IP → `ch395f_init()` → `ch395f_set_mac_addr()`(mac 非空且非全零时)→ Socket 0~7 缓冲分配 → ping 使能
|
||||
- 网口参数(IP/掩码/网关/MAC)取自通用配置文件 `/config.ini` 的 [network] 段(`Drivers/BSP/NETCFG/` + `App/cfg_file` 引擎:工厂默认 192.168.1.100/24、gw .1,MAC 全零 = 芯片内置),保存后**立即生效**(网络重建)或下次上电生效;旧版 `/cfg/netcfg.bin`(NCFG)首启自动迁移;PHY 强制 100M 全双工
|
||||
- **新文件需手动添加到 Keil MDK 工程**才能编译
|
||||
|
||||
## 测试构建模式
|
||||
|
||||
- `test/test_config.h`:`TEST_SUITE_CH395F` / `TEST_SUITE_STORAGE` / `TEST_SUITE_GD5F` / `TEST_SUITE_RTC` **互斥**(一次构建只能启用一个,`#error`);全部注释 = 正常产品构建
|
||||
- CH395F 套件沿用 `test/ch395f_test.h` 阶段宏:硬件层 Phase 1~5 与 NET 层 Phase 6~11 **互斥**(`#error`);硬件层模式下 netTask 不创建,testTask 独占 CH395F
|
||||
- 各模块测试指南见 `docs/测试说明/`(CH395F / GD5F / SD2506 / FTP)
|
||||
|
||||
## 关键文件
|
||||
|
||||
| 路径 | 说明 |
|
||||
|---|---|
|
||||
| `Src/main.c` | 入口,CubeMX 生成 + USER CODE 区域 |
|
||||
| `Src/freertos.c` | FreeRTOS task 创建,CubeMX 生成 + USER CODE 区域 |
|
||||
| `App/app_main.c` | 应用初始化流程编排 |
|
||||
| `App/sys_events.h` | 系统就绪事件(Event Flags 就绪屏障) |
|
||||
| `App/app_cfg.h` | 功能模块编译开关 |
|
||||
| `App/task/net_task.c` | netTask 主循环(网络初始化 + 轮询) |
|
||||
| `test/test_config.h` | 测试套件选择(互斥开关) |
|
||||
| `Drivers/BSP/NET/` | BSD Socket API 网络抽象层 + lftpd |
|
||||
| `Drivers/BSP/NETCFG/` | 网口配置(通用配置文件 `/config.ini` [network] 段 + 旧档 NCFG 迁移;网口设置内容页数据源) |
|
||||
| `App/cfg_file.*` + `App/cfg_file_store*` | 通用配置文件引擎(双端共享核心 + 平台存储后端:INI 解析/校验/外科保存/模板/沉降轮询) |
|
||||
| `App/log/sys_log.h` + `sys_log_mcu.c` | 运行/自检记录引擎(定长 64B 文本记录,落盘 `/log/run.log`·`selftest.log`,defaultTask 唯一写者;UI 页与 FTP 数据源) |
|
||||
| `Drivers/BSP/CH395F/` | CH395F SPI 驱动 |
|
||||
| `Drivers/BSP/GD5F2GQ5UE/` | NAND Flash 驱动 + dhara FTL + FatFS diskio |
|
||||
| `Drivers/BSP/TPAFE5160/` | ADC 并行接口驱动 |
|
||||
| `Drivers/BSP/SD2506/` | RTC 驱动 |
|
||||
| `Drivers/BSP/RS485/` | RS-485 通信(UART5 + PD0 DE) |
|
||||
| `Drivers/BSP/UI/` | LVGL UI 组件(与 PC 模拟器共用源码) |
|
||||
|
||||
## 驱动关键点
|
||||
|
||||
详见 `docs/` 目录:
|
||||
- `docs/项目架构总览.md` — 六层全景架构(分层/任务/启动时序/存储·网络·UI 栈)
|
||||
- `docs/配置文件设计说明.md` — 通用配置文件(INI `/config.ini`:设计决策 D1–D15 / 双端支持 / 阶段规划 P1–P8 / 测试与风险)
|
||||
- `docs/网络配置说明.md` — 网口设置页配置(UI 可改的 IP/掩码/网关/MAC:持久化 / 立即生效 / 页面操作)
|
||||
- `docs/问题记录/CH395F_Trap_Records.md` — CH395F 已知陷阱
|
||||
- `docs/问题记录/GD5F2GQ5UE_Trap_Records.md` — GD5F2GQ5UE 已知陷阱
|
||||
- `docs/问题记录/SD2506_Trap_Records.md` — SD2506 RTC 已知陷阱
|
||||
- `docs/测试说明/CH395F_Test_Guide.md` — 网络测试说明(含构建模式与执行顺序)
|
||||
|
||||
## 串口调试(Python 串口助手 serial_tool)
|
||||
|
||||
通过仓库内置 **Python 串口助手**(`tools/serial_tool/serial_tool.py`,常驻 daemon + 薄 CLI)自主读取/控制 **USART1 串口**(PA9 TX / PA10 RX,115200bps)的打印流。
|
||||
|
||||
- **统一入口**:`& '.venv\Scripts\python.exe' 'tools/serial_tool/serial_tool.py' <命令> [参数]`(daemon 未运行自动拉起;全部命令带硬超时 5s,JSON 输出,exit 0/1/2/3)
|
||||
- **全量历史 = 日志文件** `tools/serial_tool/state/serial.log`(RX/TX/SYS 时间戳行;Agent 直接 Read/Grep 读文件,无采集窗口仪式);20MB 上限自动截头保尾 10MB
|
||||
- **常用命令**:`ports`(枚举+配置口标注)/ `open`(幂等,不存在/占用 ≤1s 报错)/ `send`(位置参数文本 或 `--hex 0D0A`,`--nl` 加 CRLF)/ `status`(全状态)/ `log --tail N --grep P` / `clear`(代际+1)/ `wait-idle --settle-ms 8000 --max-ms 30000` / `close` / `start|stop|restart` / `selftest`(无头自检)
|
||||
- **串口端口单一配置源:`.opencode/serial_config.json`**(当前本机为 `COM6`)。端口变化只改这个文件。
|
||||
- 命令契约、日志行格式、daemon 行为、已知陷阱详见 **`docs/测试说明/串口助手设计说明.md`**
|
||||
|
||||
## 自动化测试(AI 迭代闭环)
|
||||
|
||||
改完代码后运行 **`@test`** 可自动执行完整闭环:**构建验证 → 开串口 + 清空日志(serial_tool,daemon 常驻,全程不关端口)→ 烧录(`MDK-ARM/download.bat`,下载后 Reset & Run)→ `wait-idle`(等 RX 静默 8s 或超时 30s)→ 提取 `[RX]` 行 → `test/verify_log.ps1` 标记校验 → PASS/FAIL 判定并迭代**。
|
||||
|
||||
- **推荐一键命令**:`test/run_boot_test.ps1` = open → clear → 烧录 → wait-idle → 提取日志 → verify 全流程,退出码 0=PASS / 1=FAIL / 2=采集或烧录错误 / 3=用法/预检错误
|
||||
- 判定标准:`@test` 内部先 `@build`(0 错误 0 警告),再 `@download`(退出码 0),日志用 `verify_log.ps1` 校验(默认 Required:`App init OK`/`Network Init`/`net init: OK`;Forbidden:`FAIL`/`ERROR`/`HardFault`)
|
||||
- daemon 常驻全量日志文件:开串口 + clear 必须在烧录**前**完成(`run_boot_test.ps1` 已保证顺序);旧 serial-mcp-server 的"采集窗口/first-byte/EOF 重试"仪式已整体移除
|
||||
- 每次按模块定制标记(网络/存储/RTC/ADC/RS485)见 `docs/测试说明/自动化测试流程.md`
|
||||
- UI 已有 DBG 打印(`UI port init: OK` / `UI menu init: OK` / `UI net sink: started`),可用 `-Required "UI port init: OK;UI menu init: OK"` 自动回归 UI 初始化;屏幕内容仍需人工目检
|
||||
|
||||
## 代码规范与 pre-commit
|
||||
|
||||
- **提交被 pre-commit 钩子门禁**,任一失败即拦截:cppcheck 静态分析(warning/performance/portability/style)+ 代码规范机械检查 + U+FFFD 乱码检查 + gitlint commit message
|
||||
- 代码规范 V1.0(`docs/代码规范/嵌入式C语言代码规范(V1.0).md`):命名小写下划线(`g_`/`s_`/`p_`/`a_` 前缀)、头文件保护宏 `XXX_H`、常量在右、文件头模块注释块等;可机械校验项由 `scripts/check_coding_standard.py` 强制
|
||||
- 检查范围仅项目自有代码;第三方(`Lib/`、`Middlewares/`、CMSIS/HAL、`lftpd`、`Drivers/BSP/UI`、`test/`)被排除
|
||||
- 新机器启用:`pre-commit install`;全库扫描:`pre-commit run --all-files`
|
||||
- 详见 `docs/代码规范/pre-commit使用说明.md`、`docs/代码规范/cppcheck使用说明.md`
|
||||
- 入口:`& '.venv\Scripts\python.exe' tools/serial_tool/serial_tool.py <命令>`(daemon 自动拉起;全部命令 5s 超时、JSON 输出、exit 0/1/2/3)
|
||||
- 全量历史 = 日志文件 `tools/serial_tool/state/serial.log`(RX/TX/SYS 时间戳行);agent 直接 Read/Grep 文件,**无采集窗口仪式**;20MB 上限自动截头保尾 10MB
|
||||
- 常用:`open`(幂等)/ `send <文本>`(或 `--hex 0D0A`)/ `log --tail N --grep P` / `clear`(代际+1)/ `wait-idle --settle-ms 8000 --max-ms 30000` / `status` / `close`
|
||||
- 串口端口单一配置源:`.opencode/serial_config.json`(当前 COM6);端口变化**只改这个文件**
|
||||
- 命令/工作流/故障排查 `docs/测试说明/串口助手使用指南.md`;契约/daemon 行为/陷阱 `docs/测试说明/串口助手设计说明.md`
|
||||
|
||||
## LVGL PC 模拟器
|
||||
|
||||
`simulator/`(CMake + SDL2 2.32.10 预编译库)可在 PC 上开发调试 UI,**与 MCU 端共用 UI 源码**(`Drivers/BSP/UI/ui_menu.c`、`ui_font_cn_12.c`),无需烧录:
|
||||
- `simulator/`(CMake + SDL2 预编译库)与 MCU 端共用 UI 源码(`ui_menu.c`、`ui_font_cn_12.c`),免烧录开发 UI:`cmake -B build -G "Visual Studio 16 2019" -A x64; cmake --build build --config Debug` → 运行 `simulator\build\Debug\lvgl_sim.exe`
|
||||
- 自检:`--cfgtest`(配置闭环)/ `--logtest`(日志引擎)/ `--standby shot.bin`(待机屏截图)/ `--idle <秒>`
|
||||
- UI 改动一律走 **`ui-verify` skill 五步门禁**;含新汉字的 UI 文案提交前先跑 **`font-regen` skill** 重生成中文字体
|
||||
|
||||
```powershell
|
||||
cd simulator
|
||||
cmake -B build -G "Visual Studio 16 2019" -A x64
|
||||
cmake --build build --config Debug
|
||||
# 运行 simulator\build\Debug\lvgl_sim.exe
|
||||
```
|
||||
## 文档与图形
|
||||
|
||||
- 详见 `docs/UI 设计/LVGL模拟器部署与使用说明.md`
|
||||
- 中文字体:`ui_cn_chars.txt`(字符集)+ `tools/font_gen/` 生成 `Drivers/BSP/UI/ui_font_cn_12.c`,见 `docs/UI 设计/UI_中文字体生成与配置.md`
|
||||
- 配置自检:`simulator\build\Debug\lvgl_sim.exe --cfgtest`(无头、进程内闭环:加载/旧档迁移 → 2s 轮询沉降 → 重载断言 + 外科保存无损回环;0=PASS,详见 `simulator/README.md` §3.7)
|
||||
- 日志引擎自检:`lvgl_sim.exe --logtest`(post N 条 → count/get 回读断言 + 宿主文件字节级校验;0=PASS);待机屏截图:`--standby shot.bin`;窗口模式空闲超时覆盖 `--idle <秒>`
|
||||
|
||||
## 图形绘制(文档配图)
|
||||
|
||||
文档里的技术图形统一用 **SVG 生成器**(`tools/arch_diagram/`,纯标准库)或 **Mermaid**,**勿手绘 ASCII 框图**:
|
||||
- **精确布局图**(协议帧 / 分层架构 / 依赖 / 就绪屏障)→ `tools/arch_diagram/gen_*.py`:改脚本顶部数据 → `& '.venv\Scripts\python.exe' tools/arch_diagram/gen_xxx.py` 重新生成 `docs/images/*.svg`(脚本内置 XML 自检)。
|
||||
- **拓扑类图**(流程 / 时序 / 状态机)→ Markdown 内嵌 `mermaid` 代码块。
|
||||
- 全流程 / 选型 / 约定 / 检查清单见 **`docs/图形绘制流程.md`**(已沉淀为 `draw-diagram` skill);产物统一放 **`docs/images/`** 专门目录;脚本与生成的 `.svg` 一并提交。
|
||||
|
||||
## 注意
|
||||
|
||||
- `Inc/` 和 `Src/` 中 CubeMX 生成的文件带有 `USER CODE BEGIN`/`END` 标记,自定义代码写在这些区域之间
|
||||
- `Drivers/BSP/` 下的驱动文件为纯手工代码,不受 CubeMX 保护
|
||||
- CH395F 每次 SPI 事务需用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹
|
||||
- CH395F SPI PCB 设计问题,分频系数必须为 8,速度相对较低
|
||||
- FreeRTOS V10.3.1 via CMSIS-RTOS V2,HAL 时基用 TIM7(非 SysTick),tick = 1ms
|
||||
- NVIC 优先级分组 4 位,外设中断优先级 ≥ 5(`configLIBRARY_MAX_SYSCALL_INTERRUPT_PRIORITY`)
|
||||
- **内存预算紧张**:任务栈目前普遍偏大(见 `待处理内容.md`),新增任务/缓冲/栈前必须先核算 RAM 余量
|
||||
|
||||
## 源码编辑与编码安全(铁律)
|
||||
|
||||
本工程源码含大量中文注释,曾因错误的文本重写方式导致整文件乱码(`U+FFFD` 替换符,不可逆)。以下规则必须遵守:
|
||||
|
||||
- **绝不用 `Get-Content` / `Set-Content` / `cmd` 文本重写含中文的源码文件**。这类"整文件重写"会按系统默认编码重新解码再写回,多字节中文必被 `U+FFFD` 替换且不可逆。
|
||||
- **改代码只用 Edit 工具**(精确子串替换,不重新编解码整个文件,安全);批量替换用 Edit 的 `replaceAll`。
|
||||
- 必须脚本级替换时,使用显式且一致的编码(**工程源码为 UTF-8**:多数文件无 BOM,但 UI 相关文件 `Drivers/BSP/UI/*`、`App/task/ui_task.c`、`Lib/lv_conf.h` 为 UTF-8 **带 BOM**——如 Python `open(p, encoding="utf-8"/"utf-8-sig")` 按原样同编码回写,保持 BOM 状态不变)——但**最稳的是别碰**,只用 Edit / git。
|
||||
- **发现乱码先别急着 `git checkout`**:`git checkout` 会丢弃所有未提交工作,使损失扩大。先评估能否用 Edit 仅改坏掉的那几行。
|
||||
- 验证是否真损坏用字节级检查(统计 `EF BF BD` 出现次数),不要依赖终端/Read 渲染判断。
|
||||
- 配置文件 `docs/配置文件设计说明.md`;墙钟 `docs/系统墙钟时间维护说明.md`;代码规范 `docs/代码规范/`;测试说明 `docs/测试说明/`;审计发现 `docs/项目审计改进清单.md`;已知待办 `待处理内容.md`(内存预算)
|
||||
- 图形走 **`draw-diagram` skill**:精确布局图(协议帧/分层/屏障)用 `tools/arch_diagram/gen_*.py` 生成器(产物放 `docs/images/`,脚本与 .svg 一并提交);拓扑图(流程/时序/状态机)用 Mermaid;**勿手绘 ASCII 框图**
|
||||
|
||||
Reference in New Issue
Block a user