LWIP移植和裁剪

1. lwIP源码目录结构

lwIP源码目录中包括doc、src、test文件夹和其他文件,其中src文件夹是lwIP的重点,里面包含了lwIP的源码

LWIP应用开发|LWIP移植和裁剪_lwip

src源码文件夹如下示,由api、core、include、netif这4个文件夹组成

+---src
|   +---api				//协议栈sequentialAPI和socket API两种接口函数的源码
|   +---core			//lwIP内核源码
|   +---include			//lwIP使用到的头文件
|   |   +---lwip
|   |   +---netif
|   |   \---posix
|   \---netif			//与网络底层接口有关的文件
  • api文件夹:LwIP为用户提供 协议栈sequentialAPIsocket 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头文件中声明的关于信号量、消息邮箱和创建线程相关的操作函数

LWIP应用开发|LWIP移植和裁剪_stm32cubemx_02

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进行裁剪和配置,根据需要使用的功能使能或者关闭相应的功能

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

LWIP应用开发|LWIP移植和裁剪_#endif_04