lwip在stm32f4上的移植

简要记录lwip在stm32f4上的移植步骤:

最简单的lwip移植主要是底层数据收发硬件接口的实现以及配置,在此处主要是ethernetif.c ethernetif.h以及配置文件lwipopt.h的修改

1. main函数

struct netif gnetif;

static void SystemClock_Config(void);
static void BSP_Config(void);
static void Netif_Config(void);
int main(void)
{
    HAL_Init();
    SystemClock_Config();
    /* Configure the BSP */
    BSP_Config();
    /* Initialize the LwIP stack */
    lwip_init();
    Netif_Config();
    /* tcp echo server Init */
    tcp_echoserver_init();
    /* Notify user about the network interface config */
    User_notification(&gnetif);
    while (1)
    {		
		ethernetif_input(&gnetif);
		sys_check_timeouts();
    }
}

其中Netif_Config()是底层的初始化配置; tcp_echoserver_init()是上层(应用层的配置)

1.1 Netif_Config():

其中netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input);这句实现了初始化,并注册了接收驱动接口。

static void Netif_Config(void)
{
  ip_addr_t ipaddr;
  ip_addr_t netmask;
  ip_addr_t gw;

#ifdef USE_DHCP
  ip_addr_set_zero_ip4(&ipaddr);
  ip_addr_set_zero_ip4(&netmask);
  ip_addr_set_zero_ip4(&gw);
#else
  IP_ADDR4(&ipaddr,IP_ADDR0,IP_ADDR1,IP_ADDR2,IP_ADDR3);
  IP_ADDR4(&netmask,NETMASK_ADDR0,NETMASK_ADDR1,NETMASK_ADDR2,NETMASK_ADDR3);
  IP_ADDR4(&gw,GW_ADDR0,GW_ADDR1,GW_ADDR2,GW_ADDR3);
#endif /* USE_DHCP */
  
  /* Add the network interface */    
  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);
  }
  
  /* Set the link callback function, this function is called on change of link status*/
  netif_set_link_callback(&gnetif, ethernetif_update_config);
}

1.2 tcp_echoserver_init()

体现了tcp server 应用层的基本操作, tcp新建-> 端口绑定->监听->等待数据接收。

void tcp_echoserver_init(void)
{
  /* create new tcp pcb */
  tcp_echoserver_pcb = tcp_new();

  if (tcp_echoserver_pcb != NULL)
  {
    err_t err;
    
    /* bind echo_pcb to port 7 (ECHO protocol) */
    err = tcp_bind(tcp_echoserver_pcb, IP_ADDR_ANY, 7);
    
    if (err == ERR_OK)
    {
      /* start tcp listening for echo_pcb */
      tcp_echoserver_pcb = tcp_listen(tcp_echoserver_pcb);
      
      /* initialize LwIP tcp_accept callback function */
      tcp_accept(tcp_echoserver_pcb, tcp_echoserver_accept);
    }
    else 
    {
      /* deallocate the pcb */
      memp_free(MEMP_TCP_PCB, tcp_echoserver_pcb);
    }
  }
}

2. ethernetif.c中的文件接口,(以下还含有ethernet.c中的函数接口)

主要实现网卡驱动

  • 初始化:

- low_level_init

    该函数实现了硬件网卡设备的初始化,通过调用HAL_ETH_Init(&EthHandle),实现了功能(mac addr,rx mode,speed,media interface(MII)等)和端口(通过调用HAL_ETH_MspInit(heth)实现,当然这个接口需要用户提供,用于初始化与网卡间的GPIO)的初始化

- err_t ethernetif_init(struct netif *netif)

    调用low_level_init实现网卡的基本功能初始化,并初始化struct netif部分功能,如netif->output = etharp_output和netif->linkoutput = low_level_output,以及网卡名。

  • 接收数据:low_level_input->ethernetif_input

- static struct pbuf * low_level_input(struct netif *netif)

        实现将底层收到的数据以链表的形式存放到struct pbuf接口中,返回链表的首地址。 后续需要研究HAL_ETH_GetReceivedFrame(&EthHandle)接收实现。

- void ethernetif_input(struct netif *netif)

       该函数调用low_level_input,将收到的底层数据,通过err = netif->input(p, netif); 发送到lwip协议栈中。其中netif->input函数既是 err_t ethernet_input(struct pbuf *p, struct netif *netif);是通过netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, &ethernet_input);注册的。

  • 发送数据:ethernet_output->low_level_output

- static err_t low_level_output(struct netif *netif, struct pbuf *p)

      该函数通过调用HAL_ETH_TransmitFrame(&EthHandle, framelength);函数将pbuf的数据发送出去。

- err_t ethernet_output(struct netif* netif, struct pbuf* p,const struct eth_addr* src, const struct eth_addr* dst,u16_t eth_type)

      该函数通过调用low_level_output函数将pbuf中的数据发送出去,该函数是lwip协议栈底层发送数据的出口。看程序主要被etharp调用,后续需要细看。

 

你可能感兴趣的:(协议)