lwip 移植

一、源码目录结构

       api 、 core、netif、 include

      core下又有IPV4 、 IPV6 、 SNMP 和.c文件

      include下又有IPV4、IPV6、LWIP、netif

      netif下的文件有

      1. ethernetif.c这里主要涉及到具体的硬件

      2.etharp.c 这里有个函数ethernet_input在初始化时被赋给netif 接口卡的input,功能为处理到来的数据,然后分发给arp  ip等等。里面还有就是完成arp方面的更新arp 缓冲什么的。

     3.loopif.c

     4.slipif.c

     5. ppp文件夹

二、开始移植

    1、在keil里新建文件夹,将文件包含进去,然后设置include路径,ok

    2、首先修改opt.h里的 NO_SYS为1,表示无系统,SYS_LIGHTWEIGHT_PROT为0,表示不保护临界区域,开始编译根据错误提示修改

          最终在include文件加下建立arch文件夹里面包含cc.h, arch.h , perf.h, sys_arch.h

      cc.h里包含的内容为

#ifndef __CC_H__
#define __CC_H__
#include "stdio.h"

typedef signed char s8_t;
typedef unsigned char u8_t;
typedef unsigned short u16_t;
typedef signed short s16_t;
typedef unsigned int u32_t;
typedef signed int s32_t;                       // 定义数据类型

typedef u32_t mem_ptr_t;            /* Unsigned 32 bit quantity        */ 定义指针大小

#define PACK_STRUCT_BEGIN __packed
#define PACK_STRUCT_STRUCT 
#define PACK_STRUCT_END
#define PACK_STRUCT_FIELD(x) x      //预编译器有关,为了实现对齐

#define BYTE_ORDER LITTLE_ENDIAN   //定义小端模式

#ifndef LITTLE_ENDIAN
#define LITTLE_ENDIAN 1234     //定义小端
#endif

#ifndef BIG_ENDIAN
#define BIG_ENDIAN 4321         //定义大端
#endif

#ifndef LWIP_PLATFORM_ASSERT      //调试用
#define LWIP_PLATFORM_ASSERT(x)
    do
    {   printf("Assertion "%s" failed at line %d in %s ", x, __LINE__, __FILE__);
    } while(0)
#endif

#ifndef LWIP_PLATFORM_DIAG     //调试用
#define LWIP_PLATFORM_DIAG(x) do {printf x;} while(0)
#endif

#endif /* __CC_H__ */

perf.h里包含的内容为

#ifndef __PERF_H__
#define __PERF_H__

#define PERF_START    /* null definition */   // 没深去弄,你看看,不难
#define PERF_STOP(x)  /* null definition */

#endif /* __PERF_H__ */

 我arch.h sys_arch.h里为空
      3,编译,如果没有问题者开始修改ethernetif.c文件,#if 1 打开底层接口修改low_level_init,  low_level_output,  low_level_input, ethernetif_init函数,

       编译无误,OK忘了,还要修改opt.h里

       #define MEM_ALIGNMENT                   4       //内存对齐

       #define MEM_SIZE                        8*1204

       #define ETHARP_TRUST_IP_MAC             1  //更新arp缓冲列表

三、定时部分

    1,设置一个定时器约为250ms调用tcp.c里的tcp_tmr函数。

        tcp_tmr该函数完成了 连接超时,延迟ACK(捎带确认),持续(persist),保鲜(keep alive),  FIN_WAIT_2,  TIME_WAIT定时功能

    2,如果开启了arp缓冲功能ETHARP_TRUST_IP_MAC ,则需要5s定时调用etharp.c里的etharp_tmr()函数来删除arp表。

四、到这里就是移植完成了,下面写一个简单的例子tcp

   1、首先定义一个struct netif接口,然后调用mem_init(); memp_init(); pbuf_init(); netif_add()初始化,然后调用netif_set_default 和netif_set_up搞定。

   2、

struct tcp_pcb *tcppcb = NULL;
void tcp_app(void)
{
    err_t err = 0;
    struct ip_addr ipaddr;
    IP4_ADDR(&ipaddr, 192,168,1,15);
     tcppcb = tcp_new();
    if(tcppcb == NULL)
        return;
    err = tcp_bind(tcppcb, &ipaddr, 80);
    tcppcb = tcp_listen(tcppcb);

   tcp_accept(tcppcb, tcppcb_accept);
}


static err_t  tcppcb_accept(void *arg, struct tcp_pcb *pcb, err_t err)
{
  struct http_state *hs;

  /* Allocate memory for the structure that holds the state of the connection */
  hs = mem_malloc(sizeof(struct http_state));

  if (hs == NULL)
  {
    return ERR_MEM;
  }

  /* Initialize the structure. */
  hs->file = NULL;
  hs->left = 0;

  /* Tell TCP that this is the structure we wish to be passed for our
     callbacks. */
  //tcp_arg(pcb, hs);

  /* Tell TCP that we wish to be informed of incoming data by a call
     to the http_recv() function. */
  tcp_recv(pcb, tcppcb_recv); //数据接收完毕之后,调用tcppcb_recv函数

  //tcp_err(pcb, conn_err);

 // tcp_poll(pcb, http_poll, 10);
  return ERR_OK;
}

static err_t tcppcb_recv(void *arg, struct tcp_pcb *pcb,  struct pbuf *p, err_t err) //处理接收到得数据

{

char *data;

int32_t ,len=0;

  if (err == ERR_OK && p != NULL)
  {
    /* Inform TCP that we have taken the data */
    tcp_recved(pcb, p->tot_len);

      data = p->payload;
      len = p->tot_len;

}


tcp_write()

LwIP通过调用函数tcp_write()来发送TCP数据。当数据被成功地发送到远程主机后,应用程序将会收到应答从而去调用一个指定的回调函数

tcp_sndbuf()

返回发送队列中可用字节的大小

tcp_sent ()

该函数用于设定远程主机成功接收到数据后调用的回调函数,通常也在函数tcp_listen()之后调用


原文地址:https://www.cnblogs.com/alan666/p/8312146.html