W5500 undefined states and behaviour

Hello,

I am working on a W5500 TCP server project, based on this Driver, that will allow me to connect and disconnect any number of times. I use the ETH WIZ click board. The W5500 is configured as a TCP sever and it is connected through SPI with an ADSP 21489. The tcp client I use to connect from laptop to server is telnet.

The function that handles the tcp communication is given below. It is called in a for ( ; ; ) loop in the main program.

void tcp_com(uint8_t tcp_socket, c_buffer_t* g_in_tcp_buffer, c_buffer_t* g_out_tcp_buffer, uint16_t port)
{
// socket 0 is used
// port number is 14321 

uint8_t socket_state;
printf("\nMODE REGISTER = %x", getSn_MR(tcp_socket));  // not working without this line

socket_state = getSn_SR(tcp_socket); /* Get the state of the socket*/

switch (socket_state)
{
	//******************************** SOCK_ESTABLISHED **********************************************
	case SOCK_ESTABLISHED:  

		//printf("ESTABLISHED STATE\n");

		if (g_socket_status[tcp_socket] == SOCK_LISTEN)
		{
			setSUBR(SubNet1);
			printf("\nServer connection established via SOCKET %d\n", tcp_socket);
			g_socket_status[tcp_socket] = SOCK_ESTABLISHED;
		}

		if ((getSn_RX_RSR(tcp_socket) >= 11))
		{
			/* If there is any received data, process it */
			receive_pakages(tcp_socket, g_in_tcp_buffer);
		}

		if (c_buffer_available_data(g_out_tcp_buffer) > 0)
		{
			int ret = transmit_packages_core(tcp_socket, g_out_tcp_buffer);

			if (ret > 0 && ret < g_send_length)
			{
				printf("\nShould send %d, send %d", g_send_length, ret);
				while (ret != g_send_length)
				{
					g_resend_length = retransmit_packages_core(tcp_socket);
					if (g_resend_length > 0)
					{
						ret += g_resend_length;
					}
					else if (g_resend_length == ERROR_WINDOW_FULL)
					{
						printf("\nWindow Full");
						close(tcp_socket);
						printf("\nTCP Socket Closed!!");
					}
					else
					{
						break;
					}
				}
			}
		}
	break;

	//******************************** SOCK_CLOSE_WAIT **********************************************
	case SOCK_CLOSE_WAIT:
		printf("\r\nSOCKET %d : CLOSE_WAIT", tcp_socket);
		disconnect(tcp_socket);
	break;

	//*********************************** SOCK_CLOSED **********************************************
	case SOCK_CLOSED:
		printf("\nSocket closed!");

		close(tcp_socket); 
		if (g_socket_status[tcp_socket] != SOCK_CLOSED)
		{
			setup_conn();
		}
		g_socket_status[tcp_socket] = SOCK_CLOSED;

		if (socket(tcp_socket, Sn_MR_TCP, port, 0x00) == 0)
		{
			printf("\r\n%d : Failed to create socket.", tcp_socket);
		}
	break;

	//*********************************** SOCK_INIT ************************************************
	case SOCK_INIT:
	{
		int result = listen(tcp_socket);
		if (1 == result)
		{
			printf("\nError entering into listen mode!");
		}
		printf("\r\nSOCKET %d : LISTEN", tcp_socket);
		g_socket_status[tcp_socket] = SOCK_INIT;
	}
	break;

	//*********************************** SOCK_LISTEN ***********************************************
	case SOCK_LISTEN:
	{
		/* socket is in the listening state. */
		g_socket_status[tcp_socket] = SOCK_LISTEN;
		//printf("LISTEN STATE\n");
		g_count_retry++;
		if (g_count_retry >= CONN_RETRY_PERIOD)
		{
			printf("\nOne retry period over!");
			g_count_retry = 0;
			/* Re-initialize W5200. */
			setup_conn();
			g_socket_status[tcp_socket] = SOCK_CLOSED;

			if (socket(tcp_socket, Sn_MR_TCP, port, 0x00) == 0)
			{
				printf("\r\n%d : Failed to create socket.", tcp_socket);
			}
		}
	}
	break;

	//************************************* DEFAULT ***********************************************
	default:
		printf("\nSocket state = %x", socket_state);
	break;
  }
}

