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?