Files
STM32F4-Base/docs/测试说明/FTP_Test_Guide.md
2026-08-28 22:02:24 +08:00

169 lines
9.0 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.
# FTP 功能测试指导
> 适用对象STM32F4-Base 上基于 `lftpd` 的 FTP Server 功能验证。
> 配套源码:`Drivers/BSP/NET/lftpd/`、`App/task/net_task.c`、`Src/freertos.c`StartFtpTask
> 关联文档:`CH395F_Test_Guide.md`(网络测试总说明·阶段 8、`NET_Socket_FTP_Support_Plan.md`PASV 改造方案)、`CH395F_Trap_Records.md`。
---
## 1. 概述
- FTP Server`lftpd`)在**默认固件构建中即常驻运行**`Src/freertos.c``StartFtpTask`(默认 `__weak` 实现)直接调用 `lftpd_start("/", 21, &ftp)`,与测试套件选择无关。
- 监听端口 **21**,根目录 `/`(即 NAND 上的 FatFS 卷),**匿名登录**`USER anonymous` / `PASS` 任意)。
- 仅支持 **1 个并发客户端**(控制通道 Socket0 + PASV 数据通道动态 Socket2backlog=1
- 测试分两类:
- **PC 端手测(推荐,覆盖真实 FTP 行为)**:用 `test/` 下 Python 脚本或 GUI 客户端。
- **固件自动化TEST_SUITE_CH395F 阶段 8**TC-NET-801/802/803 文件传输。
---
## 2. 测试环境
### 2.1 硬件与网络
- CH395F 网口经以太网连接到 PC 或同一台交换机。
- PC 网卡与固件 IP **同网段**。固件默认静态 IP **192.168.1.100**(掩码 255.255.255.0PC 可设 192.168.1.x如 192.168.1.77)。
- 启动时 `netTask` 完成 `net_init()` + PHY 稳定(约 >2s`ftpTask` 另有 `osDelay(7000)` 等待后才 `listen`;若 `open_socket` 失败会 `vTaskDelay(3000)` 重试(最多 3 次)。**客户端应在上电约 7s 后、串口出现 `[FTP] waiting for connection...` 再连接。**
### 2.2 软件
- Python 3.x脚本位于 `test/`)。
- 可选 GUI 客户端FileZilla / MobaXterm / lftp。
---
## 3. 编译与运行(固件侧)
- **默认构建即可提供 FTP Server**,无需切换测试套件。
- 任何改动后必须执行 `@build`(即 `MDK-ARM/build.bat`),确认 **0 Error(s) 0 Warning(s)** 再烧录(遵循 AGENTS.md 铁律)。
- 若需跑**自动化 FTP 文件传输用例**:在 `test/test_config.h` 选择 `TEST_SUITE_CH395F`,并在 `test/ch395f_test.h` 打开 `ENABLE_PHASE8_TESTS`(文件传输阶段),重新编译烧录。
- 烧录后打开串口115200bps观察
- `net_init` 完成、PHY link up
- `[FTP] waiting for connection...`(约 3 次重试足够 PHY 稳定);
- 客户端连接后进入 FTP 会话(控制通道 220 欢迎)。
---
## 4. PC 端脚本手测(主要手段)
所有脚本支持 `--host`(默认 `192.168.1.100`)、`--port`(默认 21`test/` 目录运行。
### 4.1 冒烟测试:`ftp_test.py`
- 用途:验证连接、登录、`PWD``PASV``LIST` 基本链路。
- 命令:`python ./test/ftp_test.py --host 192.168.1.100`
- 预期:
- 连接成功并读到 `220` 欢迎;
- `USER anonymous` / `PASS` 返回 `230`
- `PASV` 返回 `227` 并解析出数据端口(或回退 `EPSV`
- `LIST` 返回目录列表;
- `QUIT` 正常关闭。
- 判据:全程无 `[NO RESPONSE]` / `CONNECT FAILED`,且 LIST 返回 `226` 即 PASS。**空卷下 LIST 数据通道为 0 字节属正常**(新格式化卷无文件),不必要求有目录列表输出。
### 4.2 上传 / 下载 / 比对:`ftp_up_dl_test.py`
- 用途:验证 `STOR`/`RETR`/`DELE` 与数据一致性(`TYPE I` 二进制 + `PASV`)。
- 命令:`python ./test/ftp_up_dl_test.py --host 192.168.1.100`
- 流程:登录 → `TYPE I``STOR up_test.dat``LIST` 校验存在 → `RETR up_test.dat` → 逐字节比对 → `DELE` 清理 → `QUIT`
- 预期:`*** MATCH! Upload/Download success. ***`,且 LIST 中出现 `up_test.dat`
- 判据:上传/下载字节数相等且内容逐字节一致。
### 4.3 速度与大数据量:`ftp_speed_test.py`
- 用途:测量上传/下载吞吐,作回归基线,同时验证大文件不丢字节。
- 命令:`python ./test/ftp_speed_test.py --host 192.168.1.100 --size 512`(默认 512KB`--size` 可调)。
- 预期:上传/下载均返回 `226`,回读 `MATCH!`,打印 KB/s。
- 注意:脚本使用 8.3 文件名 `SPEEDTST.DAT`**FTP 仅支持 8.3 短文件名**,见 §8.3以回读比对MATCH为最终判据中间打印的 Sent 字段仅供参考。
- 判据size 一致 + MATCH + 速度稳定(受 SPI2 分频 8 限制,通常约 300~450 KB/s参见 `CH395F_Test_Guide.md` 阶段 5 吞吐基线)。
### 4.4 抓包辅助:`ftp_capture.py`
- 用途:连接/传输过程中抓包,分析 PASV 端口、命令/数据通道交互,用于疑难排查。
- 用法参见脚本内 `--help` / 注释。
---
## 5. GUI 客户端手测(可选)
- **FileZilla**:主机 `192.168.1.100`,端口 21用户 `anonymous`,密码任意;可拖拽上传/下载、浏览目录。
- 要点:使用二进制模式传输;文件名遵守 8.3**一次只连一个客户端**。
---
## 6. 自动化测试TEST_SUITE_CH395F 阶段 8
- 入口:`ENABLE_PHASE8_TESTS` → 文件传输阶段100KB 文件)。
- 用例:
- `TC-NET-801`100KB 文件上发MCU→PC
- `TC-NET-802`100KB 文件下发PC→MCU
- `TC-NET-803`round-trip可选
- 详见 `docs/CH395F_Test_Guide.md` 阶段 8。
---
## 7. 测试清单Checklist
- [ ] 默认构建烧录,串口见 `[FTP] waiting for connection`
- [ ] `ftp_test.py` 冒烟 PASS连接 / 登录 / PASV / LIST
- [ ] `ftp_up_dl_test.py` 上传下载比对 `MATCH`
- [ ] `ftp_speed_test.py` 大文件 `MATCH` + 记录速度基线。
- [ ] 可选GUI 客户端手动上传/下载成功。
- [ ] (可选)阶段 8 自动化 `TC-NET-801/802/803` PASS。
---
## 8. 常见失败与排查(基于已知陷阱)
### 8.1 连接被拒 / 长时间无欢迎
- 确认 PC 与固件同网段、IP 正确;上电后等待约 7sPHY 稳定 + `ftpTask` 延迟)再连。
- 若反复 `open_socket` 失败:见 **TRAP-09**PHY 未稳定;固件已做 3 次重试 + 7s 延迟,仍失败检查网线/交换机)。
### 8.2 PASV 失败 / 数据通道连不上
- 确认 PC 防火墙未阻断高端口PASV 动态端口)。
- **数据通道必须先 `connect` 再发命令**(如 `LIST`/`STOR`),顺序反了会失败(脚本已遵循)。
- **TRAP-11**`net_accept_locked``ESTABLISHED` 状态导致 PASV 失败——需校验 `ESTABLISHED`
### 8.3 STOR 报 FR_INVALID_NAME (err=6)
- **8.3 文件名限制**`upload_test.dat`11+3超过 8.3 → `FR_INVALID_NAME`。改用短名如 `UPLOAD.DAT` / `SPEEDTST.DAT`。这是 FatFS LFN/8.3 约束,非驱动 bug。
### 8.4 大文件传输中途 RST / 速度抖动
- **TRAP-13** / 设计约束CH395F `WRITE_SEND_BUF` 芯片侧吞吐限制,单帧 >1KB 才稳定TCP 背压会"堵一会儿",属正常流控,不丢数据。
- 接收侧 `recv_len` 首包可能较大、次包可能为 0**必须循环读直到连接关闭**(脚本已处理)。
- 若持续 RST检查 **SPI 分频 = 8**PCB 设计限制)、`net_poll()` 周期10ms是否正常、中断是否统一在 `net_poll()` 中经 `GET_GLOB_INT_STATUS` 处理。
### 8.5 路径问题
- **TRAP-12**FatFS 根路径 `/` 前缀由 `to_fatfs_path()` 统一处理;客户端用绝对路径(如 `/UPLOAD.DAT`)即可。
### 8.6 单客户端限制
- FTP 仅接受 1 个并发客户端;上一个会话未 `QUIT` 前,新连接会被拒。每次测完务必 `QUIT` / 断开。
### 8.7 LIST/STOR/RETR 全部 550卷未挂载 / 无 FAT 文件系统
- 根因FTP 服务的是 NAND 上的 FatFS 卷。固件在 `StartDefaultTask` 启动期执行 `f_mount(&fs, "", 1)`(会触发 `disk_initialize``nand_ftl_init`),使卷可用。
- **首启自动建卷**:若 `f_mount` 返回 `FR_NO_FILESYSTEM`(如坏块重建/恢复测试后卷被清空),固件会自动 `f_mkfs`FM_FAT32、无分区表参数与存储测试一致再挂载。该过程上电会多花数秒格式化串口可见 `[FS] no FAT volume, formatting NAND...``[FS] FATFS mounted`
- 若串口见 `[FS] f_mount failed (fr=...)` 且非首次(已建卷仍失败):检查 `f_mkfs` 是否报错(`[FS] f_mkfs failed`),或 NAND 是否存在物理/ECC 错误;必要时用 `TEST_SUITE_STORAGE` 跑一次确认磁盘健康。
---
## 9. 诊断手段(沿用前期测试经验)
- **串口日志 + `DBG_*`**:在 `lftpd.c` / `net_socket` 关键路径加 `DBG_ERROR/INFO` 打印(注意编码安全铁律——只用 Edit 改中文源文件,禁止用 `Get/Set-Content` 整文件重写)。
- **抓包**`ftp_capture.py` 或 Wireshark 过滤 `tcp.port==21`
- **编译验证**`@build` 必须 0/0 再烧录AGENTS.md 铁律)。
- **套件切换**`test/test_config.h``TEST_SUITE_CH395F` / `TEST_SUITE_GD5F` / `TEST_SUITE_STORAGE`(三选一,互斥)。
---
## 10. 参考文档
- `docs/CH395F_Test_Guide.md` —— 网络测试总说明(含阶段 8 文件传输、FTP 陷阱清单)
- `docs/NET_Socket_FTP_Support_Plan.md` —— FTP / PASV Socket 改造方案
- `docs/CH395F_Trap_Records.md` —— CH395F 已知陷阱
- `docs/BSD_Socket_API_使用指南.md` —— BSD Socket API 用法