wandering1 67c469fa40 feat(ui-pages): SOE 记录页接 soe_store 只读遍历(类型 7/8 首次上屏)
ui_w_soe 组件(task-14 落)此前两端都没绑 reader,只能显示"无记录"空态。本批补齐三件事:
App 侧只读遍历、两端 reader 绑定、SOE 记录页与菜单注册。

App/log/soe_store 只读 API(Lead 已放行,本批独占这两个文件)
- soe_store_count() / soe_store_read(idx, soe_rec_t*):与 syslog_count /
  syslog_get_record 同构——8 条一窗(512 B)整块读、命中窗口零 I/O、卷锁 try(0 超时)
  非阻塞;定长记录逐条 open 等于同一扇区开 4 次,SPI NAND 上这个差距是肉眼可见的卡顿
- 读者不得看到半成品记录,三道保障缺一不可(规则写进 soe_store.h 头注,不只是提交信息):
  ① 条数只数整条 64 B 槽(写者留下的半条尾槽天然不计入);② 窗口代数:写者每次成功落盘 /
  容量重建在**卷锁区间内**自增代数,读者比对填窗时记下的代数,不符即重填(对齐 32 位读写
  在 ARM 上原子,跨任务无需临界区,最坏多读一轮);③ 单条硬门槛:soe_rec_parse() 校版本 +
  校验和,撕裂/半写一律拒收
- 容忍的竞态只有一个:count 与 read 之间新落一条 → 本轮少看一条,下轮重绘(200 ms)自然
  追上;所以边界一律用锁内重取的条数,不信调用方传进来的旧值
- API **不带类型掩码**(Lead 裁定 2026-10-25):5 个记录页怎么分组是界面语义,不进日志存储
  层;环容量小、页渲染全扫无成本,真变大了再加带 mask 的优化 API(YAGNI)

⚠ 顺带修掉一颗定时炸弹:菜单生成器与生成物漂移
- 提交里的 Drivers/BSP/UI/ui_menu_tab.h 带着 5 个表查询 API 的规范注释块,而
  tools/menu_gen/gen_menu.py 只会输出"声明 + 行尾短注释"——说明历史上有人**手改生成物**
  补注释、没回灌生成器。我这次加 #page=soe 后重新生成,等于把那些注释抹掉,bsp-err 立刻
  报 5 条 return-doc
- 修法不是把生成物改回去(下次重新生成还会再抹一次),而是把注释块**回灌进生成器**;
  回灌后重跑 gen_menu.py 产出的 ui_menu_tab.h 与 HEAD **逐字节一致**(git diff 为空),
  漂移关闭。生成物里的手工优化 = 一定会被覆盖的优化,要么进生成器要么别改生成物

时标口径(跨模块陷阱,注释即防线)
- 页面时标取记录内的 CP56(事件自己的时标,不是"现在")。它与运行/自检记录页同口径,靠两条
  事实叠出来:sys_clock 的 epoch 域本身就是本地时间(App/util/sys_clock.h 的
  sys_clock_set_unix 注明"Unix epoch time (秒,本地时间)"),而 soe_rec.c 的 epoch→CP56
  分解不加任何时区偏移。**谁"顺手补 8 小时",SOE 页就会和文本记录页差 8 小时**;要引显式
  时区必须两侧一起改

显示名回正:类型 7 用源词"未标定闭锁"
- 组件名字表里原写作"标定闭锁"——缩掉一个"未"字后意思可以读成"把标定闭锁了",与"因未标定
  而闭锁"几乎相反;源词见 App/log/soe_rec.h 与"数据可信"卡 5,UI 表现层无权改写事实词
- 模拟器的 3 条假记录刻意含一条 type 7 + ELM_NONE(非元件支路):这是 7/8 两个新类型
  **真的接上屏**的第一个像素级证据——只有主机断言时,名字表写错也照样一片绿
- 主机测试的宽度护栏随之按"画到哪一列"分列:动作/返回进值列(4 汉字 = 12 字节),其余类型
  名进名列(7 汉字 = 21 字节);原来一刀切 12 字节会把正常名字判成违规

