---
title: "\"Sn_TX_RD\", \"Sn_TX_WR\" and \"Sn_TX_FSR\" reading problem [W5500]"
url: "https://maker.wiznet.io/forum/13703"
markdown_url: "https://maker.wiznet.io/forum/13703/md"
type: "Forum topic"
category: "Ethernet Chips"
author: "e sh"
created: "2020-02-14T12:11:06+09:00"
last_activity: "2020-06-06T17:53:25+09:00"
language: "en"
views: 1302
replies: 9
source: "WIZnet Makers forum (https://maker.wiznet.io/forum/)"
---

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

## Question

Asked by e sh on 2020-02-14 in Ethernet Chips.

Hello.
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.

## Replies

### Reply 1 by Mxyxixptlick, 2020-02-15

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

### Reply 2 by e sh, 2020-02-15 (in reply to reply 1)

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.

### Reply 3 by Dan1, 2020-06-03

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
[cellkey.tech.gmail.com](http://cellkey.tech.gmail.com)

### Reply 4 by e sh, 2020-06-03 (in reply to reply 3)

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.

### Reply 5 by cellkey, 2020-06-03

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 .
Thanks
Dan

### Reply 6 by e sh, 2020-06-04 (in reply to reply 5)

hi
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
SPI_transfer(0x00);//address
SPI_transfer(0x22);//address
SPI_transfer(0b00001000);//control
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
SPI_transfer(S0_TX_RD_0);//address
SPI_transfer(S0_TX_RD_1);//address
SPI_transfer(0b00010100);//control
SPI_transfer('a');//data
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(0x00);//address
SPI_transfer(0x24);//address
SPI_transfer(0b00001100);//control
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
SPI_transfer(0x00);//address
SPI_transfer(0x01);//address
SPI_transfer(0b00001100);//control
SPI_transfer(0x20);//data
PIOA->PIO_SODR = 1 << SS_PIN; // deselect slave
```

Best regards.

### Reply 7 by Dan1, 2020-06-04

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); //&lt;&lt;&lt;&lt;&lt;&lt;setting the pointer

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

ptr += len;
setSn_TX_WR(sn,ptr);
}
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…
Regards
Dan

### Reply 8 by e sh, 2020-06-04

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); //&lt;&lt;&lt;&lt;&lt;&lt;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.

### Reply 9 by cellkey, 2020-06-06 (in reply to reply 8)

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

---

Source: https://maker.wiznet.io/forum/13703
