Chinaunix首页 | 论坛 | 博客
  • 博客访问: 188545
  • 博文数量: 79
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 15
  • 用 户 组: 普通用户
  • 注册时间: 2016-07-25 14:40
文章分类
文章存档

2015年(1)

2014年(1)

2013年(2)

2012年(1)

2011年(5)

2010年(2)

2009年(6)

2008年(20)

2007年(27)

2006年(14)

我的朋友

分类:

2008-03-26 21:12:46

UIP在ucos下的移植

    刚完成了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;

}

阅读(4943) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~