1. 项目概述
在嵌入式网络开发中,STM32系列MCU配合LwIP协议栈是常见的解决方案。最近我在一个工业网关项目中遇到了一个典型需求:设备需要同时作为TCP服务端接收本地控制指令,又要作为TCP客户端主动上报数据到云端服务器。这种双角色网络架构在物联网边缘计算场景中非常普遍。
传统单线程裸机方案难以满足这种并发需求,而使用RTOS配合LwIP协议栈则可以优雅地解决问题。本文将分享基于FreeRTOS和LwIP的完整实现方案,重点解析双任务架构设计、关键配置参数以及实际开发中的避坑经验。
2. 环境准备与基础配置
2.1 硬件选型与准备
推荐使用STM32F4/F7/H7系列芯片,这些型号都内置了10/100M以太网控制器(ETH)。以STM32F407为例,其硬件连接如下:
- RMII接口:需要连接REF_CLK(50MHz)、MDIO、MDC、TXD0/TXD1、RXD0/RXD1
- PHY芯片:常用DP83848或LAN8720,需注意复位电路和LED指示灯配置
- 时钟树:确保ETH外设时钟源正确,通常使用外部25MHz晶振通过PLL倍频
硬件调试提示:首次上电时建议先用示波器检查REF_CLK信号,这是以太网通信的基础。如果PHY芯片的nINT/CLKOUT引脚有输出,可以测量其频率验证PHY工作状态。
2.2 软件环境搭建
开发环境需要以下组件:
- HAL库:ST官方提供的硬件抽象层库,建议使用最新稳定版
- LwIP协议栈:V2.1.2或更高版本,已包含在CubeMX中
- FreeRTOS:V10.4.3+,与LwIP集成时需要正确配置sys_arch层
关键配置参数(lwipopts.h):
c复制#define LWIP_ARP 1
#define LWIP_ICMP 1
#define LWIP_TCP 1
#define LWIP_UDP 1
#define LWIP_DHCP 1 // 根据需求选择静态IP或DHCP
#define LWIP_SOCKET 1 // 使用Socket API
#define LWIP_NETCONN 1 // 底层API使能
#define LWIP_NETCONN_FULLDUPLEX 1 // 全双工模式关键配置
// 内存配置(根据芯片调整)
#define MEM_SIZE (16*1024)
#define PBUF_POOL_SIZE 16
#define TCP_WND 2048
#define TCP_SND_BUF 2048
3. 双任务架构设计
3.1 服务端任务实现
TCP服务端任务主要负责监听本地端口并处理客户端连接,其工作流程如下:
- 创建监听socket
- 绑定指定端口(如8080)
- 进入监听状态
- 接受客户端连接
- 为每个连接创建数据收发循环
c复制void tcp_server_task(void *arg)
{
int sock, client_sock;
struct sockaddr_in server_addr, client_addr;
socklen_t addr_len = sizeof(client_addr);
char buf[1024];
// 创建TCP socket
sock = socket(AF_INET, SOCK_STREAM, 0);
// 配置服务端地址
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_family = AF_INET;
server_addr.sin_addr.s_addr = INADDR_ANY;
server_addr.sin_port = htons(8080);
// 绑定并监听
