W5500 Sn_SR always stays 0x00, Sn_CR never clears

Hello friends, I am having issues with my TCP server on a W5500. My SN_SR register always stays at 0x00 and the Sn_CR register never clears. I am able to ping the device on the network and SPI seems to be working correctly. I have written the following snippet of code in order to test the Sn_SR register:

int1 done = FALSE;
uint16_t timeout;
do
{
timeout = 100;
setSn_MR(sn, Sn_MR_TCP);
setSn_PORT(sn, 5000);
setSn_CR(sn, Sn_CR_OPEN);

	while(getSn_SR(sn) != SOCK_INIT)
	{
		if(--timeout == 0)
			break;
		
		delay_ms(100);
	}
	
	if(getSn_SR(sn) != SOCK_INIT)
		setSn_CR(sn, Sn_CR_CLOSE);
	else
		done = TRUE;

  delay_ms(10000);
} while(!done);

I am using a PIC24EP512
Thank you for reading, any help is greatly appreciated!

Socket closed

You do not test for it in the code provided

You must ensure you do preparations properly. You reset the chip using RESET pin per specification, and optionally perform software reset using MR. I am not 100% sure if that may be the case, but you should set basic properties for the networking communication like MAC address.

This is the second thing to prove after you ensure proper reset by reading VERSIONR register. If SPI does not work as expected, you may simply read/write to wrong locations within the chip causing undefined behavior.

Thank you for your response. I apologize for failing to provide some information as I am new to the embedded world. I have now done a reset at the start of the program my version register reads 0x04.
version reg

This is should be setting the socket registers
setSn_MR(sn, Sn_MR_TCP);
setSn_PORT(sn, 5000);
setSn_CR(sn, Sn_CR_OPEN);

delay_ms(5000);
printf(“\r\nTHIS IS VALUE OF Sn_MR: %02X\r\n”, getSn_MR(sn));
printf(“\r\nVALUE OF Sn_CR: 0x%02X\r\n”, getSn_CR(sn));
printf(“\r\nVALUE OF Sn_SR: 0x%02X\r\n”, getSn_SR(sn));

This is how it is actual behaving
Port, MR, CR setting

This is how it reads once it enters the loop to evaluate if Sn_SR is set to SOCK_INIT
Stuck in the loop

SPI should be working as I am able to write network configs to the proper registers.
SPI gateway
One thing of note is I can write all the needed registers except for 0x0010 that is needed for the IP. I’m assume this could be a part of my problem.

Thank you for the help, I apologize if anything is unclear.

Byte order is confused for address. Hopefully mistake is in printf.

Now compare address for Sn_CR in the datasheet with the address your program displays. If byte order is confused, you are trying to read location 0xa800, then 0xa801 etc. and of course you get garbage. You must provide chip with address and BSB/RWB/OM information before you can access the register.

If 0xa8 is control byte, then you address “Socket 2 TX Buffer” space.

uint8_t WIZCHIP_READ(uint32_t AddrSel) {
uint8_t spi_data[4];
uint8_t spi_rData[4];
printf(“\r\nWIZCHIP_READ: Entering function with address 0x%04X\r\n”, AddrSel);

// Construct SPI command (address phase)

spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
spi_data[2] = ((make8(AddrSel, 0) & 0x1F) << 3) | 0x00;
spi_data[3] = 0x00;

// Read data phase
 //select
 output_low(W5500_CS_PIN);
 
 //transfer
 spi_transfer(spi_data, spi_rData, 4);
 
 //deselcet
 output_high(W5500_CS_PIN);

return spi_rData[3];

}

void WIZCHIP_WRITE(uint32_t AddrSel, uint8_t data) {
uint8_t spi_data[4];

 printf("\r\nWIZCHIP_WRITE AFTER ASSIGNMENT: Entering function with address 0x%04X\r\n", AddrSel);

output_low(W5500_CS_PIN);

// Construct SPI command (address phase)
spi_data[0] = (AddrSel & 0x00FF0000) >> 16;
 spi_data[1] = (AddrSel & 0x0000FF00) >> 8;
 spi_data[2] = ((make8(AddrSel, 0) & 0x1F) << 3) | 0x04;
 spi_data[3] = data;
	
	output_low(W5500_CS_PIN);
	spi_transfer_write(spi_data, 4);
	output_high(W5500_CS_PIN);

}
This is what my read and write functions look like

Display SPI data instead of address in the debug and see if it matches the location/operation you assume it performs.

Yeah my SPI data is complete junk. I’m not sure how I should go about writing a read and write function that accomplishes targeting the socket registers. The ioLibary code doesnt seem to be working correctly. It seems like the control byte is off.

WIZCHIP_SOCKET_WRITE(0x5000, 0x01);
to write 0x01 to socket register 5
ADDRESS HIGH BYTE: 00

ADDRESS LOW BYTE: 50

CONTROL BYTE: 04

WRITTEN BYTE: 01

to write 0x01 to socket 3 register 5

WIZCHIP_SOCKET_WRITE(0x500 | (0x0d << 3), 0x01);

or

WIZCHIP_SOCKET_WRITE((chip_address << 8) | (bsb << 3), 0x01);

This seems to be working ok for the write function, however read seems to be off. First set is write the second is read. I appreciate your help.
ADDRESS HIGH BYTE: 00

ADDRESS LOW BYTE: 05

CONTROL BYTE: 6C

WRITTEN BYTE: 01

ADDRESS HIGH BYTE: 00

ADDRESS LOW BYTE: 00

CONTROL BYTE: 68

THIS IS THE VALUE OF SOCKET 5: 03

I was wrong

WIZCHIP_SOCKET_WRITE((chip_address << 8) | bsb, 0x01)

because bsb is already <<3 in the functions. What we are doing now is not related to W5500, but relates to just C and code of the functions you currently have. Your task is providing address, bsb and data into there in proper format. Note you must use appropriate address and bsb per datasheet’s chapter 3 to address specific data.