RX_RSR/RX_RD value is abnormal

I am in trouble,so Advice please.

Set RMSR=0x55 2K memory assign each 4 sockets.
I am using TCP.

I think Sn_RX_RSR/Sn_RX_RD is 2K at the maximum.
Most of it is less than 2048(0x0800), but rarely it exceeds 2048.
For example 0x66A9 and so on will be unrelated figures.
When that happens, I put a large number in the Windows Size in the ACK and the reception fails.
Clipboard02

What factors can cause such numbers to come in?

Please share related Wireshark log.

Hi Eugeny, Thank you for your reply.

Attach the requested file.
The IP address of w5100 is 192.168.10.100.
Please filter with tcp.port == 2111.

Packets 47 to 268 are normal communication data.
Packets 1836 to 1955 are abnormal communication data.
Two of communication is using the same data.
In case of abnormality, large amounts of data are sent at once and can not be received.

Please say anything if you need more information.
Thanks for your help.

senderr.zip (84.1 KB)

I do not see [SYN, ACK] response from the W5100 which must follow [SYN].

I am not sure, but it may happen that you mess the RX pointer - for example just after connect you get RX pointer 0, received size of 2048. You copy 2048 bytes from buffer, and set RX_RD pointer to 2048. Then you receive 2048, get the new data, but for some reason update RX_RD not with 4096, but with 32347 (or some other wrong number out of the data you can get from the buffer).

I recommend you making log of the sizes you receive and pointers you update with. Note that RX_RD pointer is full 16 bit, and you must treat bits [15:12] properly.

Hi Eugeny.

I got a log.
RSR and RD are register raw values.
Mask with 0x7FF when using.

On success, it is a multiple of 0x0400 except the last packet.
I think that 1631 of RD is 0x6000 of the sum of 1630 0x0400 of RSR and 1630 0x5c00 of RD, but it is actually different.

Then you receive 2048, get the new data, but for some reason update RX_RD >>not with 4096, but with 32347.

I think that the phenomenon pointed out is occurring, but how should I respond?

1631: RX_RSR can not be 24897 because RX buffer size is only 2K. Check register reading routine. Is this value displayed just after you read the register (maybe you perform some math operations modifying the value before displaying?)

Also RX_RD does not look proper - 23552+24897 does not equal to 65215.

Please post your receiving code.

Can you also perform dump of all registers - common and related socket registers - when you encounter RSR of > 2048?

I will attach an excerpt code of the receiving part.
w5100 connected by a bus.

Is this value displayed just after you read the register

Yes, The last log is obtained by getSnRxRd, getSnRxRsr at the time of reception.
No operations, Direct register value.

Can you also perform dump of all registers - common and related socket registers - when you encounter RSR of > 2048?

I will try.

recv.zip (878 バイト)

If you would log direct value it would be big-endian. From your code I see there’re several move, AND and shift operations are applied. Log direct values read by REGS[ sn ].RX_RSR.WORD and REGS[ sn ].RX_RD.WORD. Does your implementation read byte at offset +0 first, and then byte at offset +1, or vice versa?

There’s no setSnRxRd() and WAIT_ENDPROCESS() in the code.

Else condition for if(0 < recLen) in recv() is wrong - even if socket is closed at the time you read socket status, it does not mean that nothing was received into W5100 buffer after you last time checked for the RX_RSR being 0 and before status read. You must check for RSR being 0 once more, and flush remaining data of there’s any data.

What is the value of W5100_RX_BUFF_SIZE? According to comment, must be 0x800.

So:

  1. log register values just before they are being written or just after they are being read;
  2. check which order bytes in word read are being read;
  3. correct recv in its else condition;
  4. perform dump of all registers as asked before, byte by byte.

Does your implementation read byte at offset +0 first, and then byte at offset +1, or vice versa?

Log value is
0x0426 0x0427
0x08 0x00
I am reading it as shown in W5100 Datasheet V1.2.7 Page.36.
getRxRsr and getRxRd return the calculated value.

There’s no setSnRxRd() and WAIT_ENDPROCESS() in the code.

sorry. It was missing last time. So added this time.

perform dump of all registers as asked before, byte by byte.

I get dump.Please confirm the attached file.
receive error is occurring at socket4.

Else condition for if(0 < recLen) in recv() is wrong

I checked again and added a bit of correction.

data.zip (8.1 KB)

I can not open BIN file. It should be text file with readable values of the registers.

I have better suggestion: replace

if ((status == Sn_SR_LISTEN) || (status == Sn_SR_CLOSED) || (status == Sn_SR_CLOSE_WAIT))

with just

if (status != Sn_SR_ESTABLISHED)

as chip will normally receive data only when connection is established. There’s small exception though - when remote device has sent FIN packet, SR will change to SOCK_CLOSE_WAIT, and then your recv function will return 0 (however W5100 is still allowed to send data).

Thank you, problem is solved.
The cause was a simple mistake.

When observing RX_RD carefully, we rarely set unintended values.
The reason was that I used one rxPtr with 4 sockets.

rxPtr = getRxRD(socket_number);
rxPtr += recv_size;
setSnRxRd(socket_number, rxPtr);

during reception of socket 4, interrupt reception of socket1(higher priority) occur,
rxPtr is unintended values.
So I fixed it as follows.

rxPtr[socket_number] = getRxRD(socket_number);
rxPtr[socket_number] += recv_size;
setSnRxRd(socket_number, rxPtr[socket_number]);

This correction no longer causes abnormal RX_RD values.
Thank you for much cooperation.

1 Like