[Top][All Lists]
[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 *)ðbroadcast;
}
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