The problems are:

  • If I comment out the printf() line from the top of the function body, the socket_state variable will have state values that are not defined in datasheet (like 0x04, 0x28 or 0x2e).

  • If I don’t comment that printf() statement, the server will enter in LISTEN MODE, but it will accept a random number n of connect-disconnect cycles (n is usually between 2 and 15) . In the n+1 attempt to connect, the server does not respond and remains stuck in LISTEN MODE, even though I try to connect using the tcp client (I get “Connect failed” error) and the only solution is a manual reset. In this situation, ping usually doesn’t work, but I encountered situations in which it worked.

I think that all this random behaviour is caused by some timing or configuration issues, but I can’t figure out a solution. I hope you will give me some hints to solve those problems.

Thank you !

It may happen that there’s some mistake in the code design, and it branches the way it is not innteded to. Perform the following: into each condition of case put some printf which will be logging the branch currently being executed; when communication will fail get the log and analyze how execution flow is being performed to see if there’re some situations causing misbehave.

Dear flonas

I checked TCP Server function in WIZ550SR module.
But I couldn’t find any problem.
I think there is another cause.
Please make sure SPI interface between DSP and W5500.
(SPI CLK speed, SPI driver source of DSP etc…)

I used WIZ550SR module for testing.

http://wizwiki.net/wiki/doku.php?id=products:wiz550sr:start

As you know, printf() has nothing to do with the problem.

I changed source code to the following.

int32_t loopback_tcps(uint8_t sn, uint8_t* buf, uint16_t port)
{
uint8_t socket_state;
printf(“\nMODE REGISTER = %x”, getSn_MR(sn)); // Case 1
//printf(“\nMODE REGISTER = %x”, getSn_MR(sn)); // Case 2

socket_state = getSn_SR(sn);

#ifdef LOOPBACK_DEBUG
uint8_t destip[4];
uint16_t destport;
#endif

//switch(getSn_SR(sn))
switch(socket_state)
{
case SOCK_ESTABLISHED :

Thanks.

It seems that every printf() I put changes the behaviour of the program, so this method doesn’t help me too much.

One thing I noticed is that removing some printfs that are displayed frequently, from the tcp handler function, determines the server to go from LISTEN STATE to CLOSED STATE, then back into LISTEN STATE then into CLOSED STATE and so on. During this time, the server appears to accept connections, but I get disconnected after a very short period. Also, ping has losses (25% usually).

I will check the SPI connection to make sure it is well configured. What I don’t understand is why the server doesn’t accept connections while it is into LISTEN MODE and why it sometimes responds, sometimes doesn’t respond, to ping requests when this problem happens.

Please share code of the following functions:

  • disconnect
  • close
  • setup_conn
  • socket
  • listen

Here they are:

functions.zip (1.8 KB)

I found some problems with the SPI mode. Until now, I used SPI in mode 3 (Clock phase = 1 and Clock polarity = 1). But when I change into mode 0 (datasheet mentions that modes 0 and 3 are supported), the ctlnetwork function, that configures the ip and mac, assigns wrong mac and ip addresses (1.1.1.1.1.1, respectively 1.1.1.1).

Can this be determined by something that causes the rest of problems ?

I think SPI inteface is abnormal.
First of all, you have to check SPI inteface and then use W5500.
Actually, I don’t know ADSP 21489. I guess you must change SPI option or SPICLK until operation is normal.

If you want to verify your HW schematic file, please send an email to support@wiznet.io with your file.

Thanks.

I configured the SPI to run in Mode 3 at 10 MHz clock and it works fine. I checked the frequency with an oscilloscope.

On the other hand, Mode 0 is still not functioning, even at 500 KHz. It seems that in this mode, the MISO signal is identical to the CS (chip select) signal, regardless of what data I try to transfer. I guess it’s some chip fault.

After setting and verifying the IP and MAC addresses, I found that W5500 is not always responding to ping. For example, it may respond to 3 ping requensts, but the 4th and 5th time it stops responding. After that, it may start again responding to ping. I checked the PB bit from the Mode register and it is set to zero.

UPDATE: It seems that reading the Sn_SR register in an infinite loop causes the ping problem.

Thanks !

OK, finally I think I found the problem.

After connecting an oscilloscope to the breakout pins, I found out that the connection behaves normally and timing errors dissappeared. After disconnecting the oscilloscope, the problems appear again. Most likely, there’s a problem with the breakout board (some pin floating, I don’t know).

Thank you all for the help given !