lwip-users
[Top][All Lists]
Advanced

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

[lwip-users] lwip+ucos-ii


From: tao meng
Subject: [lwip-users] lwip+ucos-ii
Date: Tue, 20 Jul 2004 18:27:33 +0800

(1).This afternoon I test lwip0.7.2+ucos-ii+ADI-BF532+my application.After it stop send packet to my PC,it enters if(tcp_sndbuf(conn->pcb.tcp) ==0) { ...},showing as following:
///////////////////////////////////////////////////////////////
 if (conn->type == NETCONN_TCP) {
     if (tcp_sndbuf(conn->pcb.tcp) == 0) {
 //by tom 7-17
DEBUGU(1,("before sys_sem_wait()0000!\n\r"));
 sys_sem_wait(conn->sem);
DEBUGU(1,("after sys_sem_wait()0000!\n\r")); if (conn->err != ERR_OK) {
   goto ret;
} ///////////////////////////////////////////////////////////////
(2).And at the same time Uart Port give out the following clues:
"In sys_arch_mbox_fetch,ucErr == OS_TIMEOUT!",my sys_arch.c file are also given out here.
///////////////////////////////////////////////////////////////
#include "lwip/debug.h"

#include "lwip/def.h"
#include "lwip/sys.h"
#include "lwip/mem.h"

#include "arch/sys_arch.h" //notice: we use OSTaskQuery in sys_arch_timeouts() !

//const void * const pvNullPointer = (void *)0xffffffff ;
const void * const pvNullPointer = (void *)0x0;
static OS_MEM * pQueueMem;

//static char segment("sdram_mem") pcQueueMemoryPool[MAX_QUEUES * sizeof(TQ_DESCR) ]; static section("sdram0") char pcQueueMemoryPool[MAX_QUEUES * sizeof(TQ_DESCR) ];

//static struct sys_timeouts segment("sdram_mem") lwip_timeouts[LWIP_TASK_MAX];
static section("sdram0") struct sys_timeouts lwip_timeouts[LWIP_TASK_MAX];
struct sys_timeouts null_timeouts;

//static OS_STK segment("sdram_mem") LWIP_TASK_STK[LWIP_TASK_MAX][LWIP_STK_SIZE]; static section("sdram0")OS_STK LWIP_TASK_STK[LWIP_TASK_MAX][LWIP_STK_SIZE];
static u8_t curr_prio_offset;

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

sys_mbox_t sys_mbox_new(void)
{
   u8_t       ucErr;
   PQ_DESCR    pQDesc;
//
   //printf("%0x\n",&pcQueueMemoryPool[0]);
pQDesc = OSMemGet( pQueueMem, &ucErr ); if( ucErr == OS_NO_ERR ) { //add by tom
                 //printf("sys_mbox_new,ucErr == OS_NO_ERR!\n");
pQDesc->pQ = OSQCreate( &(pQDesc->pvQEntries[0]), MAX_QUEUE_ENTRIES ); if( pQDesc->pQ != NULL ) {
        //add by tom
                        //printf("sys_mbox_new,pQDesc->pQ != NULL!\n");

                        return pQDesc;
         }
         //add by tom
         printf("sys_mbox_new,sys_arch.c: CreateQ error!\n");
//DEBUGU(SYS_ARCH_DEBUG,("sys_arch.c: CreateQ error\n\r"));
   }
   else
   {
                //add by tom
                printf("sys_arch.c: mbox new,no mem!\n");

        //DEBUGU(SYS_ARCH_DEBUG,("sys_arch.c: mbox new,no mem\n\r"));
   }
   return SYS_MBOX_NULL;
}

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

void
sys_mbox_free(sys_mbox_t mbox)
{
   u8_t     ucErr;
OSQFlush( mbox->pQ ); //clear OSQ EVENT
   (void)OSQDel( mbox->pQ, OS_DEL_NO_PEND, &ucErr);              //del OSQ EVENT
   ucErr = OSMemPut( pQueueMem, mbox );                                 //put 
mem back to mem queue
}

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

void
sys_mbox_post(sys_mbox_t mbox, void *data)
{
if( !data ) data = (void*)&pvNullPointer;
   (void)OSQPost( mbox->pQ, data);
}

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

//modified by tom 7-14
u16_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **data, u16_t timeout)
//u32_t sys_arch_mbox_fetch(sys_mbox_t mbox, void **data, u32_t timeout)
{
   u8_t     ucErr;
   u16_t ucos_timeout;
   //u32_t ucos_timeout;
//in lwip ,timeout is millisecond //in ucosII ,timeout is timer tick! //chang timeout from millisecond to ucos tick
 ucos_timeout = 0;
 if(timeout != 0){
 ucos_timeout = (timeout * OS_TICKS_PER_SEC)/1000;
 if(ucos_timeout < 1)
        ucos_timeout = 1;
 else if(ucos_timeout > 65535)
        ucos_timeout = 65535;
} //it is very importent!!!! //sometimes lwip calls sys_mbox_fetch(mbox,NULL)
 //it is dangrous to return (void *) to NULL ! (from OSQPend())
 if(data != NULL){
   //DEBUGU(1,("In sys_arch_mbox_fetch,before data != NULL!\n\r"));           
   *data = OSQPend( mbox->pQ, (u16_t)ucos_timeout, &ucErr );
//DEBUGU(1,("In sys_arch_mbox_fetch,after data != NULL!\n\r")); }else{
   //just discard return value if data==NULL
   //DEBUGU(1,("In sys_arch_mbox_fetch(),before data == NULL!\n\r"));
   OSQPend(mbox->pQ,(u16_t)ucos_timeout,&ucErr);
   //DEBUGU(1,("In sys_arch_mbox_fetch(),after data == NULL!\n"));
 }
if( ucErr == OS_TIMEOUT ) { DEBUGU(1,("In sys_arch_mbox_fetch(),ucErr == OS_TIMEOUT!\n\r"));
       timeout = 0;
} else
 {
          //DEBUGU(1,("In sys_arch_mbox_fetch(),ucErr != OS_TIMEOUT!\n\r"));
if(*data == (void*)&pvNullPointer ) *data = NULL;
     timeout = 1;
 }
 return timeout;
}

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


sys_sem_t sys_sem_new(u8_t count)
{
   sys_sem_t pSem;
   pSem = OSSemCreate((u16_t)count );
   return pSem;
}

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


void sys_sem_signal(sys_sem_t sem)
{
   u8_t     ucErr;
   ucErr = OSSemPost((OS_EVENT *)sem );
}

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

u16_t sys_arch_sem_wait(sys_sem_t sem, u16_t timeout)
//u32_t sys_arch_sem_wait(sys_sem_t sem, u32_t timeout)
{
 u8_t err;
 u32_t ucos_timeout;
//in lwip ,timeout is millisecond //in ucosII ,timeout is timer tick! //chang timeout from millisecond to ucos tick
 ucos_timeout = 0;
 if(timeout != 0){
 ucos_timeout = (timeout * OS_TICKS_PER_SEC)/1000;
 if(ucos_timeout < 1)
        ucos_timeout = 1;
 else if(ucos_timeout > 65535)
        ucos_timeout = 65535;
 }
        
 OSSemPend ((OS_EVENT *)sem,(u16_t)ucos_timeout, (u8_t *)&err);
 //should not return 0 when wait time is 0, only when timeout!
//see sys_arch.txt in lwip/doc if(err == OS_TIMEOUT)
        return 0;
 else
        return 1;
}

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


void sys_sem_free(sys_sem_t sem)
{
   u8_t     ucErr;
   (void)OSSemDel((OS_EVENT *)sem, OS_DEL_NO_PEND, &ucErr );
}

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

void sys_init(void)
{
   u8_t i;
   //this func is called first in lwip task!
   u8_t   ucErr;
   //init mem used by sys_mbox_t
   //use ucosII functions
pQueueMem = OSMemCreate( (void*)pcQueueMemoryPool, MAX_QUEUES, sizeof(TQ_DESCR), &ucErr );
   if(ucErr == OS_NO_ERR)
        //DEBUGU(SYS_ARCH_DEBUG,("sys_arch.c: OSMemCreate OK!\n\r"));
curr_prio_offset = 0; //init lwip task prio offset
   for(i=0;i<LWIP_TASK_MAX;i++){             //init lwip_timeouts for every 
lwip task
        lwip_timeouts[i].next = NULL;
   }
}
/*-----------------------------------------------------------------------------------*/


/*----------------------------------------------------------------------*/
struct sys_timeouts * sys_arch_timeouts(void)
{
 u8_t curr_prio;
 s16_t err,offset;
 static OS_TCB curr_task_pcb;
null_timeouts.next = NULL;
 err = OSTaskQuery(OS_PRIO_SELF,&curr_task_pcb); //get current task prio
 curr_prio = curr_task_pcb.OSTCBPrio;
offset = curr_prio - LWIP_START_PRIO; if(offset < 0 || offset >= LWIP_TASK_MAX)
 {
return &null_timeouts;//not called by a lwip task ,return timeouts->NULL
 }

 return &lwip_timeouts[offset];
}
/*------------------------------------------------------------------------*/


void
sys_thread_new(void (* function)(void *arg1), void *arg2)
{
 if(curr_prio_offset < LWIP_TASK_MAX)
 {
OSTaskCreateExt( function, arg2,//(void *)0x1111, & LWIP_TASK_STK[curr_prio_offset][LWIP_STK_SIZE-1],
                                        LWIP_START_PRIO + curr_prio_offset,
                                        LWIP_START_PRIO + curr_prio_offset,
                                        & LWIP_TASK_STK[curr_prio_offset][0],
                                        LWIP_STK_SIZE,
(void *)0, OS_TASK_OPT_STK_CLR); curr_prio_offset++; } else { //DEBUGU(SYS_ARCH_DEBUG,("sys_arch.c: lwip task prio out of range ! error! ")); }
}

///////////////////////////////////////////////////////////////
(3)
The lwipopts.h I use are given as follows:
#ifndef __LWIPOPTS_H__
#define __LWIPOPTS_H__

//add by tom 7-20
/*
////////////////////////////////////////////////////////////////////////////


* enable SYS_LIGHTWEIGHT_PROT in lwipopts.h if you want inter-task protection * for certain critical regions during buffer allocation, deallocation and memory
* allocation and deallocation.

////////////////////////////////////////////////////////////////////////////

*/
//sys_arch_protect() and sys_arch_unprotect() should be implemented in sys_arch.c
//#define SYS_LIGHTWEIGHT_PROT 1


/* ---------- Memory options ---------- */
/* MEM_ALIGNMENT: should be set to the alignment of the CPU for which
  lwIP is compiled. 4 byte alignment -> define MEM_ALIGNMENT to 4, 2
  byte alignment -> define MEM_ALIGNMENT to 2. */
//yangye 2003-1-27
#define MEM_ALIGNMENT           4       //4

/* MEM_SIZE: the size of the heap memory. If the application will send
a lot of data that needs to be copied, this should be set high. */
#define MEM_SIZE                256000//12000

/* MEMP_NUM_PBUF: the number of memp struct pbufs. If the application
  sends a lot of data out of ROM (or other static memory), this
  should be set high. */
#define MEMP_NUM_PBUF           64//32
/* MEMP_NUM_UDP_PCB: the number of UDP protocol control blocks. One
  per active UDP "connection". */
#define MEMP_NUM_UDP_PCB        6
/* MEMP_NUM_TCP_PCB: the number of simulatenously active TCP
  connections. */
  //by tom 6-3
#define MEMP_NUM_TCP_PCB        10
/* MEMP_NUM_TCP_PCB_LISTEN: the number of listening TCP
  connections. */
#define MEMP_NUM_TCP_PCB_LISTEN 8
/* MEMP_NUM_TCP_SEG: the number of simultaneously queued TCP
  segments. */
#define MEMP_NUM_TCP_SEG        16//8
/* MEMP_NUM_SYS_TIMEOUT: the number of simulateously active
  timeouts. */
#define MEMP_NUM_SYS_TIMEOUT    6

//add by tom 7-14
#define MEMP_NUM_RAW_PCB 4


/* The following four are used only with the sequential API and can be
  set to 0 if the application only will use the raw API. */
/* MEMP_NUM_NETBUF: the number of struct netbufs. */
#define MEMP_NUM_NETBUF         64//16//40
/* MEMP_NUM_NETCONN: the number of struct netconns. */
#define MEMP_NUM_NETCONN        64//16//40
/* MEMP_NUM_APIMSG: the number of struct api_msg, used for
  communication between the TCP/IP stack and the sequential
  programs. */
#define MEMP_NUM_API_MSG        64//8//40
/* MEMP_NUM_TCPIPMSG: the number of struct tcpip_msg, which is used
  for sequential API communication and incoming packets. Used in
  src/api/tcpip.c. */
#define MEMP_NUM_TCPIP_MSG      64//16//40//16

/* These two control is reclaimer functions should be compiled
  in. Should always be turned on (1). */
#define MEM_RECLAIM             1
#define MEMP_RECLAIM            1

/* ---------- Pbuf options ---------- */
/* PBUF_POOL_SIZE: the number of buffers in the pbuf pool. */
//yangye 2003-1-22
//seems there is something wrong when PBUF_POOL_SIZE = 6 #define PBUF_POOL_SIZE 64//32//16//128//48//24//16

/* PBUF_POOL_BUFSIZE: the size of each pbuf in the pbuf pool. */
#define PBUF_POOL_BUFSIZE       1024//256//128//2048//256//128

/* PBUF_LINK_HLEN: the number of bytes that should be allocated for a
  link level header. */
#define PBUF_LINK_HLEN          16

/* ---------- TCP options ---------- */
#define LWIP_TCP                1
#define TCP_TTL                 255

/* Controls if TCP should queue segments that arrive out of
  order. Define to 0 if your device is low on memory. */
#define TCP_QUEUE_OOSEQ         1

/* TCP Maximum segment size. */
#define TCP_MSS                 1024//128//512//128

/* TCP sender buffer space (bytes). */
#define TCP_SND_BUF             8192//256//1024//256

/* TCP sender buffer space (pbufs). This must be at least = 2 *
  TCP_SND_BUF/TCP_MSS for things to work. */
#define TCP_SND_QUEUELEN 4 * TCP_SND_BUF/TCP_MSS//4 * TCP_SND_BUF/TCP_MSS

/* TCP receive window. */
#define TCP_WND                 8192//1024

/* Maximum number of retransmissions of data segments. */
#define TCP_MAXRTX              12//12

/* Maximum number of retransmissions of SYN segments. */
#define TCP_SYNMAXRTX           6//4

/* ---------- ARP options ---------- */
#define ARP_TABLE_SIZE                  10

/* ---------- IP options ---------- */
/* Define IP_FORWARD to 1 if you wish to have the ability to forward
  IP packets across network interfaces. If you are going to run lwIP
  on a device with only one network interface, define this to 0. */
#define IP_FORWARD              0   //1

/* If defined to 1, IP options are allowed (but not parsed). If
  defined to 0, all packets with IP options are dropped. */
#define IP_OPTIONS              1

/* ---------- ICMP options ---------- */
#define ICMP_TTL                255


/* ---------- DHCP options ---------- */
/* Define LWIP_DHCP to 1 if you want DHCP configuration of
  interfaces. DHCP is not implemented in lwIP 0.5.1, however, so
  turning this on does currently not work. */
#define LWIP_DHCP               0

/* 1 if you want to do an ARP check on the offered address
  (recommended). */
#define DHCP_DOES_ARP_CHECK     0

/* ---------- UDP options ---------- */
#define LWIP_UDP                1
#define UDP_TTL                 255


/* ---------- Statistics options ---------- */
//#define STATS

#ifdef STATS
#define LINK_STATS
#define IP_STATS
#define ICMP_STATS
#define UDP_STATS
#define TCP_STATS
#define MEM_STATS
#define MEMP_STATS
#define PBUF_STATS
#define SYS_STATS
#endif /* STATS */

#endif /* __LWIPOPTS_H__ */
////////////////////////////////////////////////////////////////////
(4).The netcard RTL8019AS driver is given as follows:
////////////////////////////////////////////////////////////////////

#include "lwip/debug.h"

#include "lwip/opt.h"
#include "lwip/def.h"
#include "lwip/ip.h"
#include "lwip/mem.h"
#include "lwip/pbuf.h"
#include "lwip/sys.h"
#include "arch/cc.h"

#include "netif/arp.h"
//#include "lwip/netif.h"
#include "netif/ne2kif.h"
#include "lwip/tcpip.h"

//#define DATA_DISCARD   //just for debug
#define NE_DMA_TIMEOUT 0xffff;

#define MAR0 0xff//0x00 #define MAR1 0xff//0x41 #define MAR2 0xff//0x00
#define MAR3 0xff//0x80 
#define MAR4 0xff//0x00 
#define MAR5 0xff//0x00 
#define MAR6 0xff//0x00 
#define MAR7 0xff//0x00 

/*
use static struct to store the mac address of the network chip,we can also use a eeprom to do this
*/
static u8_t rtl8019as_mac[6]={0x00,0x60,0xB3,0x44,0x55,0x66};

const struct eth_addr ethbroadcast = {0xff,0xff,0xff,0xff,0xff,0xff}; //the ethernet broadcast address
//const struct eth_addr MyEthAddr = {0xff,0xff,0xff,0xff,0xff,0xff};

static void ne2k_copyin(u16_t count, u8_t * buf);
static void ne2k_copyout(u16_t count, u8_t * buf);

static void ne2k_discard(u16_t count);
void ne2k_isr(void);
static void low_level_init(struct netif * netif);
static struct pbuf * low_level_input(struct rtl8019mac * rtl8019mac);
static err_t low_level_output(struct rtl8019mac *rtl8019mac,struct pbuf *p);

///////////////////////////////////////////
static struct pbuf * low_level_receive(struct rtl8019mac * rtl8019mac);
void ne2k_recv_packet(struct netif *netif);
static err_t low_level_send(struct rtl8019mac * rtl8019mac,struct pbuf *p);
///////////////////////////////////////////

struct netif * rtl8019as_netif;         //rtl8019as netif struct which we use
//static u8_t NextRecvPage;
static section("sdram0") u8_t NextRecvPage;

/*
* Read the specified number of bytes from the device DMA port into
* the supplied buffer.
*/
static void ne2k_copyin(u16_t count, u8_t * buf)
{
#if (NE_DMA_MODE == 8)//8 bit mode while(count--) { * buf++ =* pNE_DMA; }
#else
        //u16_t temp;
        u16_t *tmpbuf = (u16_t *)buf;
        
        count = (count + 1)/2;
        while (count --)
        {
      *tmpbuf++  =* pNE_DMA;
      /*
* buf ++ = temp & 0xff; * buf ++ = (temp >> 8) & 0xff;
      */
   }
#endif
}

/*
* Write the specified number of bytes from the device DMA port into
* the supplied buffer.
*/

static void ne2k_copyout(u16_t count, u8_t * buf)
{
#if (NE_DMA_MODE == 8)//8 bit mode while(count--) {
                * pNE_DMA =* buf++;
        }
        
#else
        //u16_t temp = 0;
        u16_t *tmpbuf = (u16_t *)buf;
        
        count = (count + 1)/2;
        while (count --)
        {
                * pNE_DMA = *tmpbuf++;
                /*
                temp = * buf ++;
                temp += ((* buf ++) << 8) & 0xff00;
                * pNE_DMA = temp;
                */
        }
#endif  
}


/*
* Pull the specified number of bytes from the device DMA port,
* and throw them away.
*/
static void ne2k_discard(u16_t count)
{
        u16_t tmp;
        
#if (NE_DMA_MODE != 8)//8 bit mode count = (count + 1)/2;
        #endif
        
        while(count --)         tmp =* pNE_DMA;
}

/*
Interrupt service routine
*/
void ne2k_isr(void)
{
        u8_t  isr,curr,bnry;
        
        struct pbuf * p;
        struct rtl8019mac * rtl8019mac;
        //struct netif *netif;
        
        u8_t PDHeader[18];              //packet data header buffer
        u16_t PacketLength;     
        
        //close nic
        * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
        
        //in PAGE0
        isr =* pNE_ISR;
        
        // ram overflow interrupt
        if (isr & ISR_OVW) {
                //DEBUGU(NE2000_DEBUG,("OVW Interrupt!\n\r"));
                
                *pNE_ISR = ISR_OVW;
// ne2k_overflowProcess(); }
        
        // error transfer interrupt ,NIC abort tx due to excessive collisions   
        if (isr & ISR_TXE) {
                //DEBUGU(NE2000_DEBUG,("TXE Interrupt!\n\r"));
                * pNE_ISR = ISR_TXE;    // clear interrupt
                //temporarily do nothing
        }

        // Rx error , reset BNRY pointer to CURR (use SEND PACKET mode)
        if (isr & ISR_RXE) {
                //DEBUGU(NE2000_DEBUG,("RXE Interrupt!\n\r"));
                *pNE_ISR=ISR_RXE;               // clear interrupt
                //modified by tom
                //* pNE_CR = CMD_PAGE1 | CMD_NODMA | CMD_RUN;
                * pNE_CR = CMD_PAGE1 | CMD_NODMA | CMD_STOP;
                
                curr =* pNE_CURR ;
                //modified by tom
                //* pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
                * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
                
                * pNE_BNRY = curr;
        }
        
        //modified by tom 6-16
        //got packet with no errors
if (isr & ISR_PRX) {
                //DEBUGU(NE2000_DEBUG,("ISR: PRX Interrupt!\n\r"));
                * pNE_ISR = ISR_PRX;    // clear interrupt
                //modified by tom 6-16
                //* pNE_CR = CMD_PAGE1 | CMD_NODMA | CMD_RUN;
               * pNE_CR = CMD_PAGE1 | CMD_NODMA | CMD_STOP;
                        
                curr =* pNE_CURR;
                
                //* pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
               * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
bnry =* pNE_BNRY;
                
                //get more than one packet until receive buffer is empty
                while(curr != bnry ){
                        //#ifndef DATA_DISCARD
                        //if the buffer on netcard is not empty,receive 
continuly.
                        
                        //#if( DO_ARP_IN_ISR )
                        //ne2k_input(rtl8019as_netif);//
                        
                        //#else  //do low_lever_input here and send message now
                        
                        p = low_level_input(rtl8019mac);
                        if(p != NULL){
                                rtl8019as_netif -> input(p, rtl8019as_netif);
                        }else{
                                //by tom 7-7
                                pbuf_free(p);
                                //DEBUGU(1,("ISR: Low lever recv Error!\n\r"));
                        }
                        
                        //#endif
                        /*
#else //for test ; just discard all packages * pNE_ISR = ISR_RDC; // clear DMA cpmlete interrupt * pNE_RBCR1 = 0x0f; // See controller manual , use send packet command * pNE_CR = CMD_PAGE0 | CMD_SEND | CMD_RUN; //begin send package //get the first 18 bytes from nic ne2k_copyin(18,PDHeader);
                        //  Store real length, set len to packet length - header
// this length is generated by rtl8019as // the real value is length-4
                        PacketLength = ((u16_t) PDHeader[2] | (PDHeader[3] << 8 
));       
                        //bg4qad    let other data out
        ne2k_discard(PacketLength - 14);                
        DEBUGU(NE2000_DEBUG,("A new Package:"));
        #endif   //DATA_DISCARD
        */
                        //
                        //modified by tom 6-16
                        //get curr and bnry again                       
                        * pNE_CR=CMD_PAGE1 | CMD_NODMA | CMD_STOP;
                        //* pNE_CR=CMD_PAGE1 | CMD_NODMA | CMD_RUN;
                        curr =* pNE_CURR;
                        * pNE_CR=CMD_PAGE0 | CMD_NODMA | CMD_STOP;
                        //* pNE_CR=CMD_PAGE0 | CMD_NODMA | CMD_RUN;
                        bnry =* pNE_BNRY;               
                        }
        }
        
        //
        //Transfer complete, do nothing here
        if( isr & ISR_PTX){
                //DEBUGU(NE2000_DEBUG,("PTX Interrupt!\n\r"));
                * pNE_ISR = ISR_PTX;    // clear interrupt
        }
                
        * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
        * pNE_ISR = 0xff;                       // clear ISR
        //open nic for next packet
        * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
}


/**
* Initialize the rtk8019as, resetting the interface and getting the ethernet
* address.
*/
static void low_level_init(struct netif * netif)
{
        u32_t i;
        u8_t bnry, curr, temp;
        struct rtl8019mac * rtl8019mac;
        //Modified by tom
        //rtl8019mac = mem_malloc(sizeof(struct eth_addr));
        * pNE_CR = 0x22;  //add
       rtl8019mac = netif->state;
                
        /* make up an address. */
        for(i = 0; i < 6; i ++)
        {
                rtl8019mac -> ethaddr -> addr[i] = rtl8019as_mac[i];
                netif -> hwaddr[i] = rtl8019as_mac[i];
        }
        //Modified by tom(mask off)
//netif -> state = rtl8019mac;
/*
* Initialize physical device
*/
        //software reset        //write and read 0x1f to reset the nic
        * pNE_RESET = 0;
//i =* pNE_RESET ; //for(i=0; i < 270000; i++) //software delay at least 10ms
        OSTimeDlyHMSM(0,0,0,10);                //
        
        //in PAGE0
        * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_STOP;
        
/* FIFO threshold = 8 bytes, normal operation, 8-bit byte write DMA, BOS=0 */ /* DCR_BOS byte order select DCR_WTS word transfer select */ #if (NE_DMA_MODE == 8)//8 bit mode * pNE_DCR = DCR_LS | DCR_FIFO8; #else //* pNE_DCR = DCR_WTS | DCR_BOS |DCR_LS | DCR_FIFO8;
        * pNE_DCR = DCR_WTS | DCR_LS | DCR_FIFO8;
        #endif
        
        * pNE_RBCR0=0;
        * pNE_RBCR1=0;
//#if   0   //yangye: don't use in skyeye , maybe later
/*
* Promicuous receive(receive all the packets), including bad packets.
*/
//      outb(RCR_AB | RCR_AM | RCR_SEP | RCR_PRO, NE_RCR);
        //enable all interrupt to test //bg4qad
        
//now receive 1,broadcast 2,multicast // 3,mac address same with me
        //Modified by tom
        //* pNE_RCR = RCR_AB | RCR_AM  ;  //can be modified today
       * pNE_RCR = RCR_AB;
       //* pNE_RCR = RCR_AB | RCR_AM | RCR_SEP | RCR_PRO; //add by tom
//#else
/*
* Allow broadcast packets, in addition to packets unicast to us.
* Multicast packets that match MAR filter bits will also be
* allowed in.
*/
//      outb(RCR_AB, NE_RCR);
//#endif
//Place the SNIC in LOOPBACK mode 1 or 2 (Transmit Configuration Register e 02H or 04H)
        * pNE_TCR    = TCR_LOOP_INT;
        
        * pNE_TPSR   = XMIT_START >> 8;
        * pNE_PSTART = RECV_START >> 8;
        * pNE_BNRY   = RECV_START >> 8;
        * pNE_PSTOP  = RECV_STOP >> 8;
        
        //in PAGE1
        * pNE_CR = CMD_PAGE1 | CMD_NODMA | CMD_STOP;
        * pNE_CURR = (RECV_START >> 8) ;

/*
* Set physical address here.(not use eeprom)
*/
        * pNE_PAR0 = rtl8019as_mac[0];
        * pNE_PAR1 = rtl8019as_mac[1];
        * pNE_PAR2 = rtl8019as_mac[2];
        * pNE_PAR3 = rtl8019as_mac[3];
        * pNE_PAR4 = rtl8019as_mac[4];
        * pNE_PAR5 = rtl8019as_mac[5];

        //setup multicast address
        * pNE_MAR0 = MAR0;
        * pNE_MAR1 = MAR1;
        * pNE_MAR2 = MAR2;
        * pNE_MAR3 = MAR3;
        * pNE_MAR4 = MAR4;
        * pNE_MAR5 = MAR5;
        * pNE_MAR6 = MAR6;
        * pNE_MAR7 = MAR7;
        
        //select PAGE0 and start the nic
        * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
        
        //discard all data already in the buffer
        //nothing to do now

        //set Interrupt mask reg
        //define rxe to test interrupt bg4qad
        //Modified by tom
        * pNE_IMR = ISR_OVW | ISR_TXE | ISR_PTX | ISR_PRX;// | ISR_RXE;
//* pNE_IMR = ISR_OVW | ISR_TXE | ISR_PRX | ISR_RXE;//can be modified today
        
        * pNE_TCR = TCR_LOOP_NONE;
        
        //clear all interrupts
        * pNE_ISR = 0xff;
        //
        rtl8019as_netif = netif;
}

/*
* Function to do the actual writing of a packet into the devices
* transmit buffer.  INT is disable during the function!!!!
*/
static err_t low_level_output(struct rtl8019mac * rtl8019mac,struct pbuf *p)
{
        struct pbuf *q;
        u8_t isr;
        
        #if(NE_DMA_MODE != 8)
        u16_t temp;
        #endif
        
        u32_t i;
        u16_t padLength, PacketLength;

/*
* Set up to transfer the packet contents to the NIC RAM.
*/
        padLength = 0;
        PacketLength = p->tot_len;
         //packetLength muse >=64 (see 802.3)
   if ((p->tot_len) < 64)
        {
      padLength = 64 - (p->tot_len);
      PacketLength = 64;
        }
        
        //yangye 2003-1-21
        //don't close nic,just close receive interrupt  
                
        * pNE_CR = CMD_PAGE2 | CMD_NODMA | CMD_RUN;
        isr =* pNE_IMR;
        isr &= ~ISR_PRX;
   * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
        * pNE_IMR = isr;
                
        * pNE_ISR = ISR_RDC;

                
        //yangye 2003-1-21
        //or close nic(CMD_STOP) during receive ???
        //outb(CMD_PAGE0 | CMD_NODMA | CMD_STOP, NE_CR);
        
        
   // Amount to send
        * pNE_RBCR0 = PacketLength & 0xff;
        * pNE_RBCR1 = PacketLength >> 8;
        
   // Address on NIC to store
        * pNE_RSAR0 = XMIT_START & 0xff;
        * pNE_RSAR1 = XMIT_START >> 8;
        // Write command to start
* pNE_CR = CMD_PAGE0 | CMD_WRITE | CMD_RUN;
/*
* Write packet to ring buffers.
*/
for(q = p; q != NULL; q = q -> next) { ne2k_copyout(q -> len, q -> payload);
  }
   /* Send the data from the pbuf to the interface, one pbuf at a
      time. The size of the data in each pbuf is kept in the ->len
      variable. */
        #if(NE_DMA_MODE == 8)
        while(padLength-- > 0)       {* pNE_DMA = 0x00;}
        #else   
   temp = (padLength + 1) / 2;
        while(temp-- > 0)    {* pNE_DMA = 0x0000;}   
        #endif
        
        // Write padding for undersized packets
// Wait for remote dma to complete - ISR Bit 6 clear if busy
        //while((u8_t)(inb(NE_ISR) & ISR_RDC) == 0 );
        while((u8_t)((*pNE_ISR) & ISR_RDC )== 0);
        
        /*
        i = NE_DMA_TIMEOUT;
        while(i--)
                if((u8_t)((* pNE_ISR) & ISR_RDC) == ISR_RDC)break;  
       */
        * pNE_ISR = ISR_RDC;            //clear RDC
/*
* Issue the transmit command.(start local dma)
*/
        * pNE_TPSR = XMIT_START >> 8;
        * pNE_TBCR0 = PacketLength & 0xff;
        * pNE_TBCR1 = PacketLength >> 8;
        
        //  Start transmission (and shut off remote dma)
        //  and reopen nic(CMD_RUN)
        * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_XMIT | CMD_RUN;
                
        //yangye 2003-1-21
        //reopen receive interrupt
        
        * pNE_CR = CMD_PAGE2 | CMD_NODMA | CMD_RUN;
        isr =* pNE_IMR;
        isr |= ISR_PRX;
   * pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
        * pNE_IMR = isr;
        
        return ERR_OK;
}


/**
* Read a packet into a pbuf chain.
*
*/
static struct pbuf * low_level_input(struct rtl8019mac * rtl8019mac)
{
        u16_t  PacketLength,len;
        //modified by tom 7-7
        u8_t   PDHeader[18];
        //u8_t   PDHeader[26];   // Temp storage for ethernet headers 26 = 18 + 
8
        struct pbuf * p;
        struct pbuf * q;
        u8_t * payload;
        u16_t i;
        /*
        i = NE_DMA_TIMEOUT;
        while(i --)
                if((u8_t)((* pNE_ISR) & ISR_RDC) == ISR_RDC)break;
        */      
        //Modified by tom (add)
        * pNE_ISR = ISR_RDC;
        
* pNE_RBCR0 = 0x00; * pNE_RBCR1 = 0x0f; // See controller manual , use send packet command * pNE_CR = CMD_PAGE0 | CMD_SEND | CMD_RUN;

//get the first 18 bytes from nic ne2k_copyin(18,PDHeader);
        
        //  Store real length, set len to packet length - header
// this length is generated by rtl8019as // the real value is length-4
        PacketLength = ((u16_t) PDHeader[2] | (PDHeader[3] << 8 ));
        
        //modified by tom
        //verify if the packet is an IP packet or ARP packet
if((PDHeader[3]>0x06)||(PDHeader[16] != 8)||(PDHeader[17] != 0 && PDHeader[17] != 6))
       {
            //add by tom 7-7
//DEBUGU(1,("In low_level_input,the packet is neither IP packet nor ARP packet!"));
                 ne2k_discard(PacketLength-14);
            return NULL;
} /* // verify if the packet's length is right 0x600 = 1536 //verify if the packet is an IP packet or ARP packet
   //type != 0x0800 or type != 0x0806
        if( (PacketLength > 1536)||
                (PacketLength < 60)   ||
                (PDHeader[16] != 8)  ||
                (PDHeader[17] != 0 && PDHeader[17] != 6)        )
   {
                ne2k_copyin(8, &PDHeader[18]);
                
                //give me another chance,it is not standard but useful.
                for(i = 0;i < 18;i ++)
                {
                        PDHeader[i] = PDHeader[i + 8];
                }
                PacketLength = ((u16_t) PDHeader[2] | (PDHeader[3] << 8 ));
        
                if( (PacketLength > 1536)||
                        (PacketLength < 60)   ||
                        (PDHeader[16] != 8)  ||
                        (PDHeader[17] != 0 && PDHeader[17] != 6)        )
        {
ne2k_discard(PacketLength - 14); //discard the other data of this package
                
                        #if (0)
                        DEBUGU(NE2000_DEBUG,("low lever receive, 2th Packet 
header:\n\r"));
                        for (i = 0;i < 18;i ++)
                        {
                                UartPutcHex(PDHeader[i]);
                                DEBUGU(NE2000_DEBUG,(" "));
                        }
                        DEBUGU(NE2000_DEBUG,("\n\r"));
                        #endif  
                                
                        return NULL;
        }
} */ /* We allocate a pbuf chain of pbufs from the pool. */
        p = pbuf_alloc(PBUF_LINK, PacketLength, PBUF_POOL);
if(p != NULL) {
                /* We iterate over the pbuf chain until we have read the entire
                 packet into the pbuf. */
       // This assumes a minimum pbuf size of 14 ... a good assumption
//modified by tom 7-13 memcpy(p->payload, PDHeader + 4, 14);
       //bcopy (PDHeader + 4, p -> payload, 14);
                
                 //DEBUGU(NE2000_DEBUG,("ne2kif.c: low level 
receive,bcopy\n\r"));
                //can be r(mask off)
                /*
                if((p -> len) < 15 ){
                        ne2k_discard(PacketLength - 14);
                        DEBUGU(NE2000_DEBUG,("low lever receive,first buffer too 
small!\n\r"));
                        p = NULL;
                        return p;
                }
                */
                        
                for(q = p ; q != NULL; q = q -> next)
                {
                   /* Read enough bytes to fill this pbuf in the chain. The
                  avaliable data in the pbuf is given by the q->len
                  variable. */
                  /* read data into(q->payload, q->len); */
                payload = q -> payload;
                    len = q -> len;
                    if(q == p){
                        payload += 14;// First 14 bytes are already there, skip 
them
                                len -= 14;
                    }
        
                        ne2k_copyin(len, payload);
       }//for
       //* pNE_CR = CMD_PAGE0 | CMD_NODMA | CMD_RUN;
       //* pNE_BNRY = NextRecvPage;
} else {
   /* no more PBUF resource, Discard packet in buffer. */
        ne2k_discard(PacketLength - 14);
        //DEBUGU(NE2000_DEBUG,("ne2kif.c: low lever receive,no buffer!\n\r"));
        //DEBUGU(1,("ne2kif.c: low level receive,no buffer!\n\r"));
        }
        return p;
}


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

/*
* ethernetif_init():
*
* Should be called at the beginning of the program to set up the
* network interface. It calls the function low_level_init() to do the
* actual setup of the hardware.
*
*///  WARNING: must close all interrupts during init!!!!
/*-----------------------------------------------------------------------------------*/

//modified by tom 7-13
//void
err_t
ne2k_init(struct netif * netif)
{
 struct rtl8019mac * rtl8019mac;

 rtl8019mac = mem_malloc(sizeof(struct rtl8019mac));
//add by tom if(rtl8019mac == NULL)
 {
        //DEBUGU(1,("ne2k_init failed!\n\r"));
 }
 netif->state = rtl8019mac;
 netif->name[0] = 'e';
 netif->name[1] = 't';
 netif->output = ne2k_output; //output
 netif->input = tcpip_input;                 //input
 netif->linkoutput = low_level_output;
low_level_init(netif);
 arp_init();    
//add by tom
 return 0;      
}


/**
* Send a packet to the RTL8019AS from a series of pbuf buffers.
*/
err_t ne2k_output(struct netif * netif, struct pbuf * p,
                  struct ip_addr * ipaddr)
{
 struct rtl8019mac * rtl8019mac;
 struct pbuf * q;
 struct eth_hdr * ethhdr;
 struct eth_addr * dest, mcastaddr;
 struct ip_addr * queryaddr;
 err_t err;
 u8_t i;
//get mac address
 rtl8019mac = netif -> state;

 /* Make room for Ethernet header. */
if(pbuf_header(p, 14) != 0) {
          /* The pbuf_header() call shouldn't fail, but we allocate an extra
        pbuf just in case. */
        q = pbuf_alloc(PBUF_LINK, 14, PBUF_RAM);
if(q == NULL) {
                return ERR_MEM;
        }       
        pbuf_chain(q, p);
        p = q;
 }

 /* Construct Ethernet header. Start with looking up deciding which
    MAC address to use as a destination address. Broadcasts and
    multicasts are special, all other addresses are looked up in the
    ARP table. */
 queryaddr = ipaddr;
if(ip_addr_isany(ipaddr) || ip_addr_isbroadcast(ipaddr, &(netif->netmask))) {
   dest = (struct eth_addr *)&ethbroadcast;
 }
else if(ip_addr_ismulticast(ipaddr)) {
        
   /* Hash IP multicast address to MAC address. */
   mcastaddr.addr[0] = 0x01;
   mcastaddr.addr[1] = 0x0;
   mcastaddr.addr[2] = 0x5e;
   mcastaddr.addr[3] = ip4_addr2(ipaddr) & 0x7f;
   mcastaddr.addr[4] = ip4_addr3(ipaddr);
   mcastaddr.addr[5] = ip4_addr4(ipaddr);
   dest =& mcastaddr;
}else {

if(ip_addr_maskcmp(ipaddr, &(netif->ip_addr), &(netif->netmask))) {
     /* Use destination IP address if the destination is on the same
        subnet as we are. */
     queryaddr = ipaddr;
} else {
     /* Otherwise we use the default router as the address to send
        the Ethernet frame to. */
     queryaddr = &(netif->gw);
   }
   dest = arp_lookup(queryaddr);
 }


 /* If the arp_lookup() didn't find an address, we send out an ARP
    query for the IP address. */
if(dest == NULL) {
   q = arp_query(netif, rtl8019mac->ethaddr, queryaddr);
if(q != NULL) {
          err = low_level_output(rtl8019mac, q);
     pbuf_free(q);
     return (err);
   }
return ERR_MEM;
 }
 ethhdr = p->payload;

for(i = 0; i < 6; i++) {
   ethhdr->dest.addr[i] = dest->addr[i];
   ethhdr->src.addr[i] = rtl8019mac->ethaddr->addr[i];
 }
ethhdr->type = htons(ETHTYPE_IP);
 return low_level_output(rtl8019mac, p);
}


/**
* perform data received by tcpip_thread.
*/
void ne2k_perform(struct pbuf * p,struct netif * netif)
{
        struct eth_hdr * ethhdr;
        struct rtl8019mac * rtl8019mac;
        
        rtl8019mac = netif -> state;
ethhdr = p -> payload;
        switch(htons(ethhdr -> type))        //16bits, swap high and low 8 bit
        {
                case ETHTYPE_IP:                                //IS IP PACKET
                
                        //DEBUGU(NE2000_DEBUG,("ne2kif.c: perform IP!\n\r"));
                arp_ip_input(netif, p);         //get the ip head and update 
arp table
                pbuf_header(p, -14);            //cut the first 14 byte
                ip_input(p,netif);                      //
                        
                break;
                case ETHTYPE_ARP:                       //IS ARP PACKET
                
                        //DEBUGU(NE2000_DEBUG,("ne2kif.c: perform ARP!\n\r"));
                        p = arp_arp_input(netif, rtl8019mac->ethaddr, p);
if(p != NULL) {
                        //DEBUGU(NE2000_DEBUG,("send ARP begin!\n\r"));
                                low_level_output(rtl8019mac, p);//
                                pbuf_free(p);                             //
                                //DEBUGU(NE2000_DEBUG,("send ARP!\n\r"));
                        }
                else   {
                        //DEBUGU(NE2000_DEBUG,("ARP null!\n\r"));
                       }
                        break;
                default:
                        //DEBUGU(NE2000_DEBUG,("ne2kif.c: perform 
nothing!\n\r"));
                        pbuf_free(p);                   
                break;
                }
}

/**
* Read a packet, clearing overflows.
it is similar to ne2k_perform but they works at diffent layer and service for diffent master */
void ne2k_input(struct netif *netif)
{
 struct rtl8019mac * rtl8019mac;
 struct eth_hdr *ethhdr;
 struct pbuf *p;

 rtl8019mac = netif->state;
p = low_level_input(rtl8019mac); if(p == NULL) {
        //DEBUGU(NE2000_DEBUG,("low lever received:NULL\n\r"));
        return;
 }
ethhdr = p->payload; //

 switch(htons(ethhdr->type)) //16bits, swap high and low 8 bit
 {
 case ETHTYPE_IP:                               //IS IP PACKET
        //DEBUGU(NE2000_DEBUG,("IP package!\n\r"));
        
   arp_ip_input(netif, p);              //
   pbuf_header(p, -14);         //
   netif->input(p, netif);           //
   /* This function is called by the network device driver
        when it wants to pass a packet to the TCP/IP stack. */
                
   break;
 case ETHTYPE_ARP:                      //IS ARP PACKET
        //DEBUGU(NE2000_DEBUG,("ARP package!\n\r"));
        p = arp_arp_input(netif, rtl8019mac->ethaddr, p);
if(p != NULL) {
        low_level_output(rtl8019mac, p);//
                pbuf_free(p);                   //
        }
   break;
 default:
        //DEBUGU(NE2000_DEBUG,("nothing!\n\r"));
   pbuf_free(p);                        
   break;
 }
}

////////////////////////////////////////////////////////////////////
(5).
I really want to know why after I send some packets(sometimes 8MByte),"tcp_sndbuf(conn->pcb.tcp) == 0" always.I do see tcp_sndbuf increases in tcp_receive() function as following:
 /////////////////////////////////////////////////////////////////
 /* Update the send buffer space. */
     pcb->acked = ackno - pcb->lastack;
     pcb->snd_buf += pcb->acked;
///////////////////////////////////////////////////////////////// (6).I Create a write thread :
////////////////////////////////////////////////////////////////////
static section("sdram0") unsigned char data[2048];

static void tcpwrite_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"));
while(1) {
        DEBUGU(TCPECHO_DEBUG,("TcpEcho.c: runing!\n\r"));
// Grab new connection. newconn = netconn_accept(conn);
        
DEBUGF(TCPECHO_DEBUG,("Tcpecho.c: accepted new connection %p\n", newconn));
   DEBUGU(TCPECHO_DEBUG,("Tcpecho.c: accepted new connection!\n\r"));
       while(newconn != NULL)
   {
u16_t len = 2048; err = netconn_write(newconn,data,len,NETCONN_COPY);
     if(err != ERR_OK)
     {
        printf("netconn_write() called error!\n");
     }
     //OSTimeDly(2);
   }//while(newconn != NULL)
} //while(1) }


/////////////////////////////////////////////////////////////////// Can anyone give me some help,Thanks a lot.
                                         Meng Tao July 20 2004

_________________________________________________________________
享用世界上最大的电子邮件系统― MSN Hotmail。 http://www.hotmail.com




reply via email to

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