WINC1500 Partial Socket Receive Calls

Go To Last Post
4 posts / 0 new
Author
Message
#1
  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I am wondering how I can do partial socket receive/read calls, just like normal TCP sockets.

 

Let's say I connect to a server and then write some data. I then make a receive call, and have a buffer of 100 bytes. With normal sockets like on a PC, I could say, receive the 100 bytes, and it would give me up to 100 bytes maximum. I could then go do something else, come back in a little while and as long as the connection was still open, receive some more data into my buffer. This is expected, and is similar to the way you read a file.

 

On the WINC1500 however, it will receive the 100 bytes, and then I will keep getting successive interrupts as it receives the next 100 bytes into the same buffer and so on until the entire message is received. Is there an easy way to make this stop after my first n number of bytes? Maybe it's just as simple as somehow aborting the receive call after the first interrupt occurs. I can dig into it more but thought I would ask here first before going too far.

 

Thanks.

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

You've stumbled over what I think is the single biggest drawback of Atmel's WINC1500 API. If you post a 'recv' with a buffer size of, say, 100 bytes, and the device receives 1000 bytes of data then your recv callback will be invoked 10 times one after the other for each chunk of the data. There is no way to flow control this, you must consume all the data each time your callback is invoked. There's no way to say "just give me the first 50 bytes for now and I'll ask for the rest later".

There's no way to ask how many bytes are waiting to be read. It's all or nothing.

So the only way to deal with this is to post recvs into bounce buffers of size M2M_BUFFER_MAX_SIZE. Yep, that's 1596 bytes per socket. You can then write some code to hand out chunks of the bounce buffer to your application then post another recv when it's empty.

Really sucks on the smaller AtMega/XMega devices...

 

 

Maverick Embedded Technologies Ltd. Home of wAVR and Maven.

wAVR: WiFi AVR ISP/PDI/uPDI Programmer.

Maven: WiFi ARM Cortex-M Debugger/Programmer

https://www.maverick-embedded.co...

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

Agreed that is a real disadvantage, thanks for the quick reply, this isn't the end of the world for my use, at least the buffer isn't bigger haha

  • 1
  • 2
  • 3
  • 4
  • 5
Total votes: 0

I know this thread is about a year old, but did anyone find a workaround for this problem?

Digging around in the (now Microchip) standard firmware, I find as follows:

 

The core issue is that the Host Interface command to read from the WINC1500 does not have any kind of length parameter - essentially it is a "give me all you've got" style command.

So the recv() call, creates a transaction over the SPI interface using the verb SOCKET_CMD_RECV (wf_socket_internal.h, line 37), the result of which is a single transaction coming back which contains all data received on the socket prior to the call (I'm unclear on what this maximum is, but the maximum size of the host buffer seems to be stated as 1,600-4 = 1596 bytes at line 62 in wf_drv.h).

As implemented in wf_socket.c, there is a do-loop in ReadSocketData which issues as many hif_receive calls as needed to consume the data, passing each read up through a callback in chunks defined by the size of the buffer in the recv() call from the application layer.

It should - in principle - be possible to carry out a single round of hif_receive, save the context of the transaction then yield processing to the application task so that it has a chance to consume some of the data before calling recv() again.

When that happens, recv() would issue another hif_receive call, picking up where the last one left off.

HOWEVER...

While that is going on the host interface can't be used for anything else, so some decisions have to be made as to how to handle further calls to the socket layer.

For my application (which is just to serve a few very simple web pages), it is probably OK simply to return a brute force error such as SOCK_ERR_BUFFER_FULL for any attempts to call bind(), listen(), or send/sendto().

 

I intend to have a go at implementing this after Christmas (Holiday).

In the mean time, if anyone else has other (sensible) suggestions, please feel free to make them.

Thank you in advance,