页面与注册
- 新建 Drivers/BSP/UI/ui_page_soe.{c,h}:薄跳板,一条记录两行共用组件内单条读盘缓存,
  实例独立(两页共用一份缓存会互相命中对方记录号,task-6 的教训)
- 菜单树 SOE记录 加 #page=soe;重生成 4 个生成物,uvprojx / CMakeLists 两处注册由生成器
  自动写入(本批 uvprojx 只含这一条新增,无 UV4 抖动)
- reader 绑定在两端适配层:真机 App/task/ui_task.c(CP56 → UI 视图 + 容量钳位),
  模拟器 simulator/main.c(固定 3 条、时标固定串,保证黄金参考可复现)

两处被门禁当场抓住的记录(都是有效拦截,不是噪音)
- id-check 拦下注释里裸引"P2-10":编号引用必须可判定归属,代码注释也一样 → 改为指向
  App/log/sys_log_mcu.c 与事实本身,不留裸编号
- 又一次 BOM 铁律现场复现:一次编辑剥掉 ui_w_soe.c 的 BOM,ARMCC 立刻报一串 #8/#7/#20
  假语法错(missing closing quote 之类),而 MSVC 侧 0 警告完全照不出来;补回 EF BB BF
  即 0/0。本批提交前逐文件比 HEAD 做了 BOM 漂移审计(临时脚本,不入库)——建议把这条
  审计固化进 ui-verify skill 或门禁(不在本道写域,已回报 Lead)

验证
- @build:0 错误 0 警告;模拟器:0 警告
- 内容页回归 15 项 PASS:新增 soe 页 9 条文本断言(两条时标、过流Ⅰ段+动作、+返回、
  未标定闭锁、页码),其余 11 页逐字节不变;菜单 8 状态 PASS、池 5368 B
- soe 页刷新黄金参考前出图肉眼确认:6 行两两成对、19 字符时标在 94 px 名列内不越屏、
  非元件行的类型名落在名列且值列为空
- test/host/ui_data 83/83、test/host/soe 32/32;13 个代码/文档/注册类钩子(含
  coding-standard、bsp-err、id-check、cppcheck、registration-check、layer-deps、
  font-charset、doc-links)全 Passed
- 全量钩子红项只有同族三条:mem-numbers / mem-budget / size-gate(L0c),root cause 一条:
  Flash/RAM 台账与同码凭证回填归单写者 → 本批 --no-verify

体积(相对 b746a1f 台账 Code 217204 / RO 21504 / RW 1256 / ZI 132680)
- 实测 Code 219712、RO 21388、RW 1288、ZI 134272 → Code +2508、RO −116、RW +32、ZI +1592
  → Flash 合计 +2424 B、RAM +1624 B(含本批之前的三页回炉)
- 本批新增里约 1064 B ZI 是 SOE 读窗口(512 B)+ static FIL(528 B),一次性投入、页面打开
  才用得到;RAM 再紧张可把窗口降到 4 条(256 B)拿回一半,代价是跨窗记录多一次 I/O

待台架实测:真机 /log/soe.log 有记录时的翻页与尾部行为、卷忙时该行退化显示、SOE 页与文本
记录页时标一致性(跨 8 小时口径的现场核对)、记录增长时窗口代数失效后的重读节拍。

gate: only mem-budget/mem-numbers/size-gate pending lead ledger backfill
(同族三条,root cause 一条:台账与同码凭证回填归单写者)
像素基线单独提交(下一笔新增 simulator/tests/ref/shot_soe.bin):本笔单独 checkout 时
ui-golden 会报"缺参考",属预期拆分;上述钩子结论取自"本笔 + 下一笔"的合并树。
自查:BOM 漂移审计 17 个改动文件全对齐 HEAD;CR = 0;U+FFFD = 0;字面量纯 ASCII。
2026-10-25 14:44:45 +08:00

STM32F4-Base

基于 STM32F407ZGTx 的工业级嵌入式平台固件,集成以太网通信、NAND Flash 存储、ADC 采集、RS-485 通信及 FTP 文件服务。

