W5500 stuck on Socket Close Function - while( getSn_CR(sn) )

Hello,

I am using the W5500 chip as a module and connected it to the Nuvoton M032 chip. I checked the SPI connections. No matter what I do, I can’t get past the following line. The code keeps getting stuck on this line → while( getSn_CR(sn) );
This line is inside this function
socket() → close() → while( getSn_CR(sn) );

For this reason, I cannot create a TCP Server or client application.

When I examine the return value of this function, it gives the following values: 0x01, 0x02 and continues to give 0x01.

Server Program: Hercules
PC IP: 192, 168, 1, 106
Port: 7000

My codes are as follows.

Thanks.
Best regards.

#include "main.h"

#include "wizchip_conf.h"
#include "socket.h"

uint8_t WIZNET_SPI_Read_Byte(void)
{
	/* Check SPI0 busy status */
	while (USPI_IS_BUSY(SD_SPIx));
	
	/* Read received data */
	return (USPI_READ_RX(SD_SPIx) & 0xFF);
}

void WIZNET_SPI_Write_Byte(uint8_t data)
{
	/* Write Byte */
	USPI_WRITE_TX(SD_SPIx, data);

	/* Check SPI0 busy status */
	while (USPI_IS_BUSY(SD_SPIx)); 
}

uint8_t serverIP[4] = { 192, 168, 1, 106 };
uint16_t serverPort = 7000;

int main(void)
{
	SYSTEM_Initialize();
	
	SPI_Init(SD_SPIx, SPI_CLK_FREQ);
	
	WIZNET_RESET_LOW();
	Delay_ms(5);
	WIZNET_RESET_HIGH();

	SPI_CS_High();
	reg_wizchip_cs_cbfunc(SPI_CS_Low, SPI_CS_High);
	reg_wizchip_spi_cbfunc(WIZNET_SPI_Read_Byte, WIZNET_SPI_Write_Byte);
	
	uint8_t memsize[2][8] = { {2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2} };
	uint8_t tmp;
		
	if(ctlwizchip(CW_INIT_WIZCHIP, (void*)memsize) == -1)
	{
		//myprintf("WIZCHIP Initialized fail.\r\n");
		LED_On();
		while(1);
	}
	/* PHY link status check */
	do {
		if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1)
		{
			//printf("Unknown PHY Link status.\r\n", 1, 10);
			while(1);
		}
	} while (tmp == PHY_LINK_OFF);
	
	wiz_NetInfo netInfo = { .mac  = { 0x2C, 0xF7, 0xF1, 0x08, 0x00, 0x9A },		// Mac address
									.ip 	= { 192, 168, 1, 31 },								// IP address
									.sn 	= { 255, 255, 255, 0 },								// Subnet mask
									.gw 	= { 192, 168, 1, 1 },
									.dns  = { 0, 0, 0, 0 },
									.dhcp = NETINFO_STATIC };						

	wizchip_setnetinfo(&netInfo);
	wizchip_getnetinfo(&netInfo);	
							
	while (1)
	{  			
		ret = socket(sn, Sn_MR_TCP, serverPort, 0x00);  // STUCK HERE !
		LED_On();
        }
}



Prove that SPI communication functions properly by reading VERSIONR register and getting 0x01, 0x02, 0x03 and 0x04.

This is the SPI timing for tihs code its okay for chip version! But what is the problem :frowning:

SYSTEM_Initialize();
	
	SPI_Init(SD_SPIx, SPI_CLK_FREQ);
		
	WIZNET_RESET_HIGH();
	Delay_ms(250);
		
		
	SPI_CS_Low();
	
	USPI_WRITE_TX(SD_SPIx, 0x00);
	while (USPI_IS_BUSY(USPI0));
		
	USPI_WRITE_TX(SD_SPIx, 0x39);
	while (USPI_IS_BUSY(USPI0));
	
	USPI_WRITE_TX(SD_SPIx, 0xFF);
	while (USPI_IS_BUSY(USPI0));
	version[0] = (USPI_READ_RX(USPI0) & 0xFF);	
	
	USPI_WRITE_TX(SD_SPIx, 0x00);
	while (USPI_IS_BUSY(USPI0));
	version[1] = (USPI_READ_RX(USPI0) & 0xFF);

	USPI_WRITE_TX(SD_SPIx, 0x00);
	while (USPI_IS_BUSY(USPI0));
	version[2] = (USPI_READ_RX(USPI0) & 0xFF);	
	
	USPI_WRITE_TX(SD_SPIx, 0x00);	
	while (USPI_IS_BUSY(USPI0));
	version[3] = (USPI_READ_RX(USPI0) & 0xFF);
		
	SPI_CS_High();

