TCP可以正常使用

This commit is contained in:
2026-07-19 00:59:56 +08:00
parent fe107ea9af
commit f72d08328f
24 changed files with 5505 additions and 352 deletions

View File

@@ -13,6 +13,13 @@ STM32F4-Base/
├── Drivers/
│ ├── BSP/
│ │ ├── CH395F/ # CH395F 以太网芯片驱动(手写)
│ │ ├── NET/ # BSD Socket API 网络抽象层(手写)
│ │ │ ├── net_config.h # 网络配置宏定义
│ │ │ ├── net_types.h # 类型定义、地址结构、Socket 控制块
│ │ │ ├── net_socket.h # BSD Socket API 头文件
│ │ │ ├── net_socket.c # API 核心实现 + 状态机
│ │ │ ├── net_select.h # select/poll API 头文件
│ │ │ └── net_select.c # select/poll 实现
│ │ ├── GD5F2GQ5UE/ # GD5F2GQ5UE NAND Flash 驱动(手写)
│ │ │ ├── gd5f2gq5ue.h/c # 底层 SPI 驱动
│ │ │ ├── fal_flash_gd5f2gq5ue.c # FAL 设备适配层
@@ -37,6 +44,8 @@ STM32F4-Base/
|---|---|
| `Src/main.c` | 程序入口,初始化序列及主循环 |
| `Drivers/BSP/CH395F/ch395f.c/h` | CH395F 以太网芯片 SPI 驱动 |
| `Drivers/BSP/NET/net_socket.c/h` | BSD Socket API 网络抽象层 |
| `Drivers/BSP/NET/net_select.c/h` | select/poll I/O 多路复用 |
| `Drivers/BSP/GD5F2GQ5UE/gd5f2gq5ue.c/h` | GD5F2GQ5UE NAND Flash SPI 驱动 |
| `Drivers/BSP/GD5F2GQ5UE/fal_flash_gd5f2gq5ue.c` | FAL 设备适配层 |
| `Drivers/BSP/TPAFE5160/tpafe5160.c/h` | TPAFE5160 ADC 并行接口驱动 |
@@ -52,6 +61,29 @@ STM32F4-Base/
- C 标准C99
- 全局宏定义:`USE_HAL_DRIVER, STM32F407xx`
### 命令行编译Agent 使用)
修改代码后必须执行命令行编译验证,编译脚本位于 `MDK-ARM/build.bat`
```
cmd /c "cd /d "工作目录" && build.bat"
```
实际执行示例(从项目根目录):
```
cmd /c "cd /d "D:\Code\DTU 程序\STM32F4-Base\MDK-ARM" && build.bat"
```
**编译结果判读:**
- 退出码 0无错误无警告编译成功
- 退出码 1有警告无错误编译失败警告不可接受需修复
- 退出码 2+:编译失败,需查看 `MDK-ARM/build_log.txt` 定位错误
**UV4.exe 路径:** `C:\Keil_v5\UV4\UV4.exe`
**工程文件:** `MDK-ARM/STM32F407-Demo.uvprojx`
**目标名称:** `STM32F407-Demo`
## 硬件配置
- **主频:** HSE 25MHz → PLL 168MHz (4/168/2)
@@ -96,6 +128,11 @@ HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init()
- **`SET_PHY` 必须在 `INIT_CH395` 之后**,它会复位 MAC/PHY 建立物理链路,不影响已锁定的协议栈参数
- **`CMD_PING_ENABLE` 不需要显式调用**INIT 后默认可用
- 每次 SPI 事务需调用 `ch395f_spi_begin()` / `ch395f_spi_end()` 包裹
- **大数据量收发使用 SPI2 DMA**`ch395f_write_send_buf()``ch395f_read_recv_buf()` 已改造为 DMA 批量传输DMA1_Stream3 RX, DMA1_Stream4 TX命令和配置操作仍使用逐字节轮询
- DMA 缓冲区:`s_spi2_dma_tx_buf[1500]` / `s_spi2_dma_rx_buf[1500]`4 字节对齐
- **TCP 重传参数**`SET_RETRAN_COUNT`默认12次最大20`SET_RETRAN_PERIOD`默认500ms最大1000ms必须在 `INIT_CH395` 之前设置,总重传时间 = 次数 × 周期
- **KeepAlive 参数必须为 500ms 的倍数**`SET_KEEPALIVE_IDLE`默认20000ms`SET_KEEPALIVE_INTVL`默认15000ms单位为 ms且 IDLE 必须 > INTVL均为 500 的倍数;传入非 500 倍数的值会导致未定义行为CH395F 内部定时器异常TCP 连接几秒内 TIMEOUT
- **KeepAlive 默认关闭**:需在 `SINT_STAT_CONNECT` 后调用 `ch395f_set_keepalive_enable(sock, 1)` 启用
## GD5F2GQ5UE 驱动关键点
@@ -124,6 +161,28 @@ HAL_Init() → SystemClock_Config() → MX_GPIO_Init() → MX_USART1_UART_Init()
- 读取时序168MHz 下 GPIO 写操作 + 5个 NOP (~30ns) 覆盖 t10=22ns 和 t14=21ns 要求
- 硬件 RANGE 接 GND → ±5V 量程LSB=152.59µV
## NET 网络层关键点
- **文件结构**`Drivers/BSP/NET/` 下包含 net_config.h、net_types.h、net_socket.h/c、net_select.h/c
- **使用前必须调用** `net_init(ip, mask, gateway)` 初始化网络子系统
- **主循环必须调用** `net_poll()` 轮询所有 Socket 状态,处理中断事件
- **TCP Server 多连接模式**1 个监听 Socket + 最多 7 个数据 Socket
- **select/poll 支持**`net_select()``net_poll_events()` 用于 I/O 多路复用
- **事件回调**:可通过 `net_set_event_cb()` 注册连接/断开/数据到达等事件回调
- **非阻塞模式**`net_recv()` 使用 `NET_MSG_DONTWAIT` 标志,或使用 select/poll
- **字节序转换**:使用 `net_htons()/net_ntohs()/net_htonl()/net_ntohl()` 进行主机序/网络序转换
- **IP 地址转换**`net_inet_addr("192.168.1.100")` 字符串转网络序,`net_inet_ntoa()` 反向转换
- **注意**:新文件需手动添加到 Keil MDK 工程中才能编译
- **RECV 中断是电平触发的**`net_poll()``do { ... } while(0)` 只处理一批中断,由主循环读取数据,避免无限循环导致主循环饿死
- **TCP Server 多连接模式**Socket 0 专职监听Socket 1~7 自动分配
- **多连接模式初始化顺序(关键!遗漏将导致 TCP 连接失败)**
1. `ch395f_set_fun_para(0x02)` — 启用多连接(在 `INIT_CH395` 之前)
2. `ch395f_init()` — 协议栈初始化
3. Socket 0: `SET_PROTO_TCP → SET_SOUR_PORT → OPEN → TCP_LISTEN`
4. **Socket 1~7: `SET_PROTO_TCP → SET_SOUR_PORT相同端口`(不 OPEN**
- 如果不配置数据 Socket 的协议类型和源端口CH395F 不知道哪些 Socket 可用于多连接分配,客户端连接会被静默拒绝(无 CONNECT 中断)
- **TCP Server 单连接模式**Socket 先 `OPEN``SET_PROTO_TCP``SET_SOUR_PORT``OPEN``TCP_LISTEN`;收到 `SINT_STAT_CONNECT` 后 Socket 自动切换为数据通道;`DISCONNECT`/`TIMEOUT` 后需重新 `OPEN``TCP_LISTEN`
## 已知问题
### CH395F 与 RTL8305NBI 自动协商不兼容