"Sn_TX_RD", "Sn_TX_WR" and "Sn_TX_FSR" reading problem [W5500]

Before any question excuse me for my English. My language isn’t English.
I want to write a simple test code for W5500 with Arduino Due. W5500 works as a client and
my PC works as a server. The code saves a character in TX buffer and sends it to my PC.
My code performs the following tasks:

  • loading common registers with appropriate values
  • opening the socket0 in TCP mode
  • connecting to server
    until here all things are perfect, but when i run send command (Sn_CR=0x20), the server receives arbitrary bytes. I perform updating process of Sn_TX_WR with respect to data sheet.
    Also, according to W5500 data sheet after connecting to server in TCP
    mode, the value of Sn_TX_RD and Sn_TX_WR will be re-initialized to 0x0000.
    But when i read these registers after connect command (Sn_CR=0x04), W5500 returns arbitrary numbers for both and these values are same for these registers. Also the value of Sn_TX_FSR
    reads as 0X0800 which is correct.
    When i read these registers after send command (Sn_CR=0x20), W5500 returns 0x0000 for
    Sn_TX_WR and Sn_TX_RD and an arbitrary number for Sn_TX_FRS.
    I don’t know where is the problem. Can anyone help me???
    Thanks in advance.

What software is acting as a server on your PC, and how do you know the problem isn’t there?

The problem solved!
A little mistake in writing to tx buffer.
But i wondering why W5500 returns an arbitrary numbers for Sn_TX_RD and Sn_Tx_WR registers after connecting to server?
Server software on pc is a simple c code downloaded from internet and has been tested.
Thanks for your reply.

These shoud be an arbitray number because TCP packet have sequence number and it can be hacked if the number is exposed easy to see.

Thank you.

Hi, I have same problem now…!
When sending string to a server I get a lot of “garbage” with the string.
Reading getSn_TX_FSR before sending give 800h (2048) as expected but after sending the value is “strange” and not what I expect (2048 - string lengh)…
What was the writing mistake? can you share it?
Any Idea?
Dan Groswirth

Hello Dan1.

I done the following steps to send data to my pc:

1- Reading start address of free space of TX buffer (Sn_TX_RD0 & Sn_TX_RD1).

2- Writing data to socket0 TX buffer in address which reads from previous step.

3- Updating S0_TX_WR register as follow:

S0_TX_WR  = S0_TX_RD0 * 256 + S0_TX_RD1 + data_size

4- Running socket send command.

I hope this be useful. I will be glad if i can help you.

Hello e_sh:
Thanks for your response. The way you suggest to update pointer is not documented as far as I know. I have not seen it in any of the examples I have seen.
Dont understand the " (Sn_TX_RD0 & Sn_TX_RD1)" that you mentioned. I use Sn_Tx_WR to get the pointer to writing location, as done at the send() rutine in socket.c file.
Please explain your idea .

I wrote my code without any library hence i manipulate registers directly.
According to datasheet “Sn_TX_RD0 & Sn_TX_RD1” are high byte and low byte of pointer, respectively.
More details on what i do:
I read the registers 0x0022 and 0x0023 in socket register block. These registers indicate the start address for writing your data in TX buffer.
Then i saved my data (for testing purpose i saved chatacter ‘a’) in TX buffer at address “Sn_TX_RD”.
After these the Sn_TX_WR pointer must be updated as i mentioned in previous post.
finally i issued the send command.
what i discribed is mentioned in pages 54 and 55 of W5500 datasheet version1.0.9.
Following is the piece of code related to these steps:

//Reading start address of free space of TX buffer
PIOA->PIO_CODR = 1 << SS_PIN; // select slave
S0_TX_RD_0 = SPI_transfer(0x00);//data
S0_TX_RD_1 = SPI_transfer(0x00);//data
PIOA->PIO_SODR = 1 << SS_PIN; // deselect slave

//Writing data to socket0 TX buffer
PIOA->PIO_CODR = 1 << SS_PIN; // select slave
PIOA->PIO_SODR = 1 << SS_PIN; // deselect slave

//Updating S0_TX_WR register
data_size = 1;
S0_TX_WR = S0_TX_RD_0 * 256 + S0_TX_RD_1 + data_size;
PIOA->PIO_CODR = 1 << SS_PIN; // select slave
SPI_transfer((S0_TX_WR >> 8) & 0xFF);//data
SPI_transfer(S0_TX_WR  & 0xFF);//data
PIOA->PIO_SODR = 1 << SS_PIN; // deselect slave  

//Socket0 sending
PIOA->PIO_CODR = 1 << SS_PIN; // select slave
PIOA->PIO_SODR = 1 << SS_PIN; // deselect slave

Best regards.

Hello e_sh:
Thanks again for your support.
I am getting into your code in order to understand the lower level of the handling of the appropriate registers…
You read TX_RD to set the writing address while W5500 library show reading TX_WR
as in that code:
//writing data to TX buffer
void wiz_send_data(uint8_t sn, uint8_t *wizdata, uint16_t len)
uint16_t ptr = 0;
uint32_t addrsel = 0;

if(len == 0) return;

ptr = getSn_TX_WR(sn); //<<<<<<setting the pointer

addrsel = ((uint32_t)ptr << 8) + (WIZCHIP_TXBUF_BLOCK(sn) << 3);
WIZCHIP_WRITE_BUF(addrsel,wizdata, len);

ptr += len;
I still confused about handling the TX_WR and TX_RD pointers as I have problem
that data I send is seen on server wrapped by “endless” garbage bytes and written several times…

Hi Dan1.
Yes. The code is written for W5500.
According to description of Sn_TX_RD in datasheet (page 54):

SEND command transmits the saved data from the current Sn_TX_RD to the Sn_TX_WR in the socket n TX buffer. After transmitting the saved data, the SEND command increases the Sn_TX_RD as same as the Sn_TX_WR.

Hence, i think in the “wiz_send_data” routine, at line :

ptr = getSn_TX_WR(sn); //<<<<<<setting the pointer

the Sn_TX_RD and Sn_TX_WR registers have the same value.
Are you sure about your code on server side?
Thank you.

Thanks, a little late…
I got it now alright. I have read both pointer at every step and learnt the way it treated…