What is the value of sn here? Not the one you may think of, but real value reported by the MCU?

sn = 0;

But reading the version of chip

register level code returns 0x04. It ok as you can see in my previous message (Logic Analyzer)

But this function returns 0x01 → chipVersion = getVERSIONR();

Is this a SPI function problem ?

Then look at what is going on the bus when you perform this call. Did you select the right chip within the library?

Yes there is W5500. Its ok.

Oh my god what is this function?

#include "main.h"

#include "wizchip_conf.h"
#include "socket.h"

uint8_t WIZNET_SPI_Read_Byte(void);
void WIZNET_SPI_Write_Byte(uint8_t data);

uint8_t chipVersion = 0;

int main(void)
{
	SYSTEM_Initialize();
	
	SPI_Init(SD_SPIx, SPI_CLK_FREQ);
		
	WIZNET_RESET_LOW();
	Delay_ms(250);
	WIZNET_RESET_HIGH();
	Delay_ms(250);
	SPI_CS_High();
		
	reg_wizchip_cs_cbfunc(SPI_CS_Low, SPI_CS_High);
	reg_wizchip_spi_cbfunc(WIZNET_SPI_Read_Byte, WIZNET_SPI_Write_Byte);

	chipVersion = getVERSIONR();

	while (1)
	{  				
		
	}
}

/**
 * @brief
 * @param
 * @retval
 */
void SYSTEM_Initialize(void)
{
	General_Init();
}

uint8_t WIZNET_SPI_Read_Byte(void)
{
	/* Check SPI0 busy status */
	while (USPI_IS_BUSY(SD_SPIx));
	
	/* Read received data */
	return (USPI_READ_RX(SD_SPIx) & 0xFF);
}

void WIZNET_SPI_Write_Byte(uint8_t data)
{
	/* Write Byte */
	USPI_WRITE_TX(SD_SPIx, data);

	/* Check SPI0 busy status */
	while (USPI_IS_BUSY(SD_SPIx));
}

this function cannot read the last byte ( chipVersion = getVERSIONR(); )

Your definition is framed within #ifndef. You are not guaranteed to have exactly this value defined if it was defined somewhere else beforehand. Dig into library and put diagnostic outputs into its flow to prove it does required thing.

I did but there is no change

If you’d do this (second thing I said) you’d know how getVERSIONR(); works for you, what it does, and where’s a problem.

Something feels wrong in the library.
I think the SPI buffer is not being cleared.
That’s why I cleaned it by reading after each sending process.

uint8_t  WIZCHIP_READ(uint32_t AddrSel)
{
   uint8_t ret;
   uint8_t spi_data[3];

   WIZCHIP_CRITICAL_ENTER();
   WIZCHIP.CS._select();

   AddrSel |= (_W5500_SPI_READ_ | _W5500_SPI_VDM_OP_);

   if(!WIZCHIP.IF.SPI._read_burst || !WIZCHIP.IF.SPI._write_burst) 	// byte operation
   {
	   WIZCHIP.IF.SPI._write_byte((AddrSel & 0x00FF0000) >> 16);
		ret = WIZCHIP.IF.SPI._read_byte(); // ADDED
		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x0000FF00) >>  8);
		ret = WIZCHIP.IF.SPI._read_byte(); // ADDED
		WIZCHIP.IF.SPI._write_byte((AddrSel & 0x000000FF) >>  0);
		ret = WIZCHIP.IF.SPI._read_byte(); // ADDED
   }
   else																// burst operation
   {
		spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
		spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
		spi_data[2] = (AddrSel & 0x000000FF) >> 0;
		WIZCHIP.IF.SPI._write_burst(spi_data, 3);
   }
	WIZCHIP.IF.SPI._write_byte(0); // ADDED - WRITE DUMMY FOR READ (GENERATE SPI CLOCK)
   ret = WIZCHIP.IF.SPI._read_byte();

   WIZCHIP.CS._deselect();
   WIZCHIP_CRITICAL_EXIT();
   return ret;
}

I can connect now!
But a new problem arose.

When I send data with the send function after the connection process, the data is sent only once. When I want to send it later, the send function returns the following value
#define SOCKERR_SOCKSTATUS (SOCK_ERROR - 7) ///< Invalid socket status for socket operation.

#include "main.h"

#include "wizchip_conf.h"
#include "socket.h"

uint8_t WIZNET_SPI_Read_Byte(void);
void WIZNET_SPI_Write_Byte(uint8_t data);

uint8_t serverIP[4] = { 192, 168, 1, 106 };
uint16_t serverPort = 5002;

