W5200 Changing Buffer Size
JohnC
Posts: 64
Hi,
I'm working through the W5200 quickstart files and need to make some changes.
It appears that the default buffers are 2K each for rx/tx, on each of 8 available sockets.
For this application, I'm receiving large (~550 byte) UDP packets which arrive in groups of 4-6, spaced only a few microseconds apart. These packet bursts are repeat every 20 mS or so.
So the 2K buffers are overrunning and I'm losing packets.
When the dust settles, I'd love to have something like this:
Socket 0 TX 2K
Socket 0 RX 8K
Socket 1 TX 2K
Socket 1 RX 2K
I've made these changes to the constant section of W5200.spin:
... but it seems like I've missed something else.
Ideas?
John
I'm working through the W5200 quickstart files and need to make some changes.
It appears that the default buffers are 2K each for rx/tx, on each of 8 available sockets.
For this application, I'm receiving large (~550 byte) UDP packets which arrive in groups of 4-6, spaced only a few microseconds apart. These packet bursts are repeat every 20 mS or so.
So the 2K buffers are overrunning and I'm losing packets.
When the dust settles, I'd love to have something like this:
Socket 0 TX 2K
Socket 0 RX 8K
Socket 1 TX 2K
Socket 1 RX 2K
I've made these changes to the constant section of W5200.spin:
{{ Socket Buffer Defaults }} INTERNAL_RX_BUFFER_ADDRESS = $C000 INTERNAL_TX_BUFFER_ADDRESS = $8000 DEFAULT_RX_TX_BUFFER = $1000' $800 DEFAULT_RX_TX_BUFFER_MASK = DEFAULT_RX_TX_BUFFER - 1 SOCKETS = 2 '8
... but it seems like I've missed something else.
Ideas?
John
Comments
IMO, the W5200 API is challenging when dealing with the socket buffers. It is not enough to simply assign a value of 8k to a buffer. The host controller must know the boundaries of the W5200s circular buffers. Otherwise the controller will not know when a buffer rolls over. This situation creates a dependency between the logic running in the controller and the W5200. Your case is special as there's only enough buffer resource to create 3 sockets from a potential 8.
The key is reading the W5200 manual related to buffers. Reading the whole thing does not hurt...
Next, tackle the W5200 SPIN code. the snippet below comes from the CON, VAR and program sections of W5200.spin
Looking at the SetDefault2kRxTxBuffers method
Unroll the REPEATs to create a customer buffer scheme.
Just to confirm - in your last |code| section should the Masks and Bases be in $hex or plain decimal? I'd think that something like
SockRxMask[0] := 2048 - 1
SockTxMask[0] := 8192 - 1
...would be better?
Everything was running along nicely, and I was receiving at ~ 86 Kbytes per second, sustained, over about half an hour. So that made me happy. I was flipping a pin after a packet was received, then again after it was processed (basically, error checked, then copied to a different local buffer). Averaged out to .5 mS per packet. So the main SPIN loop seems to load the cog to about 15% of capacity. Lots of room to expand here.
Occasionally (maybe representing 1-2% of all packets received) when calling Sock.Available, returned would be a number representing a partial packet. And then, the next call to .Available would return the balance due. If the correct packet size was 550 bytes, I'd receive 518 and then 32, for example. Data isn't being lost, it's just packaged oddly.
Wireshark confirms that every packet being sent the Wiznet chip is the exact same length. So I need to do more poking around to see what might be causing this. For now, if .available returns an odd number, I just dump the current and subsequent packet, then continue on.
For reference, the RX buffer is set to 4K, and the maximum payload within one of the 'bursts' I ever receive is four packets comprising about 2400 bytes.
Is this sort of packet-splitting behavior something to be expected?
I had a similar issue downloading large files (20M) using TCP.
Socket.DataReady also reads the socket(n) receive size register but does NOT block.
Socket.Available does not resolve itself.
Socket.Available and Socket.DataReady report the bytes in the Rx buffer. The methods do not guarantee an intact packet framed in the buffer. It's possible to read once and see a partial packet. Read again and see one full packet and the beginning of the next packet.