Files
STM32F4-Base/README.md
T
2026-08-31 17:09:59 +08:00

291 lines
12 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 | 半双工通信 |
## 项目架构
```
┌─────────────────────────────────────────────────────────────┐
│ 应用层 (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) │
└─────────────────────────────────────────────────────────────┘
```
### 启动流程
```
main.c
├─ HAL_Init()
├─ SystemClock_Config() // 168MHz 系统时钟
├─ MX_GPIO/DMA/UART/SPI/I2C_Init() // CubeMX 外设初始化
├─ app_main_init() // 应用层初始化(时间→RS485→NAND→ADC→RTC)
│ ├─ sd2506_init() + sys_clock_init() // 时间子系统优先
│ ├─ rs485_init()
│ ├─ gd5f2gq5ue_init()
│ └─ tpafe5160_init()
├─ 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 # 时间同步任务
│ ├── 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 组件
│ ├── 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.ps1 # 自动化启动测试
│ ├── verify_log.ps1 # 日志校验脚本
│ ├── serial_capture.ps1 # 串口捕获脚本
│ ├── 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 # 存储性能测试
├── docs/ # 项目文档
│ ├── 问题记录/ # 已知陷阱与解决方案
│ ├── 测试说明/ # 测试指南
│ └── 芯片手册/ # 硬件数据手册
├── tools/ # 开发工具
│ └── font_gen/ # 中文字体生成工具
├── STM32F407-Demo.ioc # CubeMX 工程文件
└── AGENTS.md # AI 开发规范
```
## 构建系统
### 环境要求
- **Keil MDK-ARM v5** (ARMCC 编译器)
- **Python 3**(测试脚本)
- **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
```
## 驱动开发指南
### 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 同步墙钟时间
## 自动化测试
### 启动测试
```bash
# 一键测试:构建 → 串口捕获 → 烧录 → 日志校验
powershell -ExecutionPolicy Bypass -File test\run_boot_test.ps1
```
退出码: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 读写速度 |
### 串口调试
通过 `serial-mcp-server` 自主读取 USART1 串口打印:
- 端口配置:`.opencode/serial_config.json`
- 详见 `docs/测试说明/serial-mcp-server_串口调试.md`
## 开发规范
### 源码编辑安全
**铁律**:绝不用 `Get-Content` / `Set-Content` / `cmd` 重写含中文的源码文件,会导致不可逆乱码。
- **改代码只用 Edit 工具**(精确子串替换)
- 发现乱码先评估能否用 Edit 修复,不要急着 `git checkout`
### CubeMX 生成文件
- `Inc/` 和 `Src/` 中的文件带有 `USER CODE BEGIN`/`END` 标记
- 自定义代码必须写在这些区域之间
- `Drivers/BSP/` 下的驱动文件为纯手工代码,不受 CubeMX 保护
### 编译验证
**所有代码修改后必须编译通过(0 错误 0 警告)才能提交。**
### 新增文件
新文件需手动添加到 Keil MDK 工程才能编译。
## 关键文件索引
| 文件 | 说明 |
|------|------|
| `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.ps1` | 自动化测试脚本 |
## 已知问题
详见 `docs/问题记录/` 目录:
- `CH395F_Trap_Records.md` — 以太网控制器已知陷阱
- `GD5F2GQ5UE_Trap_Records.md` — NAND Flash 已知陷阱
- `SD2506_Trap_Records.md` — RTC 已知陷阱
## 文档
- `docs/项目启动顺序管理.md` — Event Flags 就绪屏障设计
- `docs/STM32F4-Base存储架构说明.md` — 三层存储软件栈详解
- `docs/嵌入式C语言代码规范(V1.0).md` — 代码规范
- `docs/测试说明/自动化测试流程.md` — 测试流程说明
- `docs/芯片手册/` — 硬件数据手册
## 许可证
本项目为私有项目,未经授权不得分发。