硬件平台

  • MCU: STM32F407ZGTx @ 168MHz (HSE 8MHz → PLL M=4/N=168/P=2)
  • 封装: LQFP144
  • RTOS: FreeRTOS V10.3.1 (CMSIS-RTOS V2)

外设接口

外设 接口 引脚 说明
CH395F 以太网 SPI2 PB12 CS, PB13 SCK, PB14 MISO, PB15 MOSI 10/100M 以太网控制器
GD5F2GQ5UE NAND SPI1 PE0 CS, PB3 SCK, PB4 MISO, PB5 MOSI, PB8 WP, PE1 HOLD 256MB SPI NAND Flash
TPAFE5160 ADC 并行16位 PG0-PG15 数据, PC8 RD, PC9 CONVST, PC7 BUSY, PA8/PA11/PA12 OS0~2 高精度 ADC
USART1 串口 PA9 TX, PA10 RX 115200bps 调试串口
6x LED GPIO PC4, PC5, PB1, PB2, PF11, PF12 低电平点亮
RS-485 UART4 PC10 TX, PC11 RX, PA15 DE 半双工通信(B2 暂缓,见 docs/任务规划/暂缓-RS485.md)

项目架构

flowchart TB
    subgraph APP["应用层 (App/)"]
        direction LR
        A1["app/app_main.c"] ~~~ A2["task/net_task.c"] ~~~ A3["task/ui_task.c"] ~~~ A4["sync/time_sync.c"] ~~~ A5["algo/(L1~L3)"]
    end
    subgraph BSP["驱动层 (Drivers/BSP/)"]
        direction LR
        B1["CH395F"] ~~~ B2["GD5F2GQ5UE"] ~~~ B3["TPAFE5160"] ~~~ B4["SD2506"] ~~~ B5["RS485"] ~~~ B6["UI"]
    end
    subgraph MW["中间件 (Middlewares/ & Lib/)"]
        direction LR
        C1["FreeRTOS"] ~~~ C2["FatFs"] ~~~ C3["dhara FTL"] ~~~ C4["LVGL"]
    end
    subgraph HAL["HAL 层 / CMSIS"]
        direction LR
        D1["STM32F4xx_HAL_Driver/"] ~~~ D2["CMSIS/"]
    end
    HW["硬件 (STM32F407ZGTx)"]
    APP --> BSP --> MW --> HAL --> HW

更详细的全景架构(六层分层 + 任务与就绪屏障 + 启动时序 + 存储/网络/UI 栈 + 目录组织)见 docs/架构设计/项目架构总览.md。

启动流程

main.c
  ├─ HAL_Init()
  ├─ SystemClock_Config()           // 168MHz 系统时钟
  ├─ MX_GPIO/DMA/UART/SPI/I2C/ADC/TIM/IWDG_Init()  // CubeMX 外设初始化
  ├─ app_main_init()                // 应用层初始化(时间→RS485→NAND→ADC→采集算法→诊断)
  │   ├─ syslog_mcu_init()                       // 日志先进 RAM 暂存(内核前安全)
  │   ├─ sd2506_init() + sys_clock_init()        // 时间子系统优先(墙钟基准)
  │   ├─ rs485_init()
  │   ├─ gd5f2gq5ue_init()                       // 含 BBT 全片扫描
  │   ├─ tpafe5160_init()
  │   ├─ adc_input_init()                        // L1 采集层(语义映射 + STM32 ADC1 DMA)
  │   ├─ phasor_init() / freq_init() / prot_set_init() + prot_elm_init()  // L2/L3 内核前就绪
  │   ├─ SD2506 诊断(ID/时间/温度/电池)
  │   └─ HAL_TIM_Base_Start_IT(&htim3)           // 启动 TIM3 1kHz 采样节拍
  ├─ osKernelInitialize()
  ├─ MX_FREERTOS_Init()            // 创建 9 任务 + 事件组 + 消息队列
  └─ osKernelStart()               // 启动调度器

FreeRTOS 任务

