一、Lwip首先进行内存分配:
- Mem_init()内存栈起止地址,空闲列表初始化;
- Memp_init()内存池初始化。
两者的详细比较会在https://blog.youkuaiyun.com/weixin_41561640/article/details/113535282,进行了详细的说明
二、内存分配完之后,进行数据包管理:
pbuf_init();
三、LWIP的初始化:
sys_sem_t sem;
tcpip_init(TcpipInitDone, &sem);
四、进行网络配置,设置IP,默认子网掩码,网关等设置:
static struct netif _netif; (1) //网卡芯片
struct ip_addr ipaddr, netmask, gw; (2) //IP地址、子网掩码、网关地址
IP4_ADDR(&gw, 192,168,0,1); (3) 设置IP
IP4_ADDR(&ipaddr, 192,168,0,60); (4) 设置 网关
IP4_ADDR(&netmask, 255,255,255,0); (5) 设置子网掩码
netif_add(&_netif, &ipaddr, &netmask, &gw, NULL, ethernetif_init, ethernet_input); (6) 添加配置
netif_set_default(&_netif); (7) 调用 netif_set_default 函数初始化缺省网络接口,默认网络接口
netif_set_up(&_netif); (8)使能网络接口
(6)ethernetif_init 网络配置:
err_t ethernetif_init(struct netif *netif)
{
netif->name[0] = IFNAME0; //初始化变量 enc28j60 的 name 字段
netif->name[1] = IFNAME1;
netif->output = etharp_output; //IP 层发送数据包函数
netif->linkoutput = low_level_output; //ARP 模块发送数据包函数
low_level_init(netif); //底层硬件初始化函数
return ERR_OK;
}
//接收底层数据的函数,进行分析判断是IP数据包或者ARP数据包进行上传,传到上层进行处理
void ethernetif_input(void *arg) //创建该进程时,要将某个网络接口结构的 netif 结构指
{ //针作为参数传入
struct eth_hdr *ethhdr;
struct pbuf *p;
struct netif *netif = (struct netif *)arg;
while (1)
{
p = low_level_input (netif); // 接收一个数据包
if (p == NULL) // 如果数据包为空,
continue; // 则循环结束,启动下次接收过程
ethhdr = p->payload; // 取得数据包内数据
switch (htons(ethhdr->type)) // 判断数据包类型 注意大小端
{ // 只对 IP 数据包和 ARP 数据包进行处理
case ETHTYPE_IP: // IP 数据包
case ETHTYPE_ARP: // ARP 数据包
if (netif->input(p, netif)!=ERR_OK) // 将数据包发送到上层应用函数
{
pbuf_free(p);
p = NULL;
}
break;
default:
pbuf_free(p);
p = NULL;
break;
} //switch
} //while
} //ethernetif_input 函数
图片展示了LWIP启动时序,大部分函数都是LWIP自带的,主要的移植代码是eth_init()实现初始化以太网接口,启动程序会创建2个线程:tcpip_thread负责LWIP的绝大部分工作(主要是协议栈的解析和系统运行),ethernetif_thread负责从网口接收数据包再交付给tcpip_thread线程进行处理。
本文章转载自 https://my.oschina.net/u/274829/blog/270817
参考文章https://blog.youkuaiyun.com/jiangjunjie_2005/article/details/26051399#t16(建议细看)