W5200 TCP Client - Data arrives corrupted

Best regards:

I am using a Xmega and W5200, I have created a TCP Client with the W5200 and my PC is the server. When I press a button, I send a constant string to the server but the data arrives are random. After trying several times, the data arrives correctly and continues like this for about 50 more times and then the data arrives incorrectly and the loop is repeated. Sometimes after connecting the power the data reaches the server correctly but sometimes it does not.
When I send from the server to the W5200 the data always arrives correctly.
Code after connection is established:

uint16_t Sn_TX_WR0, dst_mask, size;
uint8_t * dst_ptr;

Read_W5200(BufferW5200, Sn_TX_WR, 2);
Sn_TX_WR0 = ((uint16_t)BufferW5200[0] << 8) + BufferW5200[1];
dst_mask = (uint32_t)Sn_TX_WR0 & gS0_TX_MASK;
dst_ptr = (uint8_t *)(gS0_TX_BASE + dst_mask);
if((dst_mask + nbytesBufferTxTCP) > ((uint32_t)gS0_TX_MASK + 1))
{
	size = ((uint32_t)gS0_TX_MASK + 1) - dst_mask;
	Write_W5200((uint8_t*)BufferTxTCP, (uint16_t)dst_ptr, size);
	BufferTxTCP += size;
	size = nbytesBufferTxTCP - size;
	dst_ptr = (uint8_t *)(gS0_TX_BASE);
	Write_W5200((uint8_t*)BufferTxTCP, (uint16_t)dst_ptr, size);
} else{
	Write_W5200((uint8_t*)BufferTxTCP, (uint16_t)dst_ptr, nbytesBufferTxTCP);
}
Sn_TX_WR0 += nbytesBufferTxTCP;
BufferW5200[0] = (Sn_TX_WR0 & 0xFF00) >> 8;
BufferW5200[1] = Sn_TX_WR0 & 0x00FF;
Write_W5200((uint8_t*)BufferW5200, Sn_TX_WR, 2);
BufferW5200[0] = SEND;
Write_W5200((uint8_t*)BufferW5200, Sn_CR, 1);

Before to send when data is corrupt (info UART) …

nbytesBufferTxTCP = 001B
Socket 0 TX Free Size (Sn_TX_FSR0_1) = 2000
Socket 0 TX Read Pointer (Sn_TX_RD0_1) = 482C
Socket 0 TX Write Pointer (Sn_TX_WR0_1) = 482C
dst_mask = 002C
dst_ptr = 802C
(dst_mask + len) = 0047
BufferTxTCP = ALC10|948310257846825|40|1|
Reading TX buffer in 804A: ALC10|948310257846825|40|1|

After to send when data is corrupt (info UART) …

Socket 0 TX Free Size (Sn_TX_FSR0_1) = 2000
Socket 0 TX Read Pointer (Sn_TX_RD0_1) = 4847
Socket 0 TX Write Pointer (Sn_TX_WR0_1) = 4847

Before to send when data is OK (info UART) …

nbytesBufferTxTCP = 001B
Socket 0 TX Free Size (Sn_TX_FSR0_1) = 2000
Socket 0 TX Read Pointer (Sn_TX_RD0_1) = 204F
Socket 0 TX Write Pointer (Sn_TX_WR0_1) = 204F
dst_mask = 004F
dst_ptr = 804F
(dst_mask + len) = 006A
BufferTxTCP = ALC10|948310257846825|40|1|
Reading TX buffer in 804A: ALC10|948310257846825|40|1|

After to send when data is OK (info UART) …

Socket 0 TX Free Size (Sn_TX_FSR0_1) = 2000
Socket 0 TX Read Pointer (Sn_TX_RD0_1) = 206A
Socket 0 TX Write Pointer (Sn_TX_WR0_1) = 206A

I read the data written in the TX buffer before the send command and I verify that the data is in the correct position and the data is also correct, but sometimes this data arrives at the server changed but the number of bytes does match.

I attach an image of wireshark and hercules when the data is corrupt and when the data is OK.

Any suggestion?
Thanks.

EP.

Do you wait for socket’s send command completion (by waiting for CR to become zero) before doing anything else with the socket?

Yes, in the code I did not copy it but before send command I clear interrupts:

Sn_TX_WR0 += nbytesBufferTxTCP;
...
BufferW5200[0] = 0;
Write_W5200((uint8_t*)BufferW5200, Sn_IR, 1); // Clear interrupts
BufferW5200[0] = SEND;
Write_W5200((uint8_t*)BufferW5200, Sn_CR, 1);
...
loop:
 Read_W5200(BufferW5200, Sn_IR, 1);
 I wait ... " SEND_OK " 
...

In my log-UART I verify Sn_CR = 0 before send process.

What I don’t understand is why in the dst_ptr address I read (only for check) the buffer that I just wrote in the TX memory and it’s OK but altered data arrives on the PC server.

The question I asked is:

and you answered some other question.

When I send the command SEND(0x20) to Sn_CR I wait until interrupt occurs (bit SEND_OK of Sn_IR), In this way I know that the SEND command is completed and so I can just send a new package.

Also, every time I send a package (just before the send process), I monitor the most important registers like Sn_CR and I always read Sn_CR=0.

In addition, to this action, put a check for CR being 0, do it just after SEND command is issued.

I have added the check Sn_CR=0 just after SEND command and also added just before start send process but still the same.

As I said sometimes I disconnect the power supply and re-feed the board and the data starts to arrive correctly to the server, but sometimes the data arrives wrong.

Maybe it’s my initialization process? My initialization TCP Client:
RST_pin_LOW
delay 1ms
RST_pin_HIGH
delay 1second
set SHAR, GAR, SUBR, SIPR, Sn_PORT, Sn_MR=TCP, Sn_CR=OPEN
wait SOCK_INIT
set Sn_DIPR, Sn_DPORT, Sn_TXMEM_SIZE=0x0800, Sn_CR=CONNECT

if( SOCK_ESTABLISHED && Sn_CR==0)
send_process

Good, so it is not a SEND commend process being corrupt.
I did not find any problem in the code.
Increase reset low to 1 second as a test.

Assuming you write proper value into the respective register (0x2 into 0x401f). As a test, please remove the code modifying memory size registers (as you set it to the default value of 2k) and see if it will change anything.

Can you identify any pattern in the data corrupt and in the regularity of the data corruption? Send one fixed string and log everything coming from the W5200, get significant amount of data and then analyze the patterns. For example - corrupt data is always corrupt in the same manner, corruption always happens in fixed period.
You can even send not just arbitrary text, but specific information - e.g. send pointers and data amount being sent so that you can check then at another end (in PC log).

1 Like

I finally found the problem and thank you so much for helping me find it Eugeny. I was writing to the Sn_TXMEM_SIZE the value 0x0800 (2K) instead of 0x02 (uint16_t instead of uint8_t). Now, after connecting and disconnecting several times the board, the data arrives correctly to the server.

Thank you very much dear friend Eugeny.

1 Like