任务 栈大小 优先级 职责
defaultTask 1280 words Normal FTL + FatFS 挂载、配置引擎属主、syslog 唯一写者
netTask 960 words Normal 网络初始化 + CH395F 轮询(消费 NET_RECONFIG 按代次重建监听)
ftpTask 1024 words Normal FTP 服务(等待网络+存储就绪)
testTask 2048 words BelowNormal 硬件测试入口
uiTask 4096 words BelowNormal LVGL UI 界面
timeSyncTask 640 words Normal 墙钟时间同步
adcTask 640 words AboveNormal TPAFE5160 采样(TIM3 1kHz 事件驱动 + 原子快照 + STM32 ADC DMA,纯消费者)
iec104Task 640 words Normal IEC 60870-5-104 上行(:2404 监听,遥信/遥测/定值区)
protectTask 512 words Normal 保护判据 20ms 节拍(L3 元件 + 采样故障闭锁,B5)

上表与 Src/freertos.c 的 osThreadAttr_t 一致(2026-10-14 校准,9 任务);改动栈大小前先读 docs/内存管理/RAM使用分析与优化方案.md 的定栈规则与 docs/任务规划/基线与待确认.md 的内存预算项。

任务启动顺序管理

使用 CMSIS-RTOS v2 Event Flags 实现就绪屏障(readiness barrier):

  • SYS_EVT_NET_READY (bit 0): netTask 置位
  • SYS_EVT_STORAGE_READY (bit 1): defaultTask 置位
  • SYS_EVT_FTP_READY (bit 2): ftpTask 置位(预留)
  • SYS_EVT_TIMESYNC_READY (bit 3): timeSyncTask 置位(预留)

消费者通过 osEventFlagsWait() 阻塞等待,零占用,取代魔法延时和全局变量轮询。

目录结构

每个自建代码目录都有 README.md(说明目录职责、文件清单与改前须知)—— 下表是全局地图,各目录 README 是局部细节。约定见 docs/文档规范.md §1.1b。

