WIZnet Developer Forum

W5500 - Need help with UDP Rx buffer pointer wrap-around

Hi,
I am working with the UDP protocol setting. I am able to receive UDP packets correctly until the Sn_RX_RD pointer reaches the end of the 2K RX buffer (I’m using the default 2K, and using Socket 0). Here is the pseudocode of what I am doing:

rx_len = getSn_RX_RSR() // get packet, returns when non-zero rx_len
rx_ptr = getSn_RX_RD() // get Rx pointer
buffer = readData(rx_ptr) // read data at pointer address
rx_ptr += rx_len // calculate new pointer
if (rx_ptr > 0x07ff) // check for wrap-around
rx_ptr -=0x07ff
setSn_RX_RD() // update pointer
setRECV() // notify receive complete

It works up until the next packet that arrives after the wrap-around. When that packet arrives, the getSn_RX_RSR() function returns 0x07ff and “gets stuck” at 0x07ff. So the W5500 reports that a packet is continuously arriving with length 0x07ff.

Any hints on how to handle the wrap-around logic – or perhaps it is something else I’ve missed?
Thanks, Richard.

Take a look into W5100 datasheet pages 44-45. You must use all 16 bits of the pointer to update RX_RD, while for actual data pointing you must use window-masked pointer.

Thanks Eugeny. I took out my wrap-around logic and implemented the 2K mask (0x07FF) on the offset address when reading as you suggested and it works now :).

A question about the purpose of Sn_RX_WR: can/should the value of this register be used to calculate the new Sn_RX_RD pointer instead of adding the received packet length (e.g., rx_ptr = getSn_RX_WR())? I’m not sure of the value of doing this, but just wondering what Sn_RX_WR is for.

Here is the updated pseudocode:
rx_len = getSn_RX_RSR() // get packet, returns when non-zero rx_len
rx_ptr = getSn_RX_RD() // get Rx pointer
rx_ptr_masked = rx_ptr & 0x07FF // mask assumes 2K RX buffer
buffer = readData(rx_ptr_masked, rx_len) // read data at masked pointer address
rx_ptr += rx_len // calculate new pointer value. Or…could use rx_ptr = getSn_RX_WR()?
setSn_RX_RD(rx_ptr) // update pointer
setRECV() // notify receive complete

No. RX_WR is being used by the chip internally, and can change in any moment, and the value you read may be just invalid (because value in register may change between reads of two bytes). You must do exactly as described in the datasheet, even if it looks not the easiest way to proceed.

Copyright © 2017 WIZnet Co., Ltd. All Rights Reserved.