查看: 3593|回复: 0

[基础] lwip 移植

[复制链接]
  • TA的每日心情
    开心
    2014-5-20 10:01
  • 签到天数: 41 天

    连续签到: 1 天

    [LV.5]常住居民I

    发表于 2017-8-11 13:43:46 | 显示全部楼层 |阅读模式
    分享到:
    一、源码目录结构
           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\n", 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()之后调用


    回复

    使用道具 举报

    您需要登录后才可以回帖 注册/登录

    本版积分规则

    关闭

    站长推荐上一条 /2 下一条



    手机版|小黑屋|与非网

    GMT+8, 2024-5-1 02:40 , Processed in 0.115593 second(s), 18 queries , MemCache On.

    ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

    苏公网安备 32059002001037号

    Powered by Discuz! X3.4

    Copyright © 2001-2024, Tencent Cloud.