Files
STM32F4-Base/README.md
T

400 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 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 数据, PD3 RD, PD4 CONVST, PD7 BUSY | 高精度 ADC |
| USART1 | 串口 | PA9 TX, PA10 RX | 115200bps 调试串口 |
| 6x LED | GPIO | PC4, PC5, PB1, PB2, PF11, PF12 | 低电平点亮 |
| RS-485 | UART5 | PC12 TX, PD2 RX, PD0 DE | 半双工通信 |
## 项目架构
```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
```
> 更详细的全景架构(六层分层 + 任务与就绪屏障 + 启动时序 + 存储/网络/UI 栈 + 目录组织)见 **`docs/项目架构总览.md`**。
### 启动流程
```
main.c
├─ HAL_Init()
├─ SystemClock_Config() // 168MHz 系统时钟
├─ MX_GPIO/DMA/UART/SPI/I2C_Init() // CubeMX 外设初始化
├─ app_main_init() // 应用层初始化(时间→RS485→NAND→ADC→诊断)
│ ├─ sd2506_init() + sys_clock_init() // 时间子系统优先
│ ├─ rs485_init()
│ ├─ gd5f2gq5ue_init()
│ ├─ tpafe5160_init()
│ ├─ SD2506 诊断(ID/时间/温度/电池)
│ └─ tpafe5160_start_conv_irq() // 首次 ADC 转换
├─ osKernelInitialize()
├─ MX_FREERTOS_Init() // 创建任务和事件组
└─ osKernelStart() // 启动调度器
```
### FreeRTOS 任务
| 任务 | 栈大小 | 优先级 | 职责 |
|------|--------|--------|------|
| defaultTask | 2048 words | Normal | FTL + FatFS 挂载(一次性) |
| netTask | 4096 words | Normal | 网络初始化 + CH395F 轮询 |
| ftpTask | 4096 words | Normal | FTP 服务(等待网络+存储就绪) |
| testTask | 4096 words | BelowNormal | 硬件测试入口 |
| uiTask | 16384 words | BelowNormal | LVGL UI 界面 |
| timeSyncTask | 2048 words | Normal | 墙钟时间同步 |
### 任务启动顺序管理
使用 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()` 阻塞等待,零占用,取代魔法延时和全局变量轮询。
## 目录结构
```
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_main.c/h # 应用初始化入口
│ ├── app_cfg.h # 功能模块编译开关
│ ├── sys_events.h # 系统就绪事件定义
│ ├── sys_clock.c/h # 墙钟时间管理
│ ├── time_sync.c/h # 时间同步任务
│ ├── log/ # 日志(sys_log 运行/自检记录、console_log 控制台单写者)
│ ├── task/ # FreeRTOS 任务实现
│ │ ├── net_task.c/h # 网络任务
│ │ ├── ui_task.c/h # UI 任务
│ │ ├── adc_task.c/h # ADC 任务
│ │ └── rs485_task.c/h # RS-485 任务
│ ├── protocol/ # 通信协议(预留)
│ └── util/ # 工具函数(CRC、环形缓冲等)
├── 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_select.c/h # select/poll 多路复用
│ │ │ └── lftpd/ # 轻量 FTP 服务器
│ │ ├── 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 # 工程文件
│ ├── build.bat # 命令行编译脚本
│ ├── download.bat # 烧录脚本
│ └── 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 # 时间同步推送服务(主机端)
├── docs/ # 项目文档
│ ├── UI 设计/ # LVGL UI:架构 / 菜单页面 / 制作流程 / 字体 / 模拟器 / 自动化测试 + mockups 样机
│ ├── 代码规范/ # C 代码规范、pre-commit / cppcheck 使用说明
│ ├── 问题记录/ # 已知陷阱与解决方案
│ ├── 测试说明/ # 测试指南
│ ├── 芯片手册/ # 硬件数据手册
│ ├── 测试开发标准流程.md # 测试开发标准流程
│ ├── 测试文档模板规范.md # 测试文档模板规范
│ ├── 图形绘制流程.md # 文档配图绘制流程(SVG 生成器 / Mermaid 选型 / 约定 / 检查清单)
│ └── *.md # 存储架构 / 墙钟时间 / 启动顺序等(UI 相关文档在 UI 设计/)
├── 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/ # 中文字体生成工具
│ └── serial_tool/ # Python 串口助手(常驻 daemon + CLI,见 docs/测试说明/串口助手设计说明.md)
├── ui_cn_chars.txt # 中文字体字符集
├── requirements.txt # Python 依赖清单(统一 .venv 环境,见 AGENTS.md「Python 环境」)
├── STM32F407-Demo.ioc # CubeMX 工程文件
├── .pre-commit-config.yaml # pre-commit 钩子配置
├── .gitlint # commit message 检查规则
├── opencode.json # opencode 配置
├── .opencode/ # opencode 本地配置(串口等)
└── AGENTS.md # AI 开发规范
```
## 构建系统
### 环境要求
- **Keil MDK-ARM v5** (ARMCC 编译器)
- **Python 3**(统一入口为仓库内 `.venv`,依赖见 `requirements.txt`,重建方法见 AGENTS.md「Python 环境」)
- **ST-Link** 或兼容调试器
### 编译
```bash
# 方式一:命令行编译(推荐)
MDK-ARM\build.bat
# 方式二:Keil IDE
# 打开 MDK-ARM\STM32F407-Demo.uvprojx → Build (F7)
```
退出码:0 = 成功 | 1 = 有警告 | 2+ = 错误
编译日志:`MDK-ARM/build_log.txt`
### 烧录
```bash
MDK-ARM\download.bat
```
### LVGL PC 模拟器
PC 端 UI 开发调试(无需烧录 MCU,与 MCU 共用 `Drivers/BSP/UI/` 源码),详见 `docs/UI 设计/LVGL模拟器部署与使用说明.md`:
```powershell
& "simulator\build_sim.bat" # 一键构建(自动探测本机 VS2019/2022/2026 生成器)
# 运行 simulator\build\Debug\lvgl_sim.exe
```
UI 改动回归门禁(菜单像素回归 + 内容页黄金参考 + 池水位校验):
```powershell
.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`
- select/poll I/O 多路复用:`net_select.h/c`
- 线程安全通过消息队列(`netMsgQueue`)实现
- 所有 CH395F 操作在 netTask 中串行处理
### 时间子系统
- SD2506 RTC 提供初始时间
- sys_clock 将 RTC 时间转为 Unix epoch 墙钟基准
- timeSyncTask 通过 TCP 同步墙钟时间
## 自动化测试
### 启动测试
```powershell
# 一键测试:串口捕获 → 烧录 → 日志校验(2026-09-20 起为纯 Python 标准库实现)
& '.venv\Scripts\python.exe' test/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_speed_test.py` | FTP 传输速度测试 |
| `ftp_capture.py` | FTP 流量抓取 |
| `time_sync_server.py` | 时间同步推送服务(PC → 板子) |
### 串口调试
通过仓库内置 Python 串口助手(`tools/serial_tool/`)自主读取 USART1 串口打印:
- 端口配置:`.opencode/serial_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` 引用)。
```bash
# 新机器启用钩子
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_main.c` | 应用初始化流程编排 |
| `App/task/net_task.c` | 网络任务主循环 |
| `App/sys_events.h` | 系统就绪事件定义 |
| `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` | 自动化测试脚本 |
## 已知问题
详见 `docs/问题记录/` 目录:
- `CH395F_Trap_Records.md` — 以太网控制器已知陷阱
- `GD5F2GQ5UE_Trap_Records.md` — NAND Flash 已知陷阱
- `SD2506_Trap_Records.md` — RTC 已知陷阱
## 文档
| 文档 | 说明 |
|------|------|
| `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/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/芯片手册/` | 硬件数据手册 |
## 许可证
本项目为私有项目,未经授权不得分发。