W5100 in server mode... host uP buffer overflow

I’m using a WIZ811MJ with a combination of direct and indirect interfacing to an Atmel UC3B0512 using GPIO. All this works fine, I switch to Indirect when I want to empty the Receive buffer, all good. I have a simple test application that sends 2mB (32kB each Send() cmd) via Visual Studio 2010 to socket 0 on the W5100… I’m only using Socket 0, and I have it configured to use all 8K RAM for socket 0. I have 32kB set up for a buffer on my UC3B. I’m using interrupt control, not polling (example code doesn’t exist for interrupt!).

If I breakpoint my VS2010 application on the send() and step it one at a time everything works great. When I go faster than about 100mS I get a buffer overrun on my UC3B… what’s happening is the last packet of the 32kB is actually bigger than it’s supposed to be, overflowing the buffer into space above it. I’ve configured a spare buffer space there, and I catch the >0x8000 condition and deal with it clumsily (memcpy into the lower buffer after I use the data)… then I set my buffer pointer to the new position instead of 0 and carry on.

So the problem may not be with the W5100, but with my understanding of TCP… when I tell VS2010 to send(buffer, 32K) the send() statements seem to run together. I’m setting blocking mode (normally default) for these transactions and I can watch the interrupt line stop banging when I break the UC3B, so the send() is blocking as it should… the W5100 doesn’t re-do the interrupt until I send the RECV command back to it (or, it never lets up the /INT line, in which case I loop in the ISR until it does).

So… the previous send() (from PC) is processed, but if the next RECV (W5100) is not sent, the next send() will continue to fill the RECV buffer? I haven’t been able to find any kind of flow control solution that helps, aside from catching the overflow and dealing with it. Here’s part of my ISR:

case WIZ_SOCK_ESTABLISHED:
	// see if there's a client request by querying the size... if size, then retrieve and process it
	size = receive_size();
	if (size > 0)// there is data waiting in the buffer
	{			
		// get the recieve buffer pointer to the current position in RX RAM
		get_data_at_address(WIZ_S0_RX_RD0,&data);
		rawOffPtr = data<<8;
		get_data_at_address(WIZ_S0_RX_RD1,&data);
		rawOffPtr += data;
		offPtr = rawOffPtr & WIZ_MAXBUF;// go in a circle
		// need to take care of the receive now... is it a command, or data?
		if (receiveState == COMMAND)
		{
			buf_ptr = 0;// as good a place to do this
			process_data(commandBuf,size,offPtr);
			commandState = WAITING;	
		}
		else
		if (receiveState == DATA_RECEIVE)
		{				
			process_data(&buf_test[buf_ptr],size,offPtr);// we just got some data
			buf_ptr += size;// accumulating data
			dataCount += size;
			
			if ((buf_ptr >= 0x8000) || (dataCount >= transferSize))// if full cluster or file end
			{			
				write_card();// first of buffer is OK
				if (buf_ptr > 0x8000)// we overflowed
				{
					buf_ptr -= 0x8000;// overflow amount, leaves this set correctly for next packet
					// write overflow (in buf_test2) to buf_test
					memcpy(buf_test,buf_test2,buf_ptr);	// circular buffer probably better here... try this for now					
				}
				else
					buf_ptr = 0;// get ready for another buffer full					
			}
		}

		rawOffPtr += size;// advance circular buffer
		put_data_at_address(WIZ_S0_RX_RD0,(rawOffPtr & 0x0000FF00)>>8);
		put_data_at_address(WIZ_S0_RX_RD1,(rawOffPtr & 0x000000FF));
							
		// give recv command to reload offPtr allow the next packet to come in
		put_data_at_address(WIZ_S0_CR,WIZ_CR_RECV);		
		
	}
	
		
	break;

… and here’s the relevant piece of my VS source:

while (sizeReceived < 0x200000)
{
iResult = send(ConnectSocket, text32768, 32768,0);
DWORD getLastError;
packetCount++;
Sleep(1);

}

… the Sleep() has to be 100 before it will run without overflow. Shouldn’t TCP just send blocks in 32Kb increments? Or is the extra data happening inside the W5100?

OK… no help… I’m guessing that in order to force TCP to break this data into 32K chunks I have to disconnect and reconnect for every block? As long as the socket’s open then data will pour into the buffer with no regard to the size of the Winsock send()? I’m reading the documentation for the W5300 and I now understand that when I send the RECV statement this is actually setting the receive window for the next TCP packet… so what I should do is only set the pointer to allow the window to complete the 32K on the next-to-last packet. Then I have to remember to put this space back in when the final packet comes in so the process can repeat. I’ll try this and repost later.

Never mind… we’ve decided to go with a different solution.