lwip-users
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[lwip-users] question about sys_mbox_fetch() which is called in netconn_


From: tao meng
Subject: [lwip-users] question about sys_mbox_fetch() which is called in netconn_recv!
Date: Fri, 17 Sep 2004 10:45:22 +0800

Dear lwip users:
I use two different communication mechanism between NE2000 NIC receive packet interrupt and my own read packet task:one is using a global variable,the other is using Semaphore,that is after create a semaphore, I will call OSSemPend(my_sem,0,&err) in my read packet task, and call OSSemPost() in NE2000 NIC receive packet interrupt.

1.First communication machanism

Now I can make lwip0.7.2+ucos_ii2.70 run stable on my ADI-BF532 board if I use a global Flag"Global_Flag" in small packet size.If NE2000 receive packet interrupt is coming then I will set "Global_Flag = 1",then In one of my task,which is use to read packet from the NIC,I just test "Global_Flag",given as follows:
  ////////////////////////////////
  (1)void ne2k_isr(void)
   {
    //other code is omitted
if (isr & ISR_PRX) {
                //* pNE_ISR = ISR_PRX;  // clear interrupt              
                Global_Flag = 1;
        }
    }
  (2)void ReadPacketTask(void *param)
{
 INT8U err;
param = param; while(1)
 {
while(rtl8019as_input(rtl8019as_netif)); OSTimeDly(1);
 }
}
  (3)bool Global_Flag = 0;

int rtl8019as_input(struct netif *my_netif)
{
            u8_t curr,bnry;
            if(Global_Flag == 0)
            return 1;
Global_Flag = 0;
                * pNE_CR = CMD_PAGE1 | CMD_NODMA | CMD_RUN;
                curr =* pNE_CURR;
                
                * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
                bnry =* pNE_BNRY;
                if(curr == bnry)
                return 1;
                //get more than one packet until receive buffer is empty
                while(curr != bnry )
                {
                    ne2k_input(my_netif);//
                        
                        //get curr and bnry again                       
                        * pNE_CR=CMD_PAGE1 | CMD_NODMA | CMD_RUN;
                        curr =* pNE_CURR;
                        * pNE_CR=CMD_PAGE0 | CMD_NODMA | CMD_RUN;
                        bnry =* pNE_BNRY;               
                }
                
                * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
       * pNE_ISR |= ISR_PRX;    // clear interrupt
                return 0;
} ////////////////////////////////
To the above code, I still have two questions:
(a).Since I should call at least a ucos_ii service in ucos_ii task,so I just call OSTimeDly(1) in ReadPacketTask,but I think it will result in low efficiency,and is there any other method to avoid making my task wait a fixed period of time???(The method of using semaphore I will talk about later!) (b)If I use the above code, I found that data throughput is very limited in both tcp and udp, even though they can work very stable in small packet size!So I want to know how I can enlarge the throughput both in tcp and udp!


2.Second communication machnism

(1)void main(void)
{       
        HardWareInit();
        
        OSInit();                               // Initialize uC/OS

        //++9-10
   rtl8019as_Sem = OSSemCreate(0);
                                
        CreateTasks();
        // Start Multitasking
        OSStart();                      

}


(2)void ne2k_isr(void)
  {
   //other code is omitted
   //got packet with no errors
if (isr & ISR_PRX) {
                //* pNE_ISR = ISR_PRX;  // clear interrupt
                
                err = OSSemPost(rtl8019as_Sem);
        }
   }
(3)void ReadPacketTask(void *param)
{
 INT8U err;
param = param; while(1) { OSSemPend(rtl8019as_Sem,0,&err); if(err != OS_NO_ERR)
          {
                
           printf("OSSemPend() error,err = %d\n",err);
           OSTaskSuspend(OS_PRIO_SELF);
          }
     rtl8019as_service(rtl8019as_netif);
 }
}
(4)void rtl8019as_service(struct netif *netif)
{
        u8_t curr,bnry;
* pNE_CR = CMD_PAGE1 | CMD_NODMA | CMD_RUN;
                curr =* pNE_CURR;
                
                * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
                bnry =* pNE_BNRY;
                
                //get more than one packet until receive buffer is empty
                while(curr != bnry )
                {
                        
                ne2k_input(netif);
                        //get curr and bnry again                       
                        * pNE_CR=CMD_PAGE1 | CMD_NODMA | CMD_RUN;
                        curr =* pNE_CURR;
                        * pNE_CR=CMD_PAGE0 | CMD_NODMA | CMD_RUN;
                        bnry =* pNE_BNRY;               
                }
                * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
       * pNE_ISR |= ISR_PRX;                    
}

In this communication mechanism I still have the following questions:
(1)sometimes it shows that "sys_mbox_fetch(conn->recvmbox, (void **)&p);" (which is called in netconn_recv() ) return "p == NULL",that is the following branch will be enter in netconn_recv():
/////////////////
/* If we are closed, we indicate that we no longer wish to receive
      data by setting conn->recvmbox to SYS_MBOX_NULL. */
if (p == NULL) {
     memp_free(MEMP_NETBUF, buf);
     sys_mbox_free(conn->recvmbox);
     conn->recvmbox = SYS_MBOX_NULL;
     DEBUGU(1,("In netconn_recv(),p == NULL\n\r"));
     return NULL;
   }
