W5500 Socket TX Buffer

I’m having issues transmitting data over SPI to the W5500 from a TI MSP430x chipset and having a correct send over TCP. I have the W5500 set as the server and connect to it using a simple python script as a client for testing.

I have a simple program on the MSP430x chip where I will read the current Sn_TX_WR register pointer value, translate this to ASCII and store it as 4-byte data value which I then pass to the Sn TX Buffer starting at Sn_TX_WR pointer address. I then increment the pointer by 4, write this into Sn_TX_WR, and then issue a ‘send’ command to the Sn_CR register. All of this happens whenever the python script acting as a client sends data to the W5500 socket over TCP (it likewise is sending a random 4-byte ASCII string).

My issue:
All of this works just beautifully for cases where the Sn_TX_WR register pointer is hex ‘x0xx’ or ‘x8xx’, in other words, whenever the third byte in the address is a ‘0’ or ‘8’. For any other address value, I seem to be unable to write to the TX buffer nor receive anything but garbage data over the TCP to my python test bench client.

example output from the TI MSP chip debug console:
txAddr: 0x60fb
txData[0]: 0x36 (6) txData[1]: 0x30 (0) txData[2]: 0x46 (f) txData[3]: 0x42 (b)
txAddr: 0x60ff
txData[0]: 0x36 (6) txData[1]: 0x30 (0) txData[2]: 0x46 (f) txData[3]: 0x46 (f)
txAddr: 0x6103
txData[0]: 0x36 (6) txData[1]: 0x31 (1) txData[2]: 0x30 (0) txData[3]: 0x33 (3)

And the corresponding output from the TCP as displayed from the python output (verified through wireshark):
b’60FB’
b’60FF’
b’\x05g\x96\xf2’

so you’ll see the first two transmissions are as expected, but the third the python client should have received ‘6103’ (or hex values 0x36 0x31 0x30 0x33) but instead received hex values 0x05 0x67 0x96 0xf2

If anyone has any clue as to why I’m only able to access and use 1/8th of the memory in the buffer I would be appreciative. It should be noted that the Sn_RX Buffer does not have this issue at all. Just the TX Buffer.

EDIT for clarification
I have tried setting different values for the TXBuffer size, anywhere from 1k to 16k. I am only using one socket.

Here is a snippet of my code used to transmit data to the socket TX buffer as well as print out the data seen in the TI MSP chip debug console:

void send_TCP(SPI_Handle* handle, char socket, uint16_t txSz, char* data) {
	char spiData[2], txRD[2], txWR[2], temp;
	uint16_t txAddr;
	char txData[4];
	int i;

	/* read 2 bytes from Sn_TX_WR register (0x0024 - 0x0025) */
    	spiSend(handle, Sn_TX_WR0, socket, REG, REG_READ, CTRL_LEN_2, (unsigned char*)txRD);

	/* store TX_WR current value as ptr address */
	txAddr = ((uint16_t)txRD[0] << 8) | (uint16_t)txRD[1];
	System_printf("txAddr: 0x%.4x\n",txAddr);
	System_flush();

	/* translate ptr address to ASCII and store in reverse order in data array */
	for(i=0;i<4;i++) {
		temp = (txAddr >> 4*(3-i))&0x000F;
		txData[i] = (temp <= 0x09)?(temp + 0x30):(temp + 0x37);
		System_printf("txData[%d]: 0x%.2x (%.1x) ",i,txData[i],temp);
	}
	System_printf("\n");
	System_flush();

	/* send data array to Sn TX Buf starting at ptr address */
	spiSend(handle, txAddr, socket, TX, REG_WRITE, CTRL_LEN_4, (unsigned char*)txData);

	/* increment ptr by transmit length (4) */
	txAddr += txSz;

	/* overwrite Sn_TX_WR registers with new ptr value */
	txWR[0] = (uint8_t) (txAddr >> 8);
	txWR[1] = (uint8_t) txAddr;
	spiSend(handle, Sn_TX_WR0, socket, REG, REG_WRITE, CTRL_LEN_2, (unsigned char*)txWR);

	/* send Sn TX data */
	spiData[0] = Sn_SEND;
	spiSend(handle, Sn_CR, socket, REG, REG_WRITE, CTRL_LEN_1, (unsigned char*)spiData);
}

Where’s address pointer masking to stay within the cyclical buffer? See W5100 datasheet chapter 5.2.1.1.

This doesn’t work. Maybe for 5100, not 5500. for some reason a wiznet team member forced this post over to the 5100 forum…

W5500 is listed in it’s data sheet as having a cyclical buffer for each socket that ranges from 0x0000 to 0xFFFF.
Plus, there’s no way to force the auto incrementation of the RX_WR or TX_RD register pointer values. These auto increment anytime the Sn_CR is given a RECV or SND command respectively.

I’ve looked at my issue further, and see that the Receive buffer is also an issue. It receives data from the TCP stack but only up until the RX_WR pointer auto-increments to 0x00FF. After that the RX buffer returns junk. RX_WR will continue to increment with ever receive over the TCP stack, but none of the pointer values return meaningful data. I did a full dump of the buffer, reading everything from 0x0000 to 0xFFFF and none of the data appeared to be valid for what was sent to the device over TCP. The only time it worked was when the RX_WR pointer was between 0x0000 and 0x00FF. It then worked again from 0x0800 to 0x08FF, and then every multiple of 0x0800 thereafter. But, I can’t force the RX_WR pointer to jump to that address… I just have to send it 1792 bytes of data to cycle it back around till it’s useful.

Masking doesn’t help with this.

Same as W5100. But it is twice larger (16k for W5100/4 sockets and 32k for W5500/8 sockets).

Did not get your point. First you said no auto increment, then say there’s autoincrement. This is how chip works, and it is logical behavior.

In overall it still seems something’s wrong with addressing. Is the first byte in the SPI transaction sent properly? If there’s an issue with it, you’d get similar 0x100 boundary issue.

Sorry, I meant that the registers do auto increment, and there is no way to jump to another address, you are forced to transverse the buffer linearly. My point is, that I can’t use masking to force reads or writes to a different area of the buffer, it must be accessed linearly, as read from the pointers listed in the RX_RD/WR and TX_RD/WR registers.

As to the SPI, I am pretty sure that the SPI byte transactions are proper as I am able to set the configuration registers for the chip and the socket, and then accurately receive data sent over the TCP for several transactions.

I suppose it remains possible, however, that there is something incorrect with the addressing used for reading and writing to the socket RX and TX buffers, though I would have expected the boundary issue to present itself differently. Still, at this point I don’t have many other options as to what might be incorrect.

Revise figure 20 in the datasheet and ensure you address what you need properly. You not only operate the address, you also operate block select bits. It seems I was not correct pointing you to W5100 and talking about cyclical buffer. W5500 implements it under the hood, and W5100 has it differently forcing programmer doing manual calculations. The remaining socket workflow is similar to W5100. Thus, if you address W5500’s TX buffer of socket 1 (for example) you can use 0-ffff addresses but set bsb to 6. This address 0-ffff will be internally masked to the buffer size and offset to its start in the global socket buffer map.