UIP tcp/ip协议栈在uCOS-II下的移植

感谢原作者。

刚完成了uip在ucos下的移植,总结一下,其实uip部分的移植非常的简单,我整整花了2个星期,是因为cs8900的接收部分驱动程序一直没有处理好,由于uip收发都使用uip_buf,cs8900就一直处于要丢弃接收包的状态,而cs8900丢弃包似乎到现在我都没有做好!最后终于自己加了个环形缓冲区,让cs8900基本把rx的所有包收入内存,不作丢弃处理,之后就万事顺利了,希望有那位高人看到这个文章后赐我一个好点的cs8900驱动。

    言归正传,uip的结构非常简单,网卡只需要接收的包填入uip_buf,设置uip_len的长度为包长。然后在uip的轮询循环中检查uip_len是否>0(调用network_device_read()函数),如果uip_len>0说明收到了数据,循环中就分类处理各种协议的请求,如果程序有数据需要发送调用uip_send发送数据,它同样是把数据送入uip_buf,设置uip_len,主循环会在本次循环中把数据送入网卡(调用network_device_send()函数)。因此uip与网卡的接口就network_device_read(), network_device_send()两个函数,一个缓冲uip_buf,一个数据uip_len.当然,真如我前面说的,为了提高效率你可以在中间加入自己的转存缓冲,否则很多包会被丢弃,你可能会看到网络里满是被丢弃和重发的包。

    你的主程序循环需要被uip循环调用,这是通过把你的程序的主循环函数声明为宏UIP_APPCALL来实现的,uip_process里调用这个宏,也就执行了你的程序循环,因此你的程序主体不应该写的太长太繁琐,以免一次循环的时间过长。

    由于uip不处理重发,你的程序必须知道之前发送了什么数据,程序处在什么状态,如果发送uip_rexmit(),程序就需要把上次送出的数据再发送一遍,实现重发。我后面的例子里发送了不同的数据,是为了测试重发的频率。因此程序需要维持一个状态机,我的程序里是example2_state 结构体。

    uip还保持一个计数器,一定时间间隔后,通过uip_poll()调用返回真值,你的程序能获得主动发送数据的机会,同时能对空闲时间进行计数,程序可以选择在空闲太久后关闭连接,以避免死连接。

    另外如果你打算在你的网卡驱动中打开中断,最好别像uip文档的例子那样先初始化设备,后初始化uip,而应该把设备初始化放到最后。有arp协议时,初始化时应该也初始化arp: uip_arp_init()

    下面是我的example程序,在头文件中定义UIP_APPCALL:

#define UIP_APPCALL example2_app

#define UIP_APPSTATE_SIZE sizeof(struct example2_state)

程序的主体:

void example2_init(void) {

    uip_listen(HTONS(2345));

}

void example2_app(void) {

    struct example2_state *s;

    s = (struct example2_state *)uip_conn->appstate;

    if(uip_connected()) {

        s->state = WELCOME_SENT;

        uip_send("Welcome!\n", 9);

        //DBGMSG("app connected \n");

        return;

    }

    if(uip_acked()) {

        switch(s->state){

        case(WELCOME_SENT): 

            s->state= WELCOME_ACKED;

            uip_send("Wbcdefghijklmnopqrstuvwxyz", 26);

            break;

        case(WELCOME_ACKED): 

            s->state=TX_SYNC_ING;

            uip_send("CBCDEFGHIJKLMNOPQRSTUVWXYZ", 26);

            break;

        case(TX_SYNC_ING):

            s->state=WELCOME_ACKED;

            uip_send("Sbcdefghijklmnopqrstuvwxyz", 26);

            break;

        } 

       // DBGMSG("app acked \n");

    }

    if(uip_poll()){

        DBGMSG("app poll \n");

    }

    

    if(uip_newdata()) {

       if( s->state=WELCOME_ACKED){

            s->state=TX_SYNC_ING;

            uip_send("NSCDEFGHIJKLMNOPQRSTUVWXYZ", 26);

       }else{

            s->state=WELCOME_ACKED;

            uip_send("NAcdefghijklmnopqrstuvwxyz", 26); 

       }

        //DBGMSG("app newdata \n");

    }

    

    if(uip_rexmit()) {

        DBGMSG("rxm\n");

        switch(s->state) {

            case WELCOME_SENT:

                uip_send("Welcome!\n", 9);

                break;

            case WELCOME_ACKED:

                s->state=TX_SYNC_ING;

                uip_send("RCcdefghijklmnopqrstuvwxyz", 26); 

                break;

            case TX_SYNC_ING:

                s->state=WELCOME_ACKED;

                uip_send("RSCDEFGHIJKLMNOPQRSTUVWXYZ", 26);

                break;

        }

    }

}

/*-------------------------------------------------------------------------*/

void uip_task_init()

{

    uip_ipaddr_t ipaddr;

    //tapdev_init();

    

    uip_init();

    uip_arp_init();

    landev_init();

    uip_ipaddr(ipaddr, 192,168,1,2);

    uip_sethostaddr(ipaddr);

    uip_ipaddr(ipaddr, 192,168,1,64);

    uip_setdraddr(ipaddr);

    uip_ipaddr(ipaddr, 255,255,255,0);

    uip_setnetmask(ipaddr);

    example2_init();

}

/*---------------------------------------------------------------------------*/

void uip_main(void *arg)

{

  int i;

  struct timer periodic_timer, arp_timer;

  timer_set(&periodic_timer, 1000);

  timer_set(&arp_timer, 1000* 10);

  

    

  uip_task_init();

  

  while(1) {

    //uip_len = landev_read();

    uip_len = landev_read();

  

    if(uip_len > 0) {

      if(BUF->type == htons(UIP_ETHTYPE_IP)) {

        uip_arp_ipin();

        uip_input();

        //DBGMSG("ip input\n");

        /* If the above function invocation resulted in data that

           should be sent out on the network, the global variable

           uip_len is set to a value > 0. */

        if(uip_len > 0) {

          uip_arp_out();

          landev_send();

        }

      } else if(BUF->type == htons(UIP_ETHTYPE_ARP)) {

        uip_arp_arpin();

        /* If the above function invocation resulted in data that

           should be sent out on the network, the global variable

           uip_len is set to a value > 0. */

        if(uip_len > 0) {

          landev_send();

        }

      }

    } else if(timer_expired(&periodic_timer)) {

      timer_reset(&periodic_timer);

      for(i = 0; i < UIP_CONNS; i++) {

        uip_periodic(i);

        /* If the above function invocation resulted in data that

           should be sent out on the network, the global variable

           uip_len is set to a value > 0. */

        if(uip_len > 0) {

          uip_arp_out();

          landev_send();

        }

      }

#if UIP_UDP

      for(i = 0; i < UIP_UDP_CONNS; i++) {

        uip_udp_periodic(i);

        /* If the above function invocation resulted in data that

           should be sent out on the network, the global variable

           uip_len is set to a value > 0. */

        if(uip_len > 0) {

          uip_arp_out();

          landev_send();

        }

      }

#endif /* UIP_UDP */

      

      /* Call the ARP timer function every 10 seconds. */

      if(timer_expired(&arp_timer)) {

        timer_reset(&arp_timer);

        uip_arp_timer();

      }

    }

  }

  //return 0;

} 


 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值