/////////////////
So I cannot transfer data anymore!The following is the "sys_mbox_fetch()" and "sys_arch_mbox_fetch" that I use:
/////////////////////
(1)void
sys_mbox_fetch(sys_mbox_t mbox, void **msg)
{
 u32_t time;

 struct sys_timeouts *timeouts;
 struct sys_timeout *tmptimeout;
 sys_timeout_handler h;
 void *arg;

again:
 timeouts = sys_arch_timeouts();

if (!timeouts || !timeouts->next) {
        //
        //DEBUGU(1,("In sys_mbox_fetch(),before1111\n\r"));
   sys_arch_mbox_fetch(mbox, msg, 0);
} else { if (timeouts->next->time > 0) {
     //
     //DEBUGU(1,("In sys_mbox_fetch(),before2222\n\r"));
     time = sys_arch_mbox_fetch(mbox, msg, timeouts->next->time);
} else {
     time = SYS_ARCH_TIMEOUT;
   }

if (time == SYS_ARCH_TIMEOUT) {
     /* If time == SYS_ARCH_TIMEOUT, a timeout occured before a message
  could be fetched. We should now call the timeout handler and
  deallocate the memory allocated for the timeout. */
     tmptimeout = timeouts->next;
     timeouts->next = tmptimeout->next;
     h = tmptimeout->h;
     arg = tmptimeout->arg;
     memp_free(MEMP_SYS_TIMEOUT, tmptimeout);
if (h != NULL) { LWIP_DEBUGF(SYS_DEBUG, ("smf calling h=%p(%p)\n", (void *)h, (void *)arg));
        h(arg);
     }

     /* We try again to fetch a message from the mbox. */
     goto again;
} else { /* If time != SYS_ARCH_TIMEOUT, a message was received before the timeout
  occured. The time variable is set to the number of
  milliseconds we waited for the message. */
if (time <= timeouts->next->time) {
      timeouts->next->time -= time;
} else {
      timeouts->next->time = 0;
     }
   }

 }
}

(2)
u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **data, u32_t timeout)
{
   u8_t     ucErr;
   u32_t ucos_timeout;
void *temp; if(timeout)
   {
       ucos_timeout = (timeout * OS_TICKS_PER_SEC)/1000;

       if(ucos_timeout < 1)
           ucos_timeout = 1;
       else if(ucos_timeout > 65535)
           ucos_timeout = 65535;
   }
   else
   {
       ucos_timeout = 0;
   }
temp = OSQPend( mbox->pQ, ucos_timeout, &ucErr );

   if(data)
   {
       if( temp == (void*)&pvNullPointer )
       {
           *data = NULL;
       }
       else
       {
           *data = temp;
       }
   }

   if( ucErr == OS_TIMEOUT )
   {
       timeout = SYS_ARCH_TIMEOUT;
   }
   else
   {
       LWIP_ASSERT( "OSQPend ", ucErr == OS_NO_ERR );
/* Calculate time we waited for the message to arrive. */ /* XXX: we cheat and just pretend that we waited for long! */
       timeout = 1;
   }

   return timeout;
}
/////////////////////

The following is my tcpecho test code:
////////////////////////
/*-----------------------------------------------------------------------------------*/


static void tcpecho_thread(void *arg)
{
 struct netconn *conn, *newconn;
 err_t err;
// Create a new connection identifier. conn = netconn_new(NETCONN_TCP); // Bind connection to well known port number 7. netconn_bind(conn, NULL, 7); // Tell connection to go into listening mode. netconn_listen(conn);
 DEBUGU(TCPECHO_DEBUG,("TcpEcho.c: listen!\n\r"));
//sys_timeout(TCP_TMR_INTERVAL, (sys_timeout_handler)tcpip_tcp_timer, NULL); while(1) { // Grab new connection. newconn = netconn_accept(conn); // Process the new connection. if(newconn != NULL) {
     struct netbuf * buf;
     void * data;
     u16_t len;
     u32_t i;
while((buf = netconn_recv(newconn)) != NULL) {
        
                do
                {
                        netbuf_data( buf, & data, & len);
                        err = netconn_write(newconn, data, len, NETCONN_COPY);
if(err != ERR_OK) { //printf("tcpecho: netconn_write: error \"%s\"\n", lwip_strerr(err));
                        DEBUGU(1,("Tcpecho.c: netconn_write error!\n\r"));
                        }
                } while(netbuf_next(buf) >= 0);
        
                netbuf_delete(buf);     
                //OSTimeDly(1);
     }
     printf("Got EOF, looping\n");
// Close connection and discard connection identifier. netconn_delete(newconn);
   }
} }


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

void
tcpecho_init(void)
{
sys_thread_new(tcpecho_thread, NULL,8); }
/*-----------------------------------------------------------------------------------*/



////////////////////////
I am looking forward to hearing your opinion to my problems,Thanks In advance!
                                Meng Tao
 Nanjing University of Posts and Telecommunications

_________________________________________________________________
与联机的朋友进行交流,请使用 MSN Messenger: http://messenger.msn.com/cn




reply via email to

[Prev in Thread] Current Thread [Next in Thread]