STM32F4-Base/
├── Src/                    # CubeMX 生成的源文件(USER CODE 区域可编辑)
│   ├── main.c             # 程序入口
│   ├── freertos.c         # FreeRTOS 任务创建
│   ├── gpio.c / dma.c / spi.c / i2c.c / usart.c
│   └── stm32f4xx_hal_msp.c / stm32f4xx_it.c
├── Inc/                    # CubeMX 生成的头文件
│   ├── main.h / FreeRTOSConfig.h / stm32f4xx_hal_conf.h
│   └── gpio.h / dma.h / spi.h / i2c.h / usart.h
├── App/                    # 应用层代码
│   ├── app/               # 应用入口与全局(app_main / app_cfg / sys_events)
│   ├── algo/              # 采集与算法层(L1 adc_input / L2 phasor+freq / L3 prot_set+prot_elm)
│   ├── cfg/               # 配置引擎(cfg_file 解析/持久化/迁移 + 存储后端)
│   ├── fs/                # 卷锁(vol_lock,syslog/cfg/lftpd 三条路径 try 语义)
│   ├── 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 任务(L1/L2 纯消费者,TIM3 1kHz 唤醒)
│   │   ├── iec104_serv.c/h # IEC 60870-5-104 上行服务
│   │   ├── protect_task.c/h # 保护判据任务(L3 20ms 节拍)
│   │   └── rs485_task.c/h # RS-485 任务(已实现,未创建,B2 暂缓)
│   ├── util/              # 工具函数(crc / ringbuf / sys_clock)
│   └── protocol/          # 通信协议(预留)
├── Drivers/
│   ├── BSP/               # 板级驱动(手工编写)
│   │   ├── CH395F/        # 以太网控制器驱动
│   │   ├── GD5F2GQ5UE/    # NAND Flash 驱动 + FTL
│   │   ├── TPAFE5160/     # ADC 驱动
│   │   ├── SD2506/        # RTC 驱动
│   │   ├── RS485/         # RS-485 通信驱动
│   │   ├── NET/           # BSD Socket API 网络抽象层
│   │   │   ├── net_socket.c/h  # Socket API
│   │   │   ├── net_events.c/h  # 芯片边沿事件处理 + 100ms 周期对账
│   │   │   ├── net_listener.c/h # 监听生命周期(请求登记 + 单一重建执行者)
│   │   │   ├── net_pending.c/h  # 阻塞 recv/send 挂起请求表(SEND 二期已落地)
│   │   │   ├── net_select.c/h  # select/poll 多路复用
│   │   │   └── lftpd/          # 轻量 FTP 服务器
│   │   ├── NETCFG/        # 网络配置(/config.ini [network] 段加载/保存)
│   │   ├── UI/            # LVGL UI 组件
│   │   └── dbg_log.h / dbg_cfg.h  # 调试日志(DBG_INFO 等)
│   ├── STM32F4xx_HAL_Driver/  # ST HAL 库
│   └── CMSIS/             # ARM CMSIS
├── Lib/                    # 第三方库
│   ├── dhara/             # NAND FTL 算法
│   ├── FatFs/             # FAT 文件系统
│   └── lvgl/              # 图形库
├── Middlewares/
│   └── Third_Party/FreeRTOS/  # FreeRTOS 内核
├── MDK-ARM/               # Keil 工程
│   ├── STM32F407-Demo.uvprojx  # 工程文件
│   ├── *_probe.py         # 台架探针(TCP 复连 / FTP 中止等)
│   └── startup_stm32f407xx.s  # 启动文件
├── test/                  # 测试代码与脚本
│   ├── 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 侧;@test 入口已迁至 .dsh/skills/serial-boot-test/)
│       ├── ch395f_socket_test.py # Socket 通信测试
│       ├── ftp_test.py / ftp_up_dl_test.py / ftp_regression.py / ftp_integrity_test.py / ftp_capture.py
│       ├── e02_probe.py         # E-02 专项探针
│       ├── latency_peer.py      # 链路时延 PC 对端
│       └── time_sync_server.py  # 时间同步推送服务
├── docs/                   # 项目文档(全量索引见 docs/README.md)
│   ├── README.md           # 文档索引:目录结构 + 推荐阅读顺序 + 全量清单
│   ├── 任务规划/            # 统一待办登记簿(README 排序权威 + 拆分文件)
│   ├── 架构设计/           # 项目架构总览 / 存储架构 / 启动顺序 / 配图流程 / 引用关系图
│   ├── 子系统设计/         # 配置 / 网络 / 墙钟 / 日志 / 运行自检记录 设计说明
│   ├── 网络/               # BSD Socket API 使用指南 + 内部函数调用关系
│   ├── 测试说明/           # 测试标准流程、各模块测试指南、串口助手、烧录复位
│   ├── 代码规范/           # C 代码规范、pre-commit / cppcheck 使用说明
│   ├── 内存管理/           # RAM 使用分析与优化方案 + 快照数据(data/)
│   ├── 问题记录/           # 各模块 Trap Records、专项审计与项目评审报告
│   ├── 环境与部署/         # 环境搭建与部署核对清单
│   ├── UI设计/            # LVGL UI:架构 / 菜单页面 / 制作流程 / 字体 / 模拟器 / 自动化测试 + mockups
│   ├── 硬件平台/           # 网表分析报告与语义图
│   ├── 芯片手册/           # 外部芯片数据手册(只读资料)
│   └── images/             # 文档技术配图(SVG 产物,脚本生成)
├── scripts/                # pre-commit 本地钩子脚本
│   ├── check_coding_standard.py  # 代码规范机械检查
│   └── check_mojibake.py         # U+FFFD 乱码检查
├── simulator/              # LVGL PC 模拟器(CMake + SDL2,与 MCU 共用 UI 源码)
│   ├── CMakeLists.txt     # 模拟器构建脚本
│   ├── main.c             # 模拟器入口(SDL → LVGL → 菜单 → 主循环)
│   ├── sim/               # 平台层(sim_port 显示/输入、net_socket_sim、推流/网口配置 backend)
│   ├── lv_conf.h          # LVGL 配置(1bpp + SDL)
│   ├── i1_to_png.py       # 截图 I1(1bpp) → PNG 转换工具
│   ├── tests/             # 无头回归脚本 + 黄金参考(菜单像素回归 / 内容页黄金参考)
│   └── SDL2/              # SDL2 2.32.10 预编译库
├── tools/                  # 开发工具
│   └── font_gen/          # 中文字体生成工具
├── ui_cn_chars.txt        # 中文字体字符集
├── requirements.txt       # Python 依赖清单(统一 .venv 环境,见 AGENTS.md「Python 环境」)
├── STM32F407-Demo.ioc     # CubeMX 工程文件
├── .pre-commit-config.yaml # pre-commit 钩子配置
├── .gitlint               # commit message 检查规则
├── .dsh/skills/           # DSH 项目级 skill(编译/烧录/串口采集/闭环 + 流程类)
├── .serialtest/           # 串口测试档案(串口端口单一配置源 + 烧录/标记参数)
└── AGENTS.md              # AI 开发规范

