C++在单片机上怎么移植LwIP协议栈实现裸机TCP/IP通信

风杰小哥_8288

风杰小哥_8288

2026-10-30

620人浏览

原创

裸机环境下不能直接用标准LwIP移植包,因其默认依赖POSIX接口(如select、pthread)和完整C库,而裸机单片机仅提供最小libc且无OS抽象层;必须关闭多线程相关选项(NO_SYS=1、LWIP_NETCONN=0等),手动实现sys_now(),用状态机+定时轮询替代阻塞调用,并确保DMA收发与pbuf管理正确。

c++在单片机上怎么移植lwip协议栈实现裸机tcp/ip通信

为什么裸机环境下不能直接用标准LwIP移植包

LwIP 官方提供的 ports 目录里确实有 unix、win32 等适配,但没有“裸机单片机”这一类——它默认依赖 POSIX 接口(如 select()、pthread、sys/time.h)和 C 标准库的完整实现。而 Cortex-M3/M4 常见开发环境(如 Keil、IAR、GCC + CMSIS)通常只提供最小 libc(如 newlib-nano),不带线程/信号量/系统时钟抽象层。

关键矛盾点在于:LwIP 的核心调度模型是「轮询 + 超时事件驱动」,但它把底层定时器、网卡收发、中断同步都交给了移植层(sys_arch.c 和 ethernetif.c)实现。你必须亲手填平这三块:

  • sys_now():必须返回毫秒级单调递增时间戳,不能靠 HAL_GetTick() 直接返回(它可能被 HAL_Delay 阻塞或受 SysTick 重载影响)
  • sys_sem_new()/sys_mbox_new():裸机没 OS,得用 CMSIS osSemaphoreId_t(如果用了 CMSIS-RTOS 封装)或纯自旋+标志位模拟;但更常见的是直接禁用 LwIP 的多线程模式(LWIP_NETCONN=0、LWIP_TCPIP_CORE_LOCKING=0)
  • low_level_input():必须在以太网 DMA 中断里调用 ethernetif_input(),且确保 pbuf 不被复用——很多初学者在这里触发 double-free 或内存踩踏

如何配置 LwIP 让它在无 OS 下跑起来

裸机移植的本质是「关掉所有需要 OS 支持的模块」,不是硬扛线程安全。推荐最小可行配置(基于 LwIP 2.1.x):

  • 关闭 TCP/IP 线程:LWIP_TCPIP_CORE_LOCKING=0、LWIP_TCPIP_THREAD=0、LWIP_NETCONN=0
  • 关闭动态内存:MEMP_MEM_MALLOC=1(用 mem_malloc 替代 pool 分配),同时设 MEMP_NUM_PBUF=16、MEMP_NUM_TCP_SEG=8(根据 RAM 大小调整)
  • 启用 NO_SYS 模式:NO_SYS=1,此时 sys_arch.c 只需实现 sys_now() 和空桩函数(sys_sem_new() 返回 NULL 即可)
  • 网卡驱动必须支持零拷贝接收:DMA 接收完成中断中,用 pbuf_alloc(PBUF_RAW, len, PBUF_POOL) 分配 pbuf,再 memcpy 数据过去;切勿用 PBUF_REF 指向 DMA buffer——DMA 续传会覆盖未处理完的数据

示例 lwipopts.h 关键片段:

#define NO_SYS                      1
#define LWIP_SOCKET                 0
#define LWIP_NETCONN                0
#define LWIP_TCPIP_CORE_LOCKING     0
#define MEMP_MEM_MALLOC             1
#define MEM_SIZE                    (16*1024)
#define MEMP_NUM_PBUF               16
#define PBUF_POOL_SIZE              16

STM32 + ETH 外设移植最常卡住的三个地方

不是编译不过,而是 ping 通但无法建立 TCP 连接,或者 connect 后立即 RST。问题往往藏在硬件交互细节里:

C++14
C++14

C++14 对 C++11 的修正与增强版本,适合旧系统维护和较老工具链兼容。

下载
  • ETH->DMABMR |= ETH_DMABMR_SR 必须在初始化最后执行——很多例程把它放在 DMA 启动前,导致 descriptor 未就绪,收包中断永不触发
  • phy_init() 后必须等 ETH->MACSR & ETH_MACSR_MII 置位再读 PHY 寄存器,否则 PHY_BSR_LINK_STATUS 总是 0
  • 发送时若用 ethernet_output(),必须确保 pbuf chain 总长 ≤ MTU(默认 1500),否则 LwIP 自动分片——但裸机没 IP 分片重组能力,对方收到 fragment 就丢弃;解决办法是提前检查 pbuf_clen(p) 并截断或拒绝

一个典型调试技巧:在 tcp_input() 开头加 if (tcphdr->dest != htons(80)) return;,先锁定 HTTP 流量,排除其他协议干扰。

裸机下怎么发 HTTP 请求又不卡死主循环

没有 socket 阻塞等待,只能靠状态机 + 定时轮询。不要试图封装成阻塞式 API,那只会让代码变脆。

  • 用 tcp_new() 创建 PCB 后,注册 connected 回调,在里面发 GET 请求;再注册 recv 回调处理响应
  • 主循环里每 10ms 调用一次 sys_check_timeouts()(LwIP 内部超时管理)和 tcp_tmr()(TCP 定时器)
  • 发送缓冲区满时,tcp_write() 返回 ERR_MEM,此时应暂停发送、等待 sent 回调触发后再继续——不能重试或忽略
  • 务必在 sent 回调里调用 tcp_output(),否则数据卡在 write queue 不发出

容易被忽略的是:LwIP 的 tcp_tmr() 必须按严格周期调用(建议 250ms),否则重传、保活、窗口更新全失效。别指望靠 “只要发包就调一次” 来省事。

C++免费学习笔记(深入):立即使用
在学习笔记中,你将探索 C++ 的入门与实战技巧!

相关专题

更多
c++和c语言的区别有哪些
c++和c语言的区别有哪些

c++和c语言的区别:1、面向对象编程(OOP)支持不同;2、新增特性不同;3、标准库不同;4、编译方式不同;5、命名空间不同等等。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.14

2268

9

c++和python学习顺序推荐
c++和python学习顺序推荐

一般建议先学习C++,再学习Python,因为这样可以逐步从较为底层的编程语言向更高级的语言过渡。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

1039

6

python和c++学习性价比分析
python和c++学习性价比分析

Python易于学习,广泛应用于Web开发、数据科学和人工智能等领域,但性能较低。C语言性能高,适用于对性能要求较高的场景,如游戏开发和系统编程,但学习曲线陡峭,错误处理复杂。想了解更多python的相关内容,可以阅读本专题下面的文章。

2024.03.14

447

5

c语言和c++一样吗
c语言和c++一样吗

c语言和c++是两种不同的编程语言,虽然有相似之处,但存在显著差异。c语言专注于过程式编程和系统级开发,以简洁、高效著称。c++作为c语言的超集,引入了面向对象编程,增强了代码组织和管理能力,但学习曲线也更陡峭。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

327

5

c语言和c++先学哪个好
c语言和c++先学哪个好

初学者选择学习c语言还是c++语言,需要根据个人学习目标、背景以及编程兴趣和预期应用方向来决定。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

426

5

c语言和c++的区别和联系
c语言和c++的区别和联系

c语言和c++是计算机科学领域应用广泛的编程语言。虽然它们有着相似的基础,但它们在语言类型、语法功能和内存管理方面存在着显著差异。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

2024.03.14

600

5

c++软件中文更改教程
c++软件中文更改教程

对于 ide,可通过打开设置,找到语言设置,选择中文,并保存更改。对于非 ide 应用程序,可查找设置或选项,选择语言设置,更改为中文,并保存更改。想了解更多c++的相关内容,可以阅读本专题下面的文章。

2024.03.21

1429

9

python和java和c++学习性价比分析
python和java和c++学习性价比分析

Python以其易学性、丰富的库和活跃的社区而著称,适合数据科学、人工智能和Web开发。Java以其跨平台性、企业级应用开发和Android应用开发而闻名。C++以其底层控制能力、高效性能和游戏开发而著称。选择哪种语言取决于个人兴趣、职业方向和特定需求。想了解更多python和java和c++的相关内容,可以阅读本专题下面的文章。

2024.03.22

1237

7

c++和c语言学习顺序推荐
c++和c语言学习顺序推荐

对于初学者,建议先学习C语言,掌握编程基础后再转入C++,便于理解面向对象编程概念。有编程经验者可直接学习C++,快速接触高级编程技术。想了解更多c++和c语言的相关内容,可以阅读本专题下面的文章。

2024.03.25

1325

9

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
C++ Core Guidelines
C++ Core Guidelines

共0课时 | 0人学习

C++ Reference
C++ Reference

共0课时 | 0人学习

C++ 官方标准说明
C++ 官方标准说明

共0课时 | 0人学习