From 3f0ea5761c36effb33d2992ecfe44826a5eddda4 Mon Sep 17 00:00:00 2001
From: Wanderingss <1624155937@qq.com>
Date: Wed, 2 Sep 2026 10:06:14 +0800
Subject: [PATCH] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E4=BA=86=E4=B8=80=E4=BA=9B?=
=?UTF-8?q?=E6=9E=B6=E6=9E=84=E5=9B=BE=E7=89=87?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
README.md | 93 ++++++++++++++++++++++++++++--------
docs/系统墙钟时间维护说明.md | 34 ++++++++-----
2 files changed, 94 insertions(+), 33 deletions(-)
diff --git a/README.md b/README.md
index e8197a72..a3d23746 100644
--- a/README.md
+++ b/README.md
@@ -21,22 +21,26 @@
## 项目架构
-```
-┌─────────────────────────────────────────────────────────────┐
-│ 应用层 (App/) │
-│ app_main.c │ net_task.c │ ui_task.c │ time_sync.c │
-├─────────────────────────────────────────────────────────────┤
-│ 驱动层 (Drivers/BSP/) │
-│ CH395F/ │ GD5F2GQ5UE/ │ TPAFE5160/ │ SD2506/ │ RS485/ │ UI/ │
-├─────────────────────────────────────────────────────────────┤
-│ 中间件 (Middlewares/ & Lib/) │
-│ FreeRTOS │ FatFs │ dhara FTL │ LVGL │
-├─────────────────────────────────────────────────────────────┤
-│ HAL 层 (Drivers/STM32F4xx_HAL_Driver/) │
-│ CMSIS (Drivers/CMSIS/) │
-├─────────────────────────────────────────────────────────────┤
-│ 硬件 (STM32F407ZGTx) │
-└─────────────────────────────────────────────────────────────┘
+```mermaid
+flowchart TB
+ subgraph APP["应用层 (App/)"]
+ direction LR
+ A1["app_main.c"] ~~~ A2["net_task.c"] ~~~ A3["ui_task.c"] ~~~ A4["time_sync.c"]
+ 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
```
### 启动流程
@@ -46,11 +50,13 @@ main.c
├─ HAL_Init()
├─ SystemClock_Config() // 168MHz 系统时钟
├─ MX_GPIO/DMA/UART/SPI/I2C_Init() // CubeMX 外设初始化
- ├─ app_main_init() // 应用层初始化(时间→RS485→NAND→ADC→RTC)
+ ├─ app_main_init() // 应用层初始化(时间→RS485→NAND→ADC→诊断)
│ ├─ sd2506_init() + sys_clock_init() // 时间子系统优先
│ ├─ rs485_init()
│ ├─ gd5f2gq5ue_init()
- │ └─ tpafe5160_init()
+ │ ├─ tpafe5160_init()
+ │ ├─ SD2506 诊断(ID/时间/温度/电池)
+ │ └─ tpafe5160_start_conv_irq() // 首次 ADC 转换
├─ osKernelInitialize()
├─ MX_FREERTOS_Init() // 创建任务和事件组
└─ osKernelStart() // 启动调度器
@@ -114,7 +120,8 @@ STM32F4-Base/
│ │ │ ├── net_socket.c/h # Socket API
│ │ │ ├── net_select.c/h # select/poll 多路复用
│ │ │ └── lftpd/ # 轻量 FTP 服务器
-│ │ └── UI/ # LVGL UI 组件
+│ │ ├── UI/ # LVGL UI 组件
+│ │ └── dbg_log.h / dbg_cfg.h # 调试日志(DBG_INFO 等)
│ ├── STM32F4xx_HAL_Driver/ # ST HAL 库
│ └── CMSIS/ # ARM CMSIS
├── Lib/ # 第三方库
@@ -132,20 +139,42 @@ STM32F4-Base/
│ ├── run_boot_test.ps1 # 自动化启动测试
│ ├── verify_log.ps1 # 日志校验脚本
│ ├── serial_capture.ps1 # 串口捕获脚本
+│ ├── 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 # 存储性能测试
+│ ├── 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 # 时间同步推送服务(主机端)
├── docs/ # 项目文档
│ ├── 代码规范/ # C 代码规范、pre-commit / cppcheck 使用说明
│ ├── 问题记录/ # 已知陷阱与解决方案
│ ├── 测试说明/ # 测试指南
│ ├── 芯片手册/ # 硬件数据手册
+│ ├── 测试开发标准流程.md # 测试开发标准流程
+│ ├── 测试文档模板规范.md # 测试文档模板规范
│ └── *.md # 存储架构 / UI 规划 / 墙钟时间 / 启动顺序 / LVGL 模拟器
+├── scripts/ # pre-commit 本地钩子脚本
+│ ├── check_coding_standard.py # 代码规范机械检查
+│ └── check_mojibake.py # U+FFFD 乱码检查
+├── simulator/ # LVGL PC 模拟器(CMake + SDL2)
+│ ├── CMakeLists.txt # 模拟器构建脚本
+│ ├── main.c / sim_port.c/h # 模拟器入口与移植层
+│ ├── lv_conf.h # LVGL 配置(1bpp + SDL)
+│ └── SDL2/ # SDL2 2.32.10 预编译库
├── tools/ # 开发工具
│ └── font_gen/ # 中文字体生成工具
+├── ui_cn_chars.txt # 中文字体字符集
├── STM32F407-Demo.ioc # CubeMX 工程文件
+├── .pre-commit-config.yaml # pre-commit 钩子配置
+├── .gitlint # commit message 检查规则
+├── opencode.json # opencode 配置
+├── .opencode/ # opencode 本地配置(串口等)
└── AGENTS.md # AI 开发规范
```
@@ -177,6 +206,17 @@ MDK-ARM\build.bat
MDK-ARM\download.bat
```
+### LVGL PC 模拟器
+
+PC 端 UI 开发调试(无需烧录 MCU),详见 `docs/LVGL模拟器部署与使用说明.md`:
+
+```powershell
+cd simulator
+cmake -B build -G "Visual Studio 16 2019" -A x64
+cmake --build build --config Debug
+# 运行 simulator\build\Debug\lvgl_sim.exe
+```
+
## 驱动开发指南
### CH395F 以太网
@@ -226,6 +266,17 @@ powershell -ExecutionPolicy Bypass -File test\run_boot_test.ps1
| 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_speed_test.py` | FTP 传输速度测试 |
+| `ftp_capture.py` | FTP 流量抓取 |
+| `time_sync_server.py` | 时间同步推送服务(PC → 板子) |
+
### 串口调试
通过 `serial-mcp-server` 自主读取 USART1 串口打印:
@@ -267,6 +318,8 @@ powershell -ExecutionPolicy Bypass -File test\run_boot_test.ps1
- U+FFFD 乱码(拦截,不可逆损坏)
- commit message 格式(gitlint,拦截)
+本地钩子脚本:`scripts/check_coding_standard.py`、`scripts/check_mojibake.py`(由 `.pre-commit-config.yaml` 引用)。
+
```bash
# 新机器启用钩子
pre-commit install
diff --git a/docs/系统墙钟时间维护说明.md b/docs/系统墙钟时间维护说明.md
index 757b251f..daae1be4 100644
--- a/docs/系统墙钟时间维护说明.md
+++ b/docs/系统墙钟时间维护说明.md
@@ -95,21 +95,29 @@ static volatile uint32_t s_base_unix_secs = UINT32_MAX; /* 基准对应的 Unix
## 6. 初始化流程(`sys_clock_init`)
-```
-Step 1 从 SD2506 读取初始时间 sd2506_get_time(&sd_time)
- ├─ 注意:sd_time.year 已是完整年份(驱动内已 +2000),
- │ 后续换算【不得】再加 2000,否则年份虚增 → Unix 秒数超 uint32 回绕
- └─ 可选校时(见第 9 节 RTC_DEFAULT_INIT_* 宏)
+```mermaid
+sequenceDiagram
+ autonumber
+ participant SC as sys_clock_init
+ participant RTC as SD2506 RTC
+ participant HAL as HAL Tick
-Step 2 将 RTC 时间换算为 Unix epoch 秒数
- ├─ 累计 1970 至当前年份的整年天数(含闰年 366 天判定)
- ├─ 加上当年 1 月至当前月的累计天数
- ├─ 加当月已过天数、时/分/秒
- └─ 用 int64_t 累加,避免中间溢出;结果截断存入 uint32_t(受 2038 限制,见第 12 节)
+ Note over SC,RTC: Step 1 从 SD2506 读取初始时间
+ SC->>RTC: sd2506_get_time(sd_time)
+ RTC-->>SC: sd_time(year 已是完整年份)
+ Note right of SC: 后续换算【不得】再加 2000
否则年份虚增 → Unix 秒数超 uint32 回绕
+ Note right of SC: 可选校时(见第 9 节 RTC_DEFAULT_INIT_* 宏)
-Step 3 建立基准
- s_base_tick = HAL_GetTick();
- s_base_unix_secs = (uint32_t)unix_secs;
+ Note over SC: Step 2 将 RTC 时间换算为 Unix epoch 秒数
+ SC->>SC: 累计 1970 至当前年份的整年天数(含闰年 366 天判定)
+ SC->>SC: 加上当年 1 月至当前月的累计天数
+ SC->>SC: 加当月已过天数、时/分/秒
+ SC->>SC: 用 int64_t 累加,避免中间溢出;结果截断存入 uint32_t(受 2038 限制,见第 12 节)
+
+ Note over SC,HAL: Step 3 建立基准
+ SC->>HAL: HAL_GetTick()
+ HAL-->>SC: 当前 tick
+ Note right of SC: s_base_tick = HAL_GetTick()
s_base_unix_secs = (uint32_t)unix_secs
```
初始化后,所有后续取时都基于 Step 3 的基准推算,不再访问 RTC。