构建系统

环境要求

  • Keil MDK-ARM v5 (ARMCC 编译器)
  • Python 3(统一入口为仓库内 .venv,依赖见 requirements.txt,重建方法见 AGENTS.md「Python 环境」)
  • ST-Link 或兼容调试器

编译

# 方式一:命令行编译(推荐;= keil-build skill)
& '.venv\Scripts\python.exe' .dsh\skills\keil-build\scripts\keil_build.py

# 方式二:Keil IDE
# 打开 MDK-ARM\STM32F407-Demo.uvprojx → Build (F7)

退出码:0 = 成功 | 1 = 有警告 | 2+ = 错误

编译日志:MDK-ARM/build_log.txt

烧录

& '.venv\Scripts\python.exe' .dsh\skills\stlink-flash\scripts\stlink_flash.py flash

LVGL PC 模拟器

PC 端 UI 开发调试(无需烧录 MCU,与 MCU 共用 Drivers/BSP/UI/ 源码),详见 docs/UI设计/LVGL模拟器部署与使用说明.md:

& "simulator\build_sim.bat"        # 一键构建(自动探测本机 VS2019/2022/2026 生成器)
# 运行 simulator\build\Debug\lvgl_sim.exe

UI 改动回归门禁(菜单像素回归 + 内容页黄金参考 + 池水位校验):

.venv\Scripts\python.exe simulator/tests/check_menu_rows.py
.venv\Scripts\python.exe simulator/tests/check_content_pages.py

详见 docs/UI设计/UI_自动化测试流程.md。

驱动开发指南

CH395F 以太网

  • 单连接模式:Socket 0 复用监听和数据通道
  • 中断统一处理:所有中断在 net_poll() 中通过 GET_GLOB_INT_STATUS 集中读取清除
  • SPI 事务必须用 ch395f_spi_begin() / ch395f_spi_end() 包裹
  • SPI 分频系数必须为 8(PCB 设计限制)

GD5F2GQ5UE NAND Flash

  • 三层软件栈:FatFS → dhara FTL → NAND 驱动
  • FTL 提供 LBA 映射、磨损均衡、坏块管理、垃圾回收
  • 物理分区:全部 2048 块用于 FTL + FatFS

网络层 (NET)

  • BSD Socket API 抽象:net_socket.h/c
  • 事件处理与周期对账:net_events.c(芯片边沿事件 + 100ms 对账,net_poll() 内分派)
  • 监听生命周期单一所有者:net_listener.c(net_listener_request 只登记意图、net_listener_tick 唯一执行)
  • 阻塞挂起请求表:net_pending.c(recv 一期 / SEND 二期已落地;调用方铁律 sent < len)
  • select/poll I/O 多路复用:net_select.h/c
  • 线程安全通过消息队列(netMsgQueue)实现
  • 所有 CH395F 操作在 netTask 中串行处理
  • 网口配置保存后经 SYS_EVT_NET_RECONFIG 按网络代次号重建监听(新 IP 免重启生效)

时间子系统

  • SD2506 RTC 提供初始时间
  • sys_clock 将 RTC 时间转为 Unix epoch 墙钟基准
  • timeSyncTask 通过 TCP 同步墙钟时间