uint8_t chipVersion = 0;
uint8_t memsize[2][8] = { {2, 2, 2, 2, 2, 2, 2, 2}, {2, 2, 2, 2, 2, 2, 2, 2} };
uint8_t tmp;
uint8_t sn = 3;

uint8_t socketStatus = 0xFF;
int8_t connectionStatus = -1;
int32_t sendStatus = -1;
	
uint8_t sendBuff[2] = {'S', 'A'};
	
int main(void)
{
	SYSTEM_Initialize();
	
	SPI_Init(SD_SPIx, SPI_CLK_FREQ);
		
	WIZNET_RESET_LOW();
	Delay_ms(250);
	WIZNET_RESET_HIGH();
	Delay_ms(250);
	SPI_CS_High();
		
	reg_wizchip_cs_cbfunc(SPI_CS_Low, SPI_CS_High);
	reg_wizchip_spi_cbfunc(WIZNET_SPI_Read_Byte, WIZNET_SPI_Write_Byte);

	chipVersion = getVERSIONR();
	
	// Init WIZNET W5500
	if(ctlwizchip(CW_INIT_WIZCHIP, (void*)memsize) == -1)
	{
		//myprintf("WIZCHIP Initialized fail.\r\n");
		while(1);
	}
	
	// PHY link status check
	do {
		if(ctlwizchip(CW_GET_PHYLINK, (void*)&tmp) == -1)
		{
			//printf("Unknown PHY Link status.\r\n", 1, 10);
			while(1);
		}
	} while (tmp == PHY_LINK_OFF);

	wiz_NetInfo netInfo = { .mac  = { 0x2C, 0xF7, 0xF1, 0x08, 0x00, 0x9A },		// Source Mac Address
									.ip 	= { 192, 168, 1, 31 },								// Source IP Address
									.sn 	= { 255, 255, 255, 0 },								// Subnet mask
									.gw 	= { 192, 168, 1, 1 }, 								// Gateway IP Address
									.dns  = { 0, 0, 0, 0 }, 									// DNS server IP Address		
									.dhcp = NETINFO_STATIC };									// 1 - Static, 2 - DHCP
	
	wiz_NetInfo	getInfo;
									
	wizchip_setnetinfo(&netInfo);
	wizchip_getnetinfo(&getInfo);
				
	while (socketStatus != sn)
	{
		socketStatus = socket(sn, Sn_MR_TCP, serverPort, SF_TCP_NODELAY);
	}
	
	while (connectionStatus != SOCK_OK)
	{
		connectionStatus = connect(sn, (uint8_t *)serverIP, serverPort);
	}
						
	while (1)
	{  				
		sendStatus = send(sn, sendBuff, 2);
		
		if (sendStatus < 0) 
		{
			close(sn);
			LED_On();
		}
		
		Delay_ms(500);
	}
}

/**
 * @brief
 * @param
 * @retval
 */
void SYSTEM_Initialize(void)
{
	General_Init();
}

uint8_t WIZNET_SPI_Read_Byte(void)
{
	/* Check SPI0 busy status */
	while (USPI_IS_BUSY(SD_SPIx));

	/* Read received data */
	return (USPI_READ_RX(SD_SPIx) & 0xFF);
}

void WIZNET_SPI_Write_Byte(uint8_t data)
{
	/* Write Byte */
	USPI_WRITE_TX(SD_SPIx, data);

	/* Check SPI0 busy status */
	while (USPI_IS_BUSY(SD_SPIx));
}

What does it mean “later”? What status the socket has when this “later” happens?

sorry for wrong explanation :slight_smile:
It sends data only once, but when I try to send it a second time, it gives the -7 error.

What is the socket status when you try doing it? May happen socket is already in the state when sending is not allowed/possible.

For this code socketStatus = 0;

while (socketStatus != sn)
	{
		socketStatus = socket(sn, Sn_MR_TCP, serverPort, SF_TCP_NODELAY);
	}
	
	while (connectionStatus != SOCK_OK)
	{
		connectionStatus = connect(sn, (uint8_t *)serverIP, serverPort);
	}
						
	while (1)
	{  
		socketStatus = getSn_SR(sn);	
		
		sendStatus = send(sn, sendBuff, 2);
		
		if (sendStatus < 0) 
		{
			LED_On();
		}
		
		Delay_ms(500);
	}

Read about the flow described in the W5100 datasheet.

I use W5500

Did you mean this product? https://docs.wiznet.io/img/products/w5100/W5100_DS_V128E.pdf

Which page i can read?

Chapter 5.

I read the relevant section, but I didn’t fully understand how to proceed. Can you give a hint? :slight_smile: