ARP Problem

Hi,
There are Erratum2 and Erratum3 in “3150Aplus_5100_errata_en_v2.4” document.
Altough I apply these solutions, I couldn’t observe ARP Reply from host to request from W5100.
Helps appreciated.

svsbaris,

Did you already clear W5100 SYN problem?
If not, this may be come from that problem.

I recommended you change your code like WIZnet’s reference code.
Please refer to it.

And I hope to loot at your whole driver of W5100 if you don’t mind.
Could you upload it here?

Thank you.

javakys,
Unfortunately I couldn’t fix SYN problem.
You’ll find socket.c and w5100.c as below:

socket.c

[code]/*
*
@file socket.c
@brief setting chip register for socket
*
*/

#include “types.h”
#include “w5100.h”
#include “socket.h”
#include “sys_conf.h”

static uint16 local_port;

/**
@brief This Socket function initialize the channel in perticular mode, and set the port and wait for W5100 done it.
@return 1 for sucess else 0.
*/
uint8 socket(
SOCKET s, /< for socket number */
uint8 protocol, /
< for socket protocol */
uint16 port, /< the source port for the socket */
uint8 flag /
< the option for the socket */
)
{
uint8 ret;
#ifdef DEF_IINCHIP_DBG
printf(“socket()\r\n”);
// printf(“protocol=%d\r\n”,protocol);
// printf(“port=%d\r\n”,port);
// printf(“flag=%d\r\n”,flag);
#endif
if( (protocol == (Sn_MR_TCP)) || (protocol == Sn_MR_UDP) || (protocol == Sn_MR_IPRAW) || (protocol == Sn_MR_MACRAW) || (protocol == Sn_MR_PPPOE) )
{
close(s);
// ret = 1;
// printf(“Socket kapatıldı. Yeniden yaratılıyor.\r\n”);
IINCHIP_WRITE(Sn_MR(s),protocol | flag );
if (port != 0)
{
IINCHIP_WRITE(Sn_PORT0(s),(uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE((Sn_PORT0(s) + 1),(uint8)(port & 0x00ff));
}
else
{
local_port++; // if don’t set the source port, set local_port number.
IINCHIP_WRITE(Sn_PORT0(s),(uint8)((local_port & 0xff00) >> 8));
IINCHIP_WRITE((Sn_PORT0(s) + 1),(uint8)(local_port & 0x00ff));
}
// printf(“Sn_CR_OPEN gönderildi (socket).\r\n”);
IINCHIP_WRITE(Sn_CR(s),Sn_CR_OPEN); // run sockinit Sn_CR
while(IINCHIP_READ(Sn_CR(s))); // wait for command processing
ret=1;
}
else
{
ret = 0;
}
#ifdef DEF_IINCHIP_DBG
// printf(“Socket_%d_Status_R=0x%.2x\r\n”, s,IINCHIP_READ(Sn_SR(s)));
#endif
return ret;
}

/**
@brief This function close the socket and parameter is “s” which represent the socket number
*/
void close(SOCKET s)
{
#ifdef DEF_IINCHIP_DBG
printf(“close()\r\n”);
#endif
IINCHIP_WRITE(Sn_CR(s),Sn_CR_CLOSE);
while(IINCHIP_READ(Sn_CR(s))); // wait for command processing
}

/**
@brief This function established the connection for the channel in passive (server) mode. This function waits for the request from the peer.
@return 1 for success else 0.
*/
uint8 listen( SOCKET s )// the socket number
{
uint8 ret;
#ifdef DEF_IINCHIP_DBG
// printf(“listen()\r\n”);
#endif
if (IINCHIP_READ(Sn_SR(s)) == SOCK_INIT)
{
IINCHIP_WRITE(Sn_CR(s),Sn_CR_LISTEN);
while( IINCHIP_READ(Sn_CR(s)) ) ;
ret = 1;
}
else
{
ret = 0;
#ifdef DEF_IINCHIP_DBG
printf(“Fail[invalid ip,port]\r\n”);
#endif
}
return ret;
}

uint8 connect(SOCKET s, uint8 * addr, uint16 port)
{
uint8 ret;
#ifdef DEF_IINCHIP_DBG
printf(“connect()\r\n”);
#endif
if
(
((addr[0] == 0xFF) && (addr[1] == 0xFF) && (addr[2] == 0xFF) && (addr[3] == 0xFF)) ||
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
(port == 0x00)
)
{
ret = 0;
#ifdef DEF_IINCHIP_DBG
printf(“Fail[invalid ip,port]\r\n”);
#endif
}
else
{
ret = 1;
// set destination IP
IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
IINCHIP_WRITE((Sn_DIPR0(s) + 1),addr[1]);
IINCHIP_WRITE((Sn_DIPR0(s) + 2),addr[2]);
IINCHIP_WRITE((Sn_DIPR0(s) + 3),addr[3]);
IINCHIP_WRITE(Sn_DPORT0(s),(uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE((Sn_DPORT0(s) + 1),(uint8)(port & 0x00ff));

// m2012.03.13 [ys]: set/clear subnet for ARP Errata

// applySUBR();

// setSUBR((unsigned char*)&plc.subnet_address[0]);
/* IINCHIP_WRITE((SUBR0 + 0),0);
IINCHIP_WRITE((SUBR0 + 1),0);
IINCHIP_WRITE((SUBR0 + 2),0);
IINCHIP_WRITE((SUBR0 + 3),0);*/

IINCHIP_WRITE(Sn_CR(s),Sn_CR_CONNECT);
    /* m2008.01 [bj] :  wait for completion */
while ( IINCHIP_READ(Sn_CR(s)) );

// check the SYN packet sending...
while ( IINCHIP_READ(Sn_SR(s)) != SOCK_SYNSENT )
{
   if(IINCHIP_READ(Sn_SR(s)) == SOCK_ESTABLISHED)
   { 
     /* IINCHIP_WRITE((SUBR0 + 0),0);
	  IINCHIP_WRITE((SUBR0 + 1),0);
      IINCHIP_WRITE((SUBR0 + 2),0);
	  IINCHIP_WRITE((SUBR0 + 3),0);	*/
	  break;
   }
   if (getSn_IR(s) & Sn_IR_TIMEOUT)
   {
      setSn_IR(s,(Sn_IR_TIMEOUT ));  // clear TIMEOUT Interrupt
      ret = 0;
    /*  IINCHIP_WRITE((SUBR0 + 0),0);
	  IINCHIP_WRITE((SUBR0 + 1),0);
	  IINCHIP_WRITE((SUBR0 + 2),0);
	  IINCHIP_WRITE((SUBR0 + 3),0);	*/
	  break;
   }
}

// clearSUBR();

// setSUBR((unsigned char*)&plc.subnet_address[0]);
/* IINCHIP_WRITE((SUBR0 + 0),0);
IINCHIP_WRITE((SUBR0 + 1),0);
IINCHIP_WRITE((SUBR0 + 2),0);
IINCHIP_WRITE((SUBR0 + 3),0); */
}

return ret;
}

/**
@brief This function used for disconnect the socket and parameter is “s” which represent the socket number
@return 1 for success else 0.
*/
void disconnect(SOCKET s)
{
#ifdef DEF_IINCHIP_DBG
// printf(“disconnect()\r\n”);
#endif
IINCHIP_WRITE(Sn_CR(s),Sn_CR_DISCON);
while (IINCHIP_READ(Sn_CR(s)));
}

/**
@brief This function used to send the data in TCP mode
@return 1 for success else 0.
*/

uint16 send(
SOCKET s, /< the socket index */
const uint8 * buf, /
< a pointer to data */
uint16 len /**< the data size to be send */
)
{
uint8 status=0;
uint16 ret=0;
uint16 freesize=0;
#ifdef DEF_IINCHIP_DBG
// printf(“send()\r\n”);
#endif

if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
else ret = len;

// if freebuf is available, start.
do
{
freesize = getSn_TX_FSR(s);
status = IINCHIP_READ(Sn_SR(s));
if ((status != SOCK_ESTABLISHED) && (status != SOCK_CLOSE_WAIT))
{
ret = 0;
break;
}
#ifdef DEF_IINCHIP_DBG
printf(“socket %d freesize(%d) empty or error\r\n”, s, freesize);
#endif
} while (freesize < ret);

  // copy data
send_data_processing(s, (uint8 *)buf, ret);
IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND);

/* +20071122[chungs]:wait to process the command… */
while( IINCHIP_READ(Sn_CR(s)) ) ;

#ifdef DEF_IINCHIP_INT
while ( (getISR(s) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
#else
while ( (IINCHIP_READ(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
#endif
{
if ( IINCHIP_READ(Sn_SR(s)) == SOCK_CLOSED )
{
#ifdef DEF_IINCHIP_DBG
printf(“SOCK_CLOSED.\r\n”);
#endif
close(s);
return 0;
}
}
#ifdef DEF_IINCHIP_INT
putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
#else
IINCHIP_WRITE(Sn_IR(s), Sn_IR_SEND_OK);
#endif
return ret;
}

/**
@brief This function is an application I/F function which is used to receive the data in TCP mode.
It continues to wait for data as much as the application wants to receive.

@return received data size for success else -1.
*/
uint16 recv(
SOCKET s, /< socket index */
uint8 * buf, /
< a pointer to copy the data to be received */
uint16 len /**< the data size to be read */
)
{
uint16 ret=0;
#ifdef DEF_IINCHIP_DBG
// printf(“recv()\r\n”);
#endif

if ( len > 0 )
{
	recv_data_processing(s, buf, len);
	IINCHIP_WRITE(Sn_CR(s),Sn_CR_RECV);
	while( IINCHIP_READ(Sn_CR(s)) ) ;
	ret = len;
}
return ret;

}

uint16 sendto(
SOCKET s, /< socket index */
const uint8 * buf, /
< a pointer to the data */
uint16 len, /< the data size to send */
uint8 * addr, /
< the peer’s Destination IP address */
uint16 port /**< the peer’s destination port number */
)
{
// uint8 status=0;
// uint8 isr=0;
uint16 ret=0;

#ifdef DEF_IINCHIP_DBG
// printf(“sendto(%s)\r\n”, buf);
#endif
if (len > getIINCHIP_TxMAX(s)) ret = getIINCHIP_TxMAX(s); // check size not to exceed MAX size.
else ret = len;

if
(
((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) && (addr[3] == 0x00)) ||
((port == 0x00)) ||(ret == 0)
)
{
/* +2008.01 [bj] : added return value /
ret = 0;
#ifdef DEF_IINCHIP_DBG
printf(“[ch%d] Fail[%.3d.%.3d.%.3d.%.3d, %.d, %d]\r\n”,s, addr[0], addr[1], addr[2], addr[3] , port, len);
printf(“Fail[invalid ip,port]\r\n”);
#endif
}
else
{
IINCHIP_WRITE(Sn_DIPR0(s),addr[0]);
IINCHIP_WRITE((Sn_DIPR0(s) + 1),addr[1]);
IINCHIP_WRITE((Sn_DIPR0(s) + 2),addr[2]);
IINCHIP_WRITE((Sn_DIPR0(s) + 3),addr[3]);
IINCHIP_WRITE(Sn_DPORT0(s),(uint8)((port & 0xff00) >> 8));
IINCHIP_WRITE((Sn_DPORT0(s) + 1),(uint8)(port & 0x00ff));
// copy data
send_data_processing(s, (uint8 )buf, ret);
// m2012.03.13 [ys]: set/clear subnet for ARP Errata
// applySUBR();
// setSUBR((unsigned char
)&plc.subnet_address[0]);
/
IINCHIP_WRITE((SUBR0 + 0),0);
IINCHIP_WRITE((SUBR0 + 1),0);
IINCHIP_WRITE((SUBR0 + 2),0);
IINCHIP_WRITE((SUBR0 + 3),0); */

IINCHIP_WRITE(Sn_CR(s),Sn_CR_SEND);
/* +20071122[chungs]:wait to process the command... */
while( IINCHIP_READ(Sn_CR(s)) );

/* ------- */

/* +2008.01 bj /
#ifdef DEF_IINCHIP_INT
while ( (getISR(s) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
#else
while ( (IINCHIP_READ(Sn_IR(s)) & Sn_IR_SEND_OK) != Sn_IR_SEND_OK )
#endif
{
#ifdef DEF_IINCHIP_INT
if (getISR(s) & Sn_IR_TIMEOUT)
#else
if (IINCHIP_READ(Sn_IR(s)) & Sn_IR_TIMEOUT)
#endif
{
#ifdef DEF_IINCHIP_DBG
printf(“send fail.\r\n”);
#endif
/
+2008.01 [bj]: clear interrupt /
#ifdef DEF_IINCHIP_INT
putISR(s, getISR(s) & ~(Sn_IR_SEND_OK | Sn_IR_TIMEOUT)); /
clear SEND_OK & TIMEOUT /
#else
IINCHIP_WRITE(Sn_IR(s), (Sn_IR_SEND_OK | Sn_IR_TIMEOUT)); /
clear SEND_OK & TIMEOUT */
#endif
return 0;
}
}

/* +2008.01 bj /
#ifdef DEF_IINCHIP_INT
putISR(s, getISR(s) & (~Sn_IR_SEND_OK));
#else
IINCHIP_WRITE(Sn_IR(s), Sn_IR_SEND_OK);
#endif
// clearSUBR();
// setSUBR((unsigned char
)&plc.subnet_address[0]);
/* IINCHIP_WRITE((SUBR0 + 0),0);
IINCHIP_WRITE((SUBR0 + 1),0);
IINCHIP_WRITE((SUBR0 + 2),0);
IINCHIP_WRITE((SUBR0 + 3),0); */
}
return ret;
}

/**
@brief This function is an application I/F function which is used to receive the data in other then
TCP mode. This function is used to receive UDP, IP_RAW and MAC_RAW mode, and handle the header as well.

@return This function return received data size for success else -1.
*/
uint16 recvfrom(
SOCKET s, /< the socket number */
uint8 * buf, /
< a pointer to copy the data to be received */
uint16 len, /< the data size to read */
uint8 * addr, /
< a pointer to store the peer’s IP address */
uint16 *port /**< a pointer to store the peer’s port number. */
)
{
uint8 head[8];
uint16 data_len=0;
uint16 ptr=0;
#ifdef DEF_IINCHIP_DBG
// printf(“recvfrom()\r\n”);
#endif

if ( len > 0 )
{
ptr = IINCHIP_READ(Sn_RX_RD0(s));
ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_RX_RD0(s) + 1);

#ifdef DEF_IINCHIP_DBG
// printf(“ISR_RX: rd_ptr : %.4x\r\n”, ptr);
#endif
switch (IINCHIP_READ(Sn_MR(s)) & 0x07)
{
case Sn_MR_UDP :
read_data(s, (uint8 *)ptr, head, 0x08);
ptr += 8;
// read peer’s IP address, port number.
addr[0] = head[0];
addr[1] = head[1];
addr[2] = head[2];
addr[3] = head[3];
*port = head[4];
*port = (*port << 8) + head[5];
data_len = head[6];
data_len = (data_len << 8) + head[7];

#ifdef DEF_IINCHIP_DBG
// printf(“UDP msg arrived\r\n”);
// printf(“source Port : %d\r\n”, *port);
// printf(“source IP : %d.%d.%d.%d\r\n”, addr[0], addr[1], addr[2], addr[3]);
#endif

		read_data(s, (uint8 *)ptr, buf, data_len); // data copy.
		ptr += data_len;

		IINCHIP_WRITE(Sn_RX_RD0(s),(uint8)((ptr & 0xff00) >> 8));
		IINCHIP_WRITE((Sn_RX_RD0(s) + 1),(uint8)(ptr & 0x00ff));
		break;

case Sn_MR_IPRAW :
		read_data(s, (uint8 *)ptr, head, 0x06);
		ptr += 6;

		addr[0] = head[0];
		addr[1] = head[1];
		addr[2] = head[2];
		addr[3] = head[3];
		data_len = head[4];
		data_len = (data_len << 8) + head[5];

#ifdef DEF_IINCHIP_DBG
printf(“IP RAW msg arrived\r\n”);
printf(“source IP : %d.%d.%d.%d\r\n”, addr[0], addr[1], addr[2], addr[3]);
#endif
read_data(s, (uint8 *)ptr, buf, data_len); // data copy.
ptr += data_len;

		IINCHIP_WRITE(Sn_RX_RD0(s),(uint8)((ptr & 0xff00) >> 8));
		IINCHIP_WRITE((Sn_RX_RD0(s) + 1),(uint8)(ptr & 0x00ff));
		break;
case Sn_MR_MACRAW :
		read_data(s,(uint8*)ptr,head,2);
		ptr+=2;
		data_len = head[0];
		data_len = (data_len<<8) + head[1] - 2;

		read_data(s,(uint8*) ptr,buf,data_len);
		ptr += data_len;
		IINCHIP_WRITE(Sn_RX_RD0(s),(uint8)((ptr & 0xff00) >> 8));
		IINCHIP_WRITE((Sn_RX_RD0(s) + 1),(uint8)(ptr & 0x00ff));

#ifdef DEF_IINCHIP_DGB
printf(“MAC RAW msg arrived\r\n”);
printf(“dest mac=%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\r\n”,buf[0],buf[1],buf[2],buf[3],buf[4],buf[5]);
printf(“src mac=%.2X.%.2X.%.2X.%.2X.%.2X.%.2X\r\n”,buf[6],buf[7],buf[8],buf[9],buf[10],buf[11]);
printf(“type =%.2X%.2X\r\n”,buf[12],buf[13]);
#endif
break;

default :
		break;
}
	IINCHIP_WRITE(Sn_CR(s),Sn_CR_RECV);
}

#ifdef DEF_IINCHIP_DBG
// printf(“recvfrom() end …\r\n”);
#endif
return data_len;
}[/code]

w5100.c

[code]/*
@file w5100.c
*/

#include <stdio.h>
#include <string.h>
#include “sys_conf.h”

#include “types.h”
//#include “delay.h” // for wait function

#include “w5100.h”

#ifdef DEF_IINCHIP_PPP
#include “md5.h”
#endif

static uint8 I_STATUS[MAX_SOCK_NUM];
static uint16 SMASK[MAX_SOCK_NUM]; /< Variable for Tx buffer MASK in each channel */
static uint16 RMASK[MAX_SOCK_NUM]; /
< Variable for Rx buffer MASK in each channel */
static uint16 SSIZE[MAX_SOCK_NUM]; /< Max Tx buffer size by each channel */
static uint16 RSIZE[MAX_SOCK_NUM]; /
< Max Rx buffer size by each channel */
static uint16 SBUFBASEADDRESS[MAX_SOCK_NUM]; /< Tx buffer base address by each channel */
static uint16 RBUFBASEADDRESS[MAX_SOCK_NUM]; /
< Rx buffer base address by each channel */
extern void iinchip_init(void); // reset iinchip

uint8 getISR(uint8 s)
{
return I_STATUS[s];
}

void putISR(uint8 s, uint8 val)
{
I_STATUS[s] = val;
}

uint16 getIINCHIP_RxMAX(uint8 s)
{
return RSIZE[s];
}
uint16 getIINCHIP_TxMAX(uint8 s)
{
return SSIZE[s];
}
uint16 getIINCHIP_RxMASK(uint8 s)
{
return RMASK[s];
}
uint16 getIINCHIP_TxMASK(uint8 s)
{
return SMASK[s];
}
uint16 getIINCHIP_RxBASE(uint8 s)
{
return RBUFBASEADDRESS[s];
}
uint16 getIINCHIP_TxBASE(uint8 s)
{
return SBUFBASEADDRESS[s];
}

/**
@brief This function writes the data into W5100 registers.
*/
uint8 IINCHIP_WRITE(uint16 addr,uint8 data)
{
//while(1){ethernet_send_data(0x55); printf(“data=%d\r\n”,data);}
// SPI2_CS_CLR;
ethernet_send_data(0xF0);
ethernet_send_data((addr & 0xFF00) >> 8);
ethernet_send_data(addr & 0x00FF);
// printf(“data=%d\r\n”,data);
ethernet_send_data(data);
// SPI2_CS_SET;

return 1;

}

/**
@brief This function reads the value from W5100 registers.
*/
uint8 IINCHIP_READ(uint16 addr)
{
static uint8 data;
// SPI2_CS_CLR;
ethernet_send_data(0x0F);
ethernet_send_data((addr & 0xFF00) >> 8);
ethernet_send_data(addr & 0x00FF);
data = ethernet_send_data(0x00); // write dummy data to read
// SPI2_CS_SET;
return data;
}

/**
@brief This function writes into W5100 memory(Buffer)
/
//uint16 wiz_write_buf(unsigned long addr,uint8
buf,uint16 len)
uint16 wiz_write_buf(uint16 addr,uint8* buf,uint16 len)
{
static uint16 ii;
// SPI2_CS_CLR;
for(ii=0;ii<len;ii++)
{
ethernet_send_data(0xF0);
ethernet_send_data(((addr+ii) & 0xFF00) >> 8);
ethernet_send_data((addr+ii) & 0x00FF);
ethernet_send_data (buf[ii]);
}
// SPI2_CS_SET;
return len;
}

/**
@brief This function reads into W5100 memory(Buffer)
/
//uint16 wiz_read_buf(unsigned long addr, uint8
buf,uint16 len)
uint16 wiz_read_buf(uint16 addr, uint8* buf,uint16 len)
{
static uint16 iii;
// SPI2_CS_CLR;
for (iii=0; iii<len; iii++)
{
ethernet_send_data(0x0F);
ethernet_send_data(((addr+iii) & 0xFF00) >> 8);
ethernet_send_data((addr+iii) & 0x00FF);
//for (iii=0; iii<len; iii++)
//{
buf[iii]=ethernet_send_data(0x00); // write dummy data to read
//}
}
// SPI2_CS_SET;
return len;
}

/**
@brief This function is for resetting of the iinchip. Initializes the iinchip to work in whether DIRECT or INDIRECT mode
/
void iinchip_init(void)
{
//setMR(MR_RST);
setMR(MR_RST | MR_PB);
// printf(“MR value is %d \r\n”,IINCHIP_READ(MR));
// while(1);
/
while(1)
{
IINCHIP_WRITE(GAR0,0xC4);
//setMR(0x90);
printf(“MR value is %d \r\n”,IINCHIP_READ(GAR0));} */

/*
((volatile uint8)(MR)) = MR_RST;

#if (DEF_IINCHIP_BUS == DEF_IINCHIP_INDIRECT_MODE)
((volatile uint8)(MR)) = MR_IND | MR_AI;
#ifdef DEF_IINCHIP_DBG
printf(“MR value is %d \r\n”,IINCHIP_READ(MR));
#endif
#endif*/
}

/**
@brief This function set the transmit & receive buffer size as per the channels is used

Note for TMSR and RMSR bits are as follows\n
bit 1-0 : memory size of channel #0 \n
bit 3-2 : memory size of channel #1 \n
bit 5-4 : memory size of channel #2 \n
bit 7-6 : memory size of channel #3 \n\n
Maximum memory size for Tx, Rx in the W5100 is 8K Bytes,\n
In the range of 8KBytes, the memory size could be allocated dynamically by each channel.\n
Be attentive to sum of memory size shouldn’t exceed 8Kbytes\n
and to data transmission and receiption from non-allocated channel may cause some problems.\n
If the 8KBytes memory is already assigned to centain channel, \n
other 3 channels couldn’t be used, for there’s no available memory.\n
If two 4KBytes memory are assigned to two each channels, \n
other 2 channels couldn’t be used, for there’s no available memory.\n
*/
void sysinit(
uint8 tx_size, /< tx_size Tx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte) */
uint8 rx_size /
< rx_size Rx memory size (00 - 1KByte, 01- 2KBtye, 10 - 4KByte, 11 - 8KByte) */
)
{
int16 i;
int16 ssum,rsum;

#ifdef DEF_IINCHIP_DBG
// printf(“sysinit()\r\n”);
#endif

ssum = 0;
rsum = 0;

IINCHIP_WRITE(TMSR,tx_size); /* Set Tx memory size for each channel */
IINCHIP_WRITE(RMSR,rx_size);	 /* Set Rx memory size for each channel */

SBUFBASEADDRESS[0] = (uint16)(__DEF_IINCHIP_MAP_TXBUF__);		/* Set base address of Tx memory for channel #0 */
RBUFBASEADDRESS[0] = (uint16)(__DEF_IINCHIP_MAP_RXBUF__);		/* Set base address of Rx memory for channel #0 */

#ifdef DEF_IINCHIP_DBG
// printf(“Channel : SEND MEM SIZE : RECV MEM SIZE\r\n”);
#endif

for (i = 0 ; i < MAX_SOCK_NUM; i++) // Set the size, masking and base address of Tx & Rx memory by each channel
{
SSIZE[i] = (int16)(0);
RSIZE[i] = (int16)(0);
if (ssum < 8192)
{
switch((tx_size >> i2) & 0x03) // Set Tx memory size
{
case 0:
SSIZE[i] = (int16)(1024);
SMASK[i] = (uint16)(0x03FF);
break;
case 1:
SSIZE[i] = (int16)(2048);
SMASK[i] = (uint16)(0x07FF);
break;
case 2:
SSIZE[i] = (int16)(4096);
SMASK[i] = (uint16)(0x0FFF);
break;
case 3:
SSIZE[i] = (int16)(8192);
SMASK[i] = (uint16)(0x1FFF);
break;
}
}
if (rsum < 8192)
{
switch((rx_size >> i
2) & 0x03) // Set Rx memory size
{
case 0:
RSIZE[i] = (int16)(1024);
RMASK[i] = (uint16)(0x03FF);
break;
case 1:
RSIZE[i] = (int16)(2048);
RMASK[i] = (uint16)(0x07FF);
break;
case 2:
RSIZE[i] = (int16)(4096);
RMASK[i] = (uint16)(0x0FFF);
break;
case 3:
RSIZE[i] = (int16)(8192);
RMASK[i] = (uint16)(0x1FFF);
break;
}
}
ssum += SSIZE[i];
rsum += RSIZE[i];

  if (i != 0)             // Sets base address of Tx and Rx memory for channel #1,#2,#3
	{
		SBUFBASEADDRESS[i] = SBUFBASEADDRESS[i-1] + SSIZE[i-1];
		RBUFBASEADDRESS[i] = RBUFBASEADDRESS[i-1] + RSIZE[i-1];
	}

#ifdef DEF_IINCHIP_DBG
// printf(“%d : %.4x : %.4x : %.4x : %.4x\r\n”, i, (uint16)SBUFBASEADDRESS[i], (uint16)RBUFBASEADDRESS[i], SSIZE[i], RSIZE[i]);
#endif
}
}

void setMR(uint8 val)
{
//((volatile uint8)(MR)) = val;
IINCHIP_WRITE(MR,val);
}

/**
@brief This function sets up gateway IP address.
*/
void setGAR(
uint8 * addr /**< a pointer to a 4 -byte array responsible to set the Gateway IP address. */
)
{
// printf(“Gateway=%d.%d.%d.%d\r\n”,addr[0],addr[1],addr[2],addr[3]);
IINCHIP_WRITE((GAR0 + 0),addr[0]);
IINCHIP_WRITE((GAR0 + 1),addr[1]);
IINCHIP_WRITE((GAR0 + 2),addr[2]);
IINCHIP_WRITE((GAR0 + 3),addr[3]);
}

void getGWIP(uint8 * addr)
{
addr[0] = IINCHIP_READ((GAR0 + 0));
addr[1] = IINCHIP_READ((GAR0 + 1));
addr[2] = IINCHIP_READ((GAR0 + 2));
addr[3] = IINCHIP_READ((GAR0 + 3));
}

/**
@brief It sets up SubnetMask address
*/
void setSUBR(
uint8 * addr /**< a pointer to a 4 -byte array responsible to set the SubnetMask address */
)
{
// printf(“Subnet=%d.%d.%d.%d\r\n”,addr[0],addr[1],addr[2],addr[3]);
IINCHIP_WRITE((SUBR0 + 0),addr[0]);
IINCHIP_WRITE((SUBR0 + 1),addr[1]);
IINCHIP_WRITE((SUBR0 + 2),addr[2]);
IINCHIP_WRITE((SUBR0 + 3),addr[3]);
}

/**
@brief This function sets up MAC address.
*/
void setSHAR(
uint8 * addr /**< a pointer to a 6 -byte array responsible to set the MAC address. */
)
{
// printf(“MAC=%d.%d.%d.%d.%d.%d\r\n”,addr[0],addr[1],addr[2],addr[3],addr[4],addr[5]);
IINCHIP_WRITE((SHAR0 + 0),addr[0]);
IINCHIP_WRITE((SHAR0 + 1),addr[1]);
IINCHIP_WRITE((SHAR0 + 2),addr[2]);
IINCHIP_WRITE((SHAR0 + 3),addr[3]);
IINCHIP_WRITE((SHAR0 + 4),addr[4]);
IINCHIP_WRITE((SHAR0 + 5),addr[5]);
}

/**
@brief This function sets up Source IP address.
*/
void setSIPR(
uint8 * addr /**< a pointer to a 4 -byte array responsible to set the Source IP address. */
)
{
IINCHIP_WRITE((SIPR0 + 0),addr[0]);
IINCHIP_WRITE((SIPR0 + 1),addr[1]);
IINCHIP_WRITE((SIPR0 + 2),addr[2]);
IINCHIP_WRITE((SIPR0 + 3),addr[3]);
}

/**
@brief This function gets Interrupt register in common register.
*/
uint8 getIR( void )
{
return IINCHIP_READ(IR);
}

/**
@brief This function sets up Retransmission time.

If there is no response from the peer or delay in response then retransmission
will be there as per RTR (Retry Time-value Register)setting
*/
void setRTR(uint16 timeout)
{
IINCHIP_WRITE(RTR0,(uint8)((timeout & 0xff00) >> 8));
IINCHIP_WRITE((RTR0 + 1),(uint8)(timeout & 0x00ff));
}

/**
@brief This function set the number of Retransmission.

If there is no response from the peer or delay in response then recorded time
as per RTR & RCR register seeting then time out will occur.
*/
void setRCR(uint8 retry)
{
IINCHIP_WRITE(RCR,retry);
}

/**
@brief This function set the interrupt mask Enable/Disable appropriate Interrupt. (‘1’ : interrupt enable)

If any bit in IMR is set as ‘0’ then there is not interrupt signal though the bit is
set in IR register.
*/
void setIMR(uint8 mask)
{
IINCHIP_WRITE(IMR,mask); // must be setted 0x10.
}

/**
@brief These below functions are used to get the Gateway, SubnetMask
and Source Hardware Address (MAC Address) and Source IP address
*/
void getGAR(uint8 * addr)
{
addr[0] = IINCHIP_READ(GAR0);
addr[1] = IINCHIP_READ(GAR0+1);
addr[2] = IINCHIP_READ(GAR0+2);
addr[3] = IINCHIP_READ(GAR0+3);
}
void getSUBR(uint8 * addr)
{
addr[0] = IINCHIP_READ(SUBR0);
addr[1] = IINCHIP_READ(SUBR0+1);
addr[2] = IINCHIP_READ(SUBR0+2);
addr[3] = IINCHIP_READ(SUBR0+3);
}
void getSHAR(uint8 * addr)
{
addr[0] = IINCHIP_READ(SHAR0);
addr[1] = IINCHIP_READ(SHAR0+1);
addr[2] = IINCHIP_READ(SHAR0+2);
addr[3] = IINCHIP_READ(SHAR0+3);
addr[4] = IINCHIP_READ(SHAR0+4);
addr[5] = IINCHIP_READ(SHAR0+5);
}
void getSIPR(uint8 * addr)
{
addr[0] = IINCHIP_READ(SIPR0);
addr[1] = IINCHIP_READ(SIPR0+1);
addr[2] = IINCHIP_READ(SIPR0+2);
addr[3] = IINCHIP_READ(SIPR0+3);
}

/**
@brief These below functions are used to get the Destination Hardware Address (MAC Address), Destination IP address and Destination Port.
*/
void getSn_DHAR(SOCKET s, uint8 * addr)
{
addr[0] = IINCHIP_READ(Sn_DHAR0(s));
addr[1] = IINCHIP_READ(Sn_DHAR0(s)+1);
addr[2] = IINCHIP_READ(Sn_DHAR0(s)+2);
addr[3] = IINCHIP_READ(Sn_DHAR0(s)+3);
addr[4] = IINCHIP_READ(Sn_DHAR0(s)+4);
addr[5] = IINCHIP_READ(Sn_DHAR0(s)+5);
}
void setSn_DHAR(SOCKET s, uint8 * addr)
{
IINCHIP_WRITE((Sn_DHAR0(s) + 0),addr[0]);
IINCHIP_WRITE((Sn_DHAR0(s) + 1),addr[1]);
IINCHIP_WRITE((Sn_DHAR0(s) + 2),addr[2]);
IINCHIP_WRITE((Sn_DHAR0(s) + 3),addr[3]);
IINCHIP_WRITE((Sn_DHAR0(s) + 4),addr[4]);
IINCHIP_WRITE((Sn_DHAR0(s) + 5),addr[5]);
}
void getSn_DIPR(SOCKET s, uint8 * addr)
{
addr[0] = IINCHIP_READ(Sn_DIPR0(s));
addr[1] = IINCHIP_READ(Sn_DIPR0(s)+1);
addr[2] = IINCHIP_READ(Sn_DIPR0(s)+2);
addr[3] = IINCHIP_READ(Sn_DIPR0(s)+3);
}
void setSn_DIPR(SOCKET s, uint8 * addr)
{
IINCHIP_WRITE((Sn_DIPR0(s) + 0),addr[0]);
IINCHIP_WRITE((Sn_DIPR0(s) + 1),addr[1]);
IINCHIP_WRITE((Sn_DIPR0(s) + 2),addr[2]);
IINCHIP_WRITE((Sn_DIPR0(s) + 3),addr[3]);
}
void getSn_DPORT(SOCKET s, uint8 * addr)
{
addr[0] = IINCHIP_READ(Sn_DPORT0(s));
addr[1] = IINCHIP_READ(Sn_DPORT0(s)+1);
}
void setSn_DPORT(SOCKET s, uint8 * addr)
{
IINCHIP_WRITE((Sn_DPORT0(s) + 0),addr[0]);
IINCHIP_WRITE((Sn_DPORT0(s) + 1),addr[1]);
}

/**
@brief This sets the maximum segment size of TCP in Active Mode), while in Passive Mode this is set by peer
*/
void setSn_MSS(SOCKET s, uint16 Sn_MSSR0)
{
IINCHIP_WRITE(Sn_MSSR0(s),(uint8)((Sn_MSSR0 & 0xff00) >> 8));
IINCHIP_WRITE((Sn_MSSR0(s) + 1),(uint8)(Sn_MSSR0 & 0x00ff));
}

void setSn_TTL(SOCKET s, uint8 ttl)
{
IINCHIP_WRITE(Sn_TTL(s), ttl);
}

/**
@brief These below function is used to setup the Protocol Field of IP Header when
executing the IP Layer RAW mode.
*/
void setSn_PROTO(SOCKET s, uint8 proto)
{
IINCHIP_WRITE(Sn_PROTO(s),proto);
}

/**
@brief get socket interrupt status

These below functions are used to read the Interrupt & Soket Status register
*/
uint8 getSn_IR(SOCKET s)
{
// printf(“Sn_IR(s)=%d\r\n”,Sn_IR(s));
return IINCHIP_READ(Sn_IR(s));
}

/**
@brief get socket interrupt status

These below functions are used to read the Interrupt & Soket Status register
*/
void setSn_IR(SOCKET s, uint8 flag)
{
// printf(“Sn_IR(s)=%d\r\n”,Sn_IR(s));
IINCHIP_WRITE(Sn_IR(s),flag);
}

/**
@brief get socket status
*/
uint8 getSn_SR(SOCKET s)
{
return IINCHIP_READ(Sn_SR(s));
}

/**
@brief get socket TX free buf size

This gives free buffer size of transmit buffer. This is the data size that user can transmit.
User shuold check this value first and control the size of transmitting data
*/
uint16 getSn_TX_FSR(SOCKET s)
{
uint16 val=0,val1=0;
do
{
val1 = IINCHIP_READ(Sn_TX_FSR0(s));
val1 = (val1 << 8) + IINCHIP_READ(Sn_TX_FSR0(s) + 1);
if (val1 != 0)
{
val = IINCHIP_READ(Sn_TX_FSR0(s));
val = (val << 8) + IINCHIP_READ(Sn_TX_FSR0(s) + 1);
}
} while (val != val1);
return val;
}

/**
@brief get socket RX recv buf size

This gives size of received data in receive buffer.
*/
uint16 getSn_RX_RSR(SOCKET s)
{
uint16 val=0,val1=0;
// printf(“getSn_RX_RSR geldi\r\n”);
// while(1);
do
{
val1 = IINCHIP_READ(Sn_RX_RSR0(s));
val1 = (val1 << 8) + IINCHIP_READ(Sn_RX_RSR0(s) + 1);
if(val1 != 0)
{
val = IINCHIP_READ(Sn_RX_RSR0(s));
val = (val << 8) + IINCHIP_READ(Sn_RX_RSR0(s) + 1);
}
} while (val != val1);
return val;
}

/**
@brief This function is being called by send() and sendto() function also.

This function read the Tx write pointer register and after copy the data in buffer update the Tx write pointer
register. User should read upper byte first and lower byte later to get proper value.
*/
void send_data_processing(SOCKET s, uint8 *data, uint16 len)
{
uint16 ptr;
ptr = IINCHIP_READ(Sn_TX_WR0(s));
ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_TX_WR0(s) + 1);
write_data(s, data, (uint8 *)(ptr), len);
ptr += len;
IINCHIP_WRITE(Sn_TX_WR0(s),(uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE((Sn_TX_WR0(s) + 1),(uint8)(ptr & 0x00ff));
}

/**
@brief This function is being called by recv() also.

This function read the Rx read pointer register
and after copy the data from receive buffer update the Rx write pointer register.
User should read upper byte first and lower byte later to get proper value.
*/
void recv_data_processing(SOCKET s, uint8 *data, uint16 len)
{
uint16 ptr;
ptr = IINCHIP_READ(Sn_RX_RD0(s));
ptr = ((ptr & 0x00ff) << 8) + IINCHIP_READ(Sn_RX_RD0(s) + 1);
#ifdef DEF_IINCHIP_DBG
// printf(“ISR_RX: rd_ptr : %.4x\r\n”, ptr);
#endif
read_data(s, (uint8 *)ptr, data, len); // read data
ptr += len;
IINCHIP_WRITE(Sn_RX_RD0(s),(uint8)((ptr & 0xff00) >> 8));
IINCHIP_WRITE((Sn_RX_RD0(s) + 1),(uint8)(ptr & 0x00ff));
}

/**
@brief for copy the data form application buffer to Transmite buffer of the chip.

This function is being used for copy the data form application buffer to Transmite
buffer of the chip. It calculate the actual physical address where one has to write
the data in transmite buffer. Here also take care of the condition while it exceed
the Tx memory uper-bound of socket.
*/
void write_data(SOCKET s, vuint8 * src, vuint8 * dst, uint16 len)
{
unsigned long size;
unsigned long dst_mask;
uint8 * dst_ptr;

dst_mask = (unsigned long)dst & getIINCHIP_TxMASK(s);
dst_ptr = (uint8 *)(getIINCHIP_TxBASE(s) + dst_mask);

if (dst_mask + len > getIINCHIP_TxMAX(s)) 
{
	size = getIINCHIP_TxMAX(s) - dst_mask;
	wiz_write_buf((unsigned long)dst_ptr, (uint8*)src, size);
	src += size;
	size = len - size;
	dst_ptr = (uint8 *)(getIINCHIP_TxBASE(s));
	wiz_write_buf((unsigned long)dst_ptr, (uint8*)src, size);
} 
else
{
	wiz_write_buf((unsigned long)dst_ptr, (uint8*)src, len);
}

}

/**
@brief This function is being used for copy the data form Receive buffer of the chip to application buffer.

It calculate the actual physical address where one has to read
the data from Receive buffer. Here also take care of the condition while it exceed
the Rx memory uper-bound of socket.
*/
void read_data(SOCKET s, vuint8 * src, vuint8 * dst, uint16 len)
{
unsigned long size;
unsigned long src_mask;
uint8 * src_ptr;

src_mask = (unsigned long)src & getIINCHIP_RxMASK(s);
src_ptr = (uint8 *)(getIINCHIP_RxBASE(s) + src_mask);

if( (src_mask + len) > getIINCHIP_RxMAX(s) ) 
{
	size = getIINCHIP_RxMAX(s) - src_mask;
	wiz_read_buf((unsigned long)src_ptr, (uint8*)dst,size);
	dst += size;
	size = len - size;
	src_ptr = (uint8 *)(getIINCHIP_RxBASE(s));
	wiz_read_buf((unsigned long)src_ptr, (uint8*) dst,size);
} 
else
{
	wiz_read_buf((unsigned long)src_ptr, (uint8*) dst,len);
}

}

#ifdef DEF_IINCHIP_PPP
/bu kod aynen çikarildi/
#endif
[/code]

You’ll also find 3 *.pcapng files at [url]http://sdrv.ms/19BOxba[/url]:
When modem connects to Hercules via Port 502, everything is OK.
When Scada connects to PLC via Port 502, everything is OK.
When modem connects to PLC via Port 502, no SYN, SYN/ACK, ACK packets.

I also applied ARP Erratas and nothing changed.
Pls help in a hurry.
Thanks.

Hi, svsbaris.

You can download our fixed driver.
[url]https://www.wiznet.co.kr:8011/Admin_Root/UpLoad_Files/BoardFiles/W5100_DV_V180(0).zip[/url]

But it is fixed only erratum 3. Because if it is fixed erratum2, it cannot use broadcasting.

Best regards.

Hi hjjeon0609,
Pls explain me how can I connect to Hercules via port 502 successfully without any change while I can’t connect to PLC via port 502?
I haven’t any problem with Hercules but with same source code, I can’t connect to PLC because I can’t get reply of ARP Request as you seen in [url]http://sdrv.ms/19BOxba[/url].
What may be the problem?
What’s the difference?
I don’t understand because there is no change in source code.
I also applied your fixed driver. The result is same neither I applied your fixed driver nor not: Connection to hercules is OK but not to PLC.
Thanks.

Hi, svsbaris.

Fixed driver information :
In w5100.c
Modified setSUBR. Added clearSUBR, applySUBR

In socket.c
Modified connect(), sendto()

It is difference.

We already tested driver so I think it is not the problem of driver.

Could I get where did you capture pcap file?? and physical network configuration and w5100 reply ARP packet or not???

Best regards.

Hi svsbaris,

I examined the latest source code and capture files which you posted on this forum.
And I found something strange in your capture files.

<Something strange #1>
If you see “PC_Scada to PLC(port_502).pcapng” and “Modem to PLC(port_502).pcapng”, then you can find some difference out there.

There is only one ARP request from your PC at line no. 171 in “PC_Scada to PLC” but twice ARP requests are there at line no. 90 ~ 91, 93 ~ 94, 95~96 and so on in “Modem to PLC…”.
It looks strange that there are two ARP requests within 1ms at every try.

<Something strange #2>
There are many two successive ARP requests from W5100 in both of “Modem to PLC” and “Modem to Hercules”.
But the result is different.
ARP request packet which W5100 made has 60 bytes including 18 bytes 0’ padding, but one which PC made has 42 bytes and there is no padding.
60 bytes ARP request packet follows the standard.
I don’t know why Hercules accepted ARP request having 60 bytes length from W5100 but PLC couldn’t.

So, I want to look through your source code including main routine and w5100 driver.
And I want to know the network configuration which consists of PC, PLC, Modem, Gateway and so on.
Finally, I want to know the test result when you connect PLC and Modem directly.

Could you send me all material?
This is my email address,
jameskim@wiznet.co.kr

I hope your additional information.

Thank you.

javakys