自动化测试

启动测试

# 一键测试:串口捕获 → 烧录 → 日志校验(2026-09-20 起为纯 Python 标准库实现)
& '.venv\Scripts\python.exe' .dsh/skills/serial-boot-test/scripts/run_boot_test.py

退出码:0 = PASS | 1 = FAIL | 2 = 错误

测试模块

模块 测试文件 说明
CH395F 硬件 ch395f_test_task.c SPI 通信、寄存器读写
NAND Flash gd5f_test_task.c 页读写、块擦除、ECC
网络层 net_test_task.c BSD Socket、TCP/UDP
RTC sd2506_test_task.c 时间读写、温度、电池
存储性能 storage_test_task.c FTL/FatFS 读写速度

主机端测试脚本(Python)

脚本 说明
ch395f_socket_test.py Socket 通信测试
ftp_test.py FTP 服务器基础测试
ftp_up_dl_test.py FTP 上传/下载测试
ftp_regression.py FTP 功能回归(会话流程全序列)
ftp_integrity_test.py FTP 传输完整性压测(多轮 SHA-256 校验)
ftp_capture.py FTP 流量抓取
time_sync_server.py 时间同步推送服务(PC → 板子)

串口调试

通过仓库内置 Python 串口助手(.dsh/skills/serial-assistant/)自主读取 USART1 串口打印:

  • 端口配置:.serialtest/config.json(单一配置源)
  • 用法详见 docs/测试说明/串口助手使用指南.md,设计见 docs/测试说明/串口助手设计说明.md

开发规范

源码编辑安全

铁律:绝不用 Get-Content / Set-Content / cmd 重写含中文的源码文件,会导致不可逆乱码。

  • 改代码只用 Edit 工具(精确子串替换)
  • 发现乱码先评估能否用 Edit 修复,不要急着 git checkout

CubeMX 生成文件

  • Inc/ 和 Src/ 中的文件带有 USER CODE BEGIN/END 标记
  • 自定义代码必须写在这些区域之间
  • Drivers/BSP/ 下的驱动文件为纯手工代码,不受 CubeMX 保护

编译验证

所有代码修改后必须编译通过(0 错误 0 警告)才能提交。

新增文件

新文件需手动添加到 Keil MDK 工程才能编译。

自动化代码审查(pre-commit)

每次 git commit 自动执行检查,任一失败即拦截提交:

  • 行尾空格 / 文件尾换行(自动修复)
  • 大文件 / 冲突标记 / YAML 语法(拦截)
  • cppcheck 静态分析:warning / performance / portability / style 四类,发现问题即拦截
  • 代码规范检查:头文件保护宏、命名(宏大写/_t 后缀)、函数注释、default 分支、禁用 strcpy/sprintf/goto/Tab 等(规范 V1.0 可机械校验项)
  • U+FFFD 乱码(拦截,不可逆损坏)
  • commit message 格式(gitlint,拦截)

本地钩子脚本:scripts/check_coding_standard.py、scripts/check_mojibake.py(由 .pre-commit-config.yaml 引用)。

# 新机器启用钩子
pre-commit install
# 全库扫描(配置变更后验证)
pre-commit run --all-files

详见 docs/代码规范/pre-commit使用说明.md 与 docs/代码规范/cppcheck使用说明.md。

关键文件索引

文件 说明
Src/main.c 程序入口,CubeMX 生成 + USER CODE 区域
Src/freertos.c FreeRTOS 任务创建
App/app/app_main.c 应用初始化流程编排
App/task/net_task.c 网络任务主循环
App/app/sys_events.h 系统就绪事件定义
App/app/app_cfg.h 功能裁剪的决策占位说明(当前无宏;原未接线占位开关 2026-10-22 已删)
Drivers/BSP/CH395F/ch395f.c 以太网控制器驱动
Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c NAND Flash 驱动
Drivers/BSP/NET/net_socket.c BSD Socket API
Drivers/BSP/NET/net_events.c 芯片边沿事件处理 + 周期对账
Drivers/BSP/NET/net_listener.c 监听生命周期(单一重建所有者)
App/algo/prot_elm.h L3 保护元件框架(判据消费入口)
.dsh/skills/keil-build/scripts/keil_build.py 编译脚本(@build)
.dsh/skills/serial-boot-test/scripts/run_boot_test.py 自动化测试脚本

