lwIP TCP/IP 协议栈笔记之八: 无操作系统移植

目录

1. lwIP添加到工程

2. 添加头文件

3. 修改网卡驱动

4. lwIP 时基

5. 协议栈初始化

6. 获取数据包

6.1 查询方式

6.2 中断方式

7. ping 命令和ipconfig命令


1. lwIP添加到工程

lwIP TCP/IP 协议栈笔记之八: 无操作系统移植_第1张图片

如上图,把源码中src 添加到工程,并添加LwIP 头文件路径。比较简单,不做赘述

2. 添加头文件

lwipopts.h、cc.h、pref.h,并放入 新建的/arch 目录。

在之前有说明相关的配置,这里直接从“contrib-2.1.0 官方例程中拷贝,并修改。

lwIP TCP/IP 协议栈笔记之八: 无操作系统移植_第2张图片

3. 修改网卡驱动

参考contrib-2.1.0\examples\ethernetif 修改。

4. lwIP 时基

实现sys_now()函数来获取系统的时钟,以毫秒为单位,LwIP 通过两次获取的时间就能判断是否有超时,从而让内核去处理对应的事件。一般用滴答定时器产生1ms的基准,并关联该函数。

5. 协议栈初始化

使用LwIP,那就必须先将协议栈初始化,我们就创建一个函数,在函数中初始化协议栈,注册网卡,设置主机的IP 地址、子网掩码、网关地址等。

挂载网卡的函数netif_add()。注意器

void LwIP_Init(void)
{
  /* IP addresses initialization */
  /* USER CODE BEGIN 0 */
#ifdef USE_DHCP
  ip_addr_set_zero_ip4(&ipaddr);
  ip_addr_set_zero_ip4(&netmask);
  ip_addr_set_zero_ip4(&gw);
#else
  IP4_ADDR(&ipaddr,IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3);
  IP4_ADDR(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3);
  IP4_ADDR(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3);
#endif /* USE_DHCP */
  /* USER CODE END 0 */
    
  /* Initilialize the LwIP stack without RTOS */
  lwip_init();
  
  /* add the network interface (IPv4/IPv6) without RTOS */
  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);

  /* Registers the default network interface */
  netif_set_default(&gnetif);

  if (netif_is_link_up(&gnetif))
  {
    /* When the netif is fully configured this function must be called */
    netif_set_up(&gnetif);
  }
  else
  {
    /* When the netif link is down this function must be called */
    netif_set_down(&gnetif);
  }

/* USER CODE BEGIN 3 */

/* USER CODE END 3 */
}

  netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &ethernet_input);   -->  ethernet_input()

 

6. 获取数据包

获取数据包的方式有两种,一种是查询方式,另一种是中断方式。查询方式通过主函数的while 循环进行周期性处理,去获取网卡中是否接收到数据包,然后递交给上层协议去处理,而中断方式则不一样,在网卡接收到一个数据包的时候,就触发中断,通知CPU 去处理,这样子效率就会高很多,特别是在操作系统环境下,我们都采用中断方式去获取数据包。

方式需底层驱动配置支持,在初始化的时候,如果网卡接收模式被配置为ETH_RXINTERRUPT_MODE,则表示使用
中断方式获取数据包,而如果网卡接收模式被配置为ETH_RXPOLLING_MODE 则表明用查询方式获取数据包。

6.1 查询方式

使用查询方式获取数据包的时候,我们只需要在程序中周期性调用网卡接收函数即可


int main(void)
{
  //板级外设初始化
  BSP_Init();
  
  //LwIP协议栈初始化
  LwIP_Init();  
  
  while (1)
  {
    //调用网卡接收函数
    ethernetif_input(&gnetif);
  
    //处理LwIP中定时事件
    sys_check_timeouts();
  }
}

6.2 中断方式

中断方式来接收数据,当接收完成的时候,就通知CPU 来处理即可,效率会比较高

int flag = 0;
int main(void)
{
  //板级外设初始化
  BSP_Init();
  
  //LwIP协议栈初始化
  LwIP_Init();  
  
  while (1)
  {
    if(flag)
    {
      flag = 0;
      //调用网卡接收函数
      ethernetif_input(&gnetif);
    }
    //处理LwIP中定时事件
    sys_check_timeouts();
  }
}
void ETH_IRQHandler(void)
{

  HAL_ETH_IRQHandler(&heth);
  
}

/**
  * @brief  Ethernet Rx Transfer completed callback
  * @param  heth: ETH handle
  * @retval None
  */
extern int flag ;

void HAL_ETH_RxCpltCallback(ETH_HandleTypeDef *heth)
{
  flag = 1;
//  LWIP_Process();
}

7. ping 命令和ipconfig命令

https://blog.csdn.net/XieWinter/article/details/99962809

执行“arp -a”命令,可以看到电脑主机的ARP 表,我们开发板的IP地址与MAC 地址都正确出现在ARP 表。

 

总结:无操作系统移植相对比较简单,需要主要该方式只能使用lwIP raw API接口

     例程:https://download.csdn.net/download/xiewinter/11588610

 

你可能感兴趣的:(TCP/IP,STM32,嵌入式开发,LWIP)