(W5500)TCP Client Connect not working with Arduino Library

Hi Everyone,

I’ve been working with the W5500 for a couple of weeks now and everything was going quite well until yesterday. I ported the Wiznet W5500 Arduino library over to Particle for use with Particle Photon and Electron modules. I tested DHCP which worked well and I tested UDP which worked well for sending out broadcast data on the network.

Yesterday I decided to try out TCP clients and connect the W5500 to a server running via Netcat on my Mac. It’s not working yet.

The EthernetClient.connect(IP, port) function always returns 0. It goes into a while loop to check that status() returns SnSR::Established but it never does. status() always returns 0x13 which is SnSR::INIT Here is a block of my code which basically adds print debugs to the connect function:

int EthernetClient::connect(IPAddress ip, uint16_t port, network_interface_t) {
	Serial.println("in connect function");
	if (_sock != MAX_SOCK_NUM){
		Serial.println("_sock != MAX_SOCK_NUM");
		return 0;
	}
	Serial.println("Here");

	for (int i = 0; i < MAX_SOCK_NUM; i++) {
		Serial.println("Inside For Loop");
		uint8_t s = w5500.readSnSR(i);
		if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
			_sock = i;
			break;
		}
	}
	Serial.println("After for loop in connect");

	if (_sock == MAX_SOCK_NUM){
		Serial.println("_sock != MAX_SOCK_NUM, after loop");
		return 0;
	}

	_srcport++;
	if (_srcport == 0){
		_srcport = 1024;
	}
	socket(_sock, SnMR::TCP, _srcport, 0);

	delay(1000);

	byte* lA = (byte*)&ip.raw().ipv4;
	Serial.printf("Attempting to connect to: %i.%i.%i.%i on port %i", lA[3], lA[2], lA[1], lA[0], port);
	if (!::connect(_sock, lA, port)) {
		_sock = MAX_SOCK_NUM;
		return 0;
	}

	while (status() != SnSR::ESTABLISHED) {
		delay(10);
		uint8_t state = status();
		if (state == SnSR::CLOSED) {
			_sock = MAX_SOCK_NUM;
			Serial.println("Got here");
			return 0;
		}else{
			Serial.printf("status() = %02X \n", state);
		}
	}

	return 1;
}

My serial console shows status() = 13 repeatedly until got here prints and the connection fails. Any ideas on this? I can tell you the Particle module runs faster than the Arduino processor from previous experience. Could this be an issue?

I do not immediately see anything wrong with the code. 0x13 is the status after socket is open, and as connect returns with 0x13, I guess it can not/does not proceed to connect. The only educated guess I have is that you pass variable port as 0. I am not sure, I had the case before that connect does not work if destination port is 0.

1 Like

Thanks for the reply @Eugeny

I have the destination port set to 4000. I also added debug code to the connect function which reads back the destination IP and port from the W5500 class. It prints out the correct IP and port number. See revised connect function here where I check the destination IP and port:
int EthernetClient::connect(IPAddress ip, uint16_t port, network_interface_t) {
Serial.println(“in connect function”);
if (_sock != MAX_SOCK_NUM){
Serial.println(“_sock != MAX_SOCK_NUM”);
return 0;
}
Serial.println(“Here”);

	for (int i = 0; i < MAX_SOCK_NUM; i++) {
		Serial.println("Inside For Loop");
		uint8_t s = w5500.readSnSR(i);
		if (s == SnSR::CLOSED || s == SnSR::FIN_WAIT || s == SnSR::CLOSE_WAIT) {
			_sock = i;
			break;
		}
	}
	Serial.println("After for loop in connect");

	if (_sock == MAX_SOCK_NUM){
		Serial.println("_sock != MAX_SOCK_NUM, after loop");
		return 0;
	}

	_srcport++;
	if (_srcport == 0){
		_srcport = 1024;
	}
	socket(_sock, SnMR::TCP, _srcport, 0);

	delay(1000);

	byte* lA = (byte*)&ip.raw().ipv4;
	Serial.printf("Attempting to connect to: %i.%i.%i.%i on port %i", lA[3], lA[2], lA[1], lA[0], port);
	if (!::connect(_sock, lA, port)) {
		_sock = MAX_SOCK_NUM;
		return 0;
	}

	uint8_t ipArray[4];
	w5500.readSnDIPR(_sock, ipArray);
	uint16_t setPort = w5500.readSnDPORT(_sock);
	Serial.printf("_sock IP and port: %i.%i.%i.%i on port %i", ipArray[3], ipArray[2], ipArray[1], ipArray[0], setPort);

	while (status() != SnSR::ESTABLISHED) {
		delay(10);
		uint8_t state = status();
		if (state == SnSR::CLOSED) {
			_sock = MAX_SOCK_NUM;
			Serial.println("Got here");
			return 0;
		}else{
			Serial.printf("status() = %02X \n", state);
		}
	}

	return 1;
}

It prints out correctly as 192.168.1.53 which is my computer’s local IP on the network and port 4000 which is the port I’m listening on. So it seems the IP and port of the server is set correctly but it’s just never succeeding. I also cannot get the TCP server to work on the W5500 either.

Do you check for interrupt flags - do they change at least?
It seems connect function needs to be troubleshot. It would help if you can point to its code.

1 Like

My full port of the Arduino Library thus far is available on this github repo:

Not sure where to check interrupt flags or which ones you are refering to. Can you elaborate? Thank you very much for your help/interest to this point.

Everything seems to be ok. Please perform dump of the register values of the common register block and socket’s register block. You can use

uint8_t W5500Class::read(uint16_t _addr, uint8_t _cb)

function for it. Common register addresses are 0x00 to 0x39, socket register addresses are 0x00 to 0x2f, CB parameter is set as:

  • 0x01 for common register block
  • 0x09 for socket # 0 (you did not mention which socket you use).
1 Like

Hi @Eugeny

Sorry for the ridiculously delayed response. I have been really tied up lately and just got back to this project.

Going through your requests here. _sock in EthernetClient::connect prints out to my serial log as 0. Is that valid?

Why not? There’s such socket 0 and you can use it (properly :slight_smile: )

1 Like

:wink: Thank you for that.

Can you elaborate on how you want me to read the register values you requested?

I am afraid to be not so familiar with libraries you use; please look into “sockets” header files, or “w5500” header file, you should be able to locate W5500 register read call (I am sure there will be comment/verbose description saying so). Then read register one by one and dump to the log.

1 Like

Not seeing a generic read function on the W5500 header or socket. I think what you are looking for is probably in the W5500 header(gut says so anyway). Here it is:
https://github.com/ControlEverythingCom/Wiznet-W5500-Particle/blob/master/src/utility/w5500.h

Nix that. Found the Read function you wanted. It’s a private function.

Yes, right these two are your friends

static uint8_t  read(uint16_t _addr, uint8_t _cb );
static uint16_t read(uint16_t _addr, uint8_t _cb, uint8_t *buf, uint16_t len);

One reads single register, another a set in a row. Please refer to the datasheet to set CB properly.

Hi @Eugeny
Forgive me if I’m being dense and this is not what you were looking for.

Registers for Socket 0:
Register 00 : 01
Register 01 : 00
Register 02 : 00
Register 03 : 13
Register 04 : 04
Register 05 : 01
Register 06 : FF
Register 07 : FF
Register 08 : FF
Register 09 : FF
Register 0A : FF
Register 0B : FF
Register 0C : 00
Register 0D : 00
Register 0E : 00
Register 0F : 00
Register 10 : 00
Register 11 : 00
Register 12 : 05
Register 13 : B4
Register 14 : 00
Register 15 : 00
Register 16 : 80
Register 17 : 00
Register 18 : 00
Register 19 : 00
Register 1A : 00
Register 1B : 00
Register 1C : 00
Register 1D : 00
Register 1E : 02
Register 1F : 02
Register 20 : 08
Register 21 : 00
Register 22 : 00
Register 23 : 00
Register 24 : 00
Register 25 : 00
Register 26 : 00
Register 27 : 00
Register 28 : 00
Register 29 : 00
Register 2A : 00
Register 2B : 00
Register 2C : FF
Register 2D : 40
Register 2E : 00
Register 2F : 00
Register 30 : 01
Register 31 : 00
Register 32 : 00
Register 33 : 00
Register 34 : 00
Register 35 : 00
Register 36 : 00
Register 37 : 00
Register 38 : 00
Register 39 : 00

Common Registers:
Register 00 : 00
Register 01 : 01
Register 02 : 01
Register 03 : A8
Register 04 : C0
Register 05 : 00
Register 06 : FF
Register 07 : FF
Register 08 : FF
Register 09 : DE
Register 0A : AD
Register 0B : BE
Register 0C : EF
Register 0D : FE
Register 0E : ED
Register 0F : 46
Register 10 : 01
Register 11 : A8
Register 12 : C0
Register 13 : 00
Register 14 : 00
Register 15 : 00
Register 16 : 00
Register 17 : 00
Register 18 : 00
Register 19 : 07
Register 1A : D0
Register 1B : 08
Register 1C : 28
Register 1D : 00
Register 1E : 00
Register 1F : 00
Register 20 : 00
Register 21 : 00
Register 22 : 00
Register 23 : 00
Register 24 : 00
Register 25 : 00
Register 26 : FF
Register 27 : FF
Register 28 : 00
Register 29 : 00
Register 2A : 00
Register 2B : 00
Register 2C : 00
Register 2D : 00
Register 2E : BF
Register 2F : 00
Register 30 : 00
Register 31 : 00
Register 32 : 00
Register 33 : 00
Register 34 : 00
Register 35 : 00
Register 36 : 00
Register 37 : 78
Register 38 : 25
Register 39 : 04

Now you can decode info yourself, following information in datasheet:
MR = 0
Gateway = 1.1.168.192, looks very strange, I think it should be 192.168.1.1?
Network mask = 0.255.255.255 - also looks reversed?
MAC address = DE:AD:BE:EF:FE:ED (dead beef feed :slight_smile: )
W5500 IP address = 70.1.168.192 - for sure reversed

Well, I see something strange for sure. Either you get dump in wrong order, or you program registers incorrectly.

Looking to socket registers I see TCP with delayed ACK, open state, and local port 1025. Also note that first octet of local MAC address has bit 1 set.

I’m seeing the same thing with all IPs being reversed. I honestly thought that was normal. This is Wiznet’s Arduino library, I really didn’t touch anything I can think of that would have reversed that. Also I can atest that DHCP is working properly which would have to make use of these reversed IPs right? Heck I don’t know.

Lol that dead beef feed was also straight out of the Arduino library samples. I can’t take comedic credit for that.

Here’s my block of code that prints out the registers. No way it’s wrong, pretty straight forward.

//dump registers for Socket 0.
Serial.println("Registers for Socket 0");
for(int i = 0x00; i < 0x3A; i++){
	Serial.printf("Register %02X : %02X\n", i, read(i, 0x09));
}
Serial.println();
Serial.println("Common Registers");
//dump common registers.
for(int i = 0x00; i < 0x3A; i++){
	Serial.printf("Register %02X : %02X\n", i, read(i, 0x01));
}

I could try passing the server IP in to the client connect function backwards and see if that works I suppose.

Yes, please try doing that.

With DHCP which works using UDP broadcast you actually do not need IP addresses and mask fields I guess. May it be that you read this information from DHCP response packet in wrong way?

OK. I might have fibbed just a little bit earlier when I said I didn’t touch anything. The Ethernet object had calls that required raw IP addresses. The platform I’m working on “Particle” does not have that function like Arduino does so I had to get the raw address in another way. It has a ipv4 function that returns the IP in raw form but as luck would have it it reverses the order of the array for some really stupid reason. Anyway I went through and reversed the array everywhere in the Wiznet library and viola Connected to Server. Pretty stocked at this point.

@Eugeny can’t thank you enough for all the help. Hopefully it’s smooth sailing from here on out(it never is so I’ll talk to you soon :wink:

1 Like

Hello telliottosceola! Is your project “ethernet client secure” working? How can I contact you? Or send me an email: 888voha@gmail.com
Thanks!

Hi @Voha

Yes, I did complete the port to Particle and developed a library for Particle here which works with the Photon. The forum actually will not let me post a link to the repo for some reason but just search GitHub for Wiznet-W5500-Particle
If you are using build.particle.io then just search libraries for NCD_Ethernet_Overlay. We developed the library to work with this Wiznet based Ethernet overlay module we manufacture.

1 Like