LWIP移植和裁剪
1. lwIP源码目录结构
lwIP源码目录中包括doc、src、test文件夹和其他文件,其中src文件夹是lwIP的重点,里面包含了lwIP的源码

src源码文件夹如下示,由api、core、include、netif这4个文件夹组成
+---src
| +---api //协议栈sequentialAPI和socket API两种接口函数的源码
| +---core //lwIP内核源码
| +---include //lwIP使用到的头文件
| | +---lwip
| | +---netif
| | \---posix
| \---netif //与网络底层接口有关的文件
- api文件夹:LwIP为用户提供 协议栈sequentialAPI 和 socket API 这两种高级API接口。它们实现的原理都是通过引进邮箱和信号量等通信与同步机制,来实现对内核中raw/callback API函数的封装和调用。也就是说,要使用这两种API,必须基于底层操作系统提供的邮箱和信号量机制,必须要在开发板上移植好操作系统
- core文件夹:是LwIP内核源代码,包含IP、ICMP、IGMP、TCP、UDP等核心协议以及建立在它们基础上的DNS、DHCP、SNMP等上层应用协议。内核源代码可以单独运行,且不需要操作系统的支持
- include文件夹:LwIP使用的各种头文件。与各源码目录相对应
- netif文件夹:主要包含了与底层网络接口相关的文件
2. lwIP移植
将lwIP源码添加到工程中,并添加或修改部分文件
2.1 网卡驱动相关移植
- 添加lwip.h和lwip.c文件(以STM32 HAL库为例)
此文件是将lwIP源码和以太网驱动库结合起来的桥梁
/********** lwip.h ***********/
extern ETH_HandleTypeDef heth;
/* LWIP init function */
void MX_LWIP_Init(void);
#if !WITH_RTOS //如果不带操作系统,则需要在lwip.c中实现以下函数
/* 来从以太网缓冲区读取接收到的数据包;发送数据包到lwIP堆栈进行处理 */
void MX_LWIP_Process(void);
#endif /* WITH_RTOS */
MX_LWIP_Init()函数实现源码在LWIP网卡实现原理一文有详细介绍
- 添加ethernetif.h和ethernetif.c这两个文件
此文件完成外设ETH初始化
/********** ethernetif.h ***********/
//完成硬件(STM32->ETH)相关的外设初始化
err_t ethernetif_init(struct netif *netif);
//完成以太网底层数据接收任务
void ethernetif_input(void const * argument);
//用于检测网线状态(link状态)
void ethernetif_set_link(void const *argument);
//当link状态发生改变时,会调用下面的函数
void ethernetif_update_config(struct netif *netif);
//当用户需要监听link状态时,需要自己实现以下函数接口
void ethernetif_notify_conn_changed(struct netif *netif);
//lwIP内核的时间基准,以HAL库的systick的时基为准
u32_t sys_jiffies(void);
u32_t sys_now(void);
以上部分函数实现源码在LWIP网卡实现原理一文有详细介绍
2.2 操作系统相关移植
如果需要使用操作系统,则要添加sys_arch.h和sys_arch.c文件
- 添加sys_arch.h文件
该文件定义了4中数据类型:信号量、互斥信号、消息邮箱和线程ID
//由于CMSIS的不断发展,已经出现多个版本,因此在移植的时候,就需要关注CMSIS版本
//要确保在lwIP中使用的操作系统的数据类型定义和CMSIS保持一致
#if (osCMSIS < 0x20000U)
#define SYS_MBOX_NULL (osMessageQId)0
#define SYS_SEM_NULL (osSemaphoreId)0
typedef osSemaphoreId sys_sem_t;
typedef osSemaphoreId sys_mutex_t;
typedef osMessageQId sys_mbox_t;
typedef osThreadId sys_thread_t;
#else
#define SYS_MBOX_NULL (osMessageQueueId_t)0
#define SYS_SEM_NULL (osSemaphoreId_t)0
typedef osSemaphoreId_t sys_sem_t;
typedef osSemaphoreId_t sys_mutex_t;
typedef osMessageQueueId_t sys_mbox_t;
typedef osThreadId_t sys_thread_t;
#endif
#ifdef __cplusplus
}
#endif
- 添加sys_arch.c文件(需要实现的函数如下表所示)
该文件定义了sys.h头文件中声明的关于信号量、消息邮箱和创建线程相关的操作函数

2.3 配置选项相关设置
由于使用了操作系统,因此需要在以下文件中更改操作系统相关宏定义
- 更改lwipopts.h中的WITH_RTOS宏定义为1
/* STM32CubeMX Specific Parameters (not defined in opt.h) */
/* Parameters set in STM32CubeMX LwIP Configuration GUI */
/* ----- WITH_RTOS enabled (Since FREERTOS is set) ----- */
#define WITH_RTOS 1
- 更改opt.h中的NO_SYS宏定义为0
#if !defined NO_SYS || defined __DOXYGEN__
#define NO_SYS 0
#endif
3. lwIP裁剪
使用STM32CuebMX可以非常方便的对lwIP进行裁剪和配置,根据需要使用的功能使能或者关闭相应的功能

如果不使用STM32CuebMX进行裁剪和配置,也可以在opt.h和lwipopts.h两个头文件中根据需要对相应功能的宏定义进行使能或者失能

