已知问题

详见 docs/问题记录/ 目录:

  • CH395F_Trap_Records.md — 以太网控制器已知陷阱
  • GD5F2GQ5UE_Trap_Records.md — NAND Flash 已知陷阱
  • SD2506_Trap_Records.md — RTC 已知陷阱

文档

📚 全量文档索引见 docs/README.md(目录结构 + 推荐阅读顺序 + 按角色导航)。

文档 说明
docs/README.md 文档索引(全量清单 + 阅读顺序 + 新增文档约定)
docs/架构设计/项目架构总览.md 项目全景架构(六层分层 + 任务/就绪屏障 + 启动时序 + 存储/网络/UI 栈 + 目录组织)
docs/环境与部署/项目部署环境要求.md 部署环境要求(开发机 / 目标板 / 网络与现场 / 远端客户端)+ 分步安装命令 + 下载来源速查 + 验收清单
docs/架构设计/STM32F4-Base存储架构说明.md 三层存储软件栈详解(FatFS → dhara FTL → NAND)
docs/架构设计/项目启动顺序管理.md Event Flags 就绪屏障设计
docs/子系统设计/系统墙钟时间维护说明.md RTC + 墙钟时间子系统
docs/子系统设计/网络配置说明.md 网口设置页配置(UI 可改的 IP/掩码/网关/MAC:持久化 + 立即生效 + 页面操作)
docs/网络/BSD_Socket_API_使用指南.md BSD Socket API 使用指南(net_socket / net_select:线程安全 / 快速开始 / TCP / UDP / I/O 多路复用 / 事件回调 / API 参考 / 常见问题)
docs/网络/Net层阻塞模型架构设计.md NET 阻塞模型(挂起请求表五路语义,recv 一期 / SEND 二期已落地)
docs/网络/网络自愈架构设计.md 网络自愈架构(监听重建 / 沉降隔离 / 周期对账)
docs/子系统设计/IEC104上行设计说明.md IEC 60870-5-104 上行(:2404 监听,B4)
docs/子系统设计/ADC采样节拍设计说明.md TIM3 1kHz 采样节拍(两片转换器同源硬件驱动)
docs/UI设计/UI_设计架构.md LVGL UI 系统架构(菜单 / 内容页 / 内存预算)
docs/UI设计/菜单页面设计.md 菜单导航行为、数据流与内容页设计
docs/UI设计/UI_界面制作流程.md 参考图 → 设计规格 → LVGL 代码管线(P0~P4 门禁)
docs/UI设计/UI_中文字体生成与配置.md 中文字体生成与配置
docs/UI设计/LVGL模拟器部署与使用说明.md LVGL PC 模拟器部署
docs/UI设计/UI_自动化测试流程.md UI 回归门禁(脚本 + 池水位常量 + 黄金参考更新)
docs/代码规范/嵌入式C语言代码规范_V1.0.md C 语言代码规范
docs/代码规范/pre-commit使用说明.md 自动化代码审查部署与使用
docs/代码规范/cppcheck使用说明.md cppcheck 规则、配置与误报抑制
docs/测试说明/自动化测试流程.md 构建 → 烧录 → 串口校验闭环
docs/测试说明/ 各模块测试指南(CH395F / NAND / FTP / RTC / 串口调试)
docs/测试说明/测试开发标准流程.md / docs/测试说明/测试文档模板规范.md 测试开发流程与文档模板
docs/问题记录/ 已知陷阱与解决方案(CH395F / NAND / RTC)
docs/芯片手册/ 硬件数据手册

许可证

本项目为私有项目,未经授权不得分发。

S
Description
No description provided
Readme 216 MiB
Languages
C 88.3%
C++ 5.8%
Python 5.5%
Assembly 0.2%
PowerShell 0.1%