There’re three locations within the chip:
RD: location of the “user” pointer - the data which application must read;
WR: system pointer, the location where the chip’s network stack writes when data arrives;
RSR: it is simply WR-RD, and it can not be larger than RX buffer size.
Note that all registers are 16-bit, and must be treated as 16-bit values even if buffer size is 8KB.
Thus you do not touch WR under normal circumstances, it is managed by the chip. You only look at the RSR - amount of data received into the RX buffer, and at RD - the location to start reading data from.
Thus if you read RSR, and it appears 0 - this means that buffer is empty, there’s no data to read, and chip must respond with full window size free in its network packets.
Logically, if RSR is not 0, then RD is not equal to WR. Maximal value of RSR is RX buffer size.
When you write to RD pointer new value, and then issue RECV command, chip assumes that data between old RD location and new RD location is flushed by the application, and considers this space as available for new incoming data.
Therefore reading RSR, then assigning RD=RD+RSR and then RECV “frees” RSR bytes in the RX buffer, and decreases current value of RSR by RSR when it was previously read. Note that while you perform reading of RSR, then RD, then performing RD+RSR and assigning it back to RD time has passed, and actual RSR register value may increase. But it does not matter because RSR you originally read will always be <= current RSR, and there will be no buffer overrun, next time you read RSR you will get “remaining” value of RSR.
Then, very important note: when reading any 16-bit register (RD or RSR or anything else) you must read byte at +0 first, and byte at +1 second. Not critical for RD because it will not change dynamically without your RECV instruction, but very critical for RSR: when reading +0 first and +1 second you will be guaranteed to get value equal or less than current, and will never overrun the buffer. If you read other way around, you may get value bigger than current RSR, shifting RD ahead of WR with RECV command, and it will mess whole communication.
Right order: you read 0x01 first, then RSR changes to 0x0200 (one more byte was received), and you read 0x00. Thus you have RSR=0x100, which, while is not “immediately correct”, should give you amount of bytes less than in the buffer, and on next read RSR will read as 0x100 and finally you will read all the data from the RX buffer.
Wrong order: you read 0xFF first, then RSR changes to 0x0200, and you read 0x02 for MSB. So you end up with RSR=0x02FF, and crash the socket communication.
I hope it is clearer now, and you can find at least the area for further investigation yourself - as I do not fully understand what is going within your design. You clearly do something incorrectly, but hard